Docker ENTRYPOINT ضد CMD — وعَدَةُ صندوقك

تحديث في

أنت دمجت ENTRYPOINT و CMD في ملف Dockerfile، وبدأ الـ container بالشيء الخاطئ، ووصلت إلى هذا الموضع. إليك التحليل الكامل — كل التوافقات، الفخ في صيغة الشيل مقابل صيغة exec، والأنماط التي تعمل فعلاً.

مدخل دوكير ENTRYPOINT مقابل CMD — أخبرت وحدة الدوكيرك 1
إعلان · حذف؟

يحدث الخطأ عند الساعة 2 صباحًا. تبدأ علامة الـ container، وبدلاً من خادم API الخاص بك، تظهر لك نافذة تعليمية أو لا شيء على الإطلاق أو يُنفذ عملية مُغلفة في "الظل" sh الذي يأكل SIGTERM كالحلوى — لذا يستغرق التوقف المُناسب 10 ثوانٍ من انتظار Docker قبل أن يُنهي الأمر ويُرسل SIGKILL.

السبب، في كل مرة تقريبًا: كنت مُخطئًا في ENTRYPOINT و CMDأو جمعت بينها بطريقة تُقبلها Docker بصمت — لكنها ليست كما توقعها.

CMD: القيمة الافتراضية التي يمكنك استبدالها

CMD تُحدد ما يُنفذ عند بدء علامة الـ container — لكنها مجرد اقتراح، وليس قاعدة. إذا أضفت أي شيء بعد اسم الصورة، فإنه يُستبدل بالكامل:

FROM ubuntu
CMD ["echo", "hello from CMD"]
$ docker run myimage
hello from CMD

$ docker run myimage echo goodbye
goodbye

هذا echo goodbye لم يُرفق — بل تم استبداله. أصبحت كل شيء CMD مفقودًا. وهذا هو المقصود: CMD هو السلوك الافتراضي، وليس السلوك المُفرض. أي مُدخل تشغيل يُكسب.

ENTRYPOINT: الجزء الذي يُنفذ دائمًا

ENTRYPOINT يُحدد التنفيذ الذي يُنفذ بغض النظر عن أي شيء. لا يُستبدل المُدخل التشغيلي — بل يُمرر إليه بدلًا من ذلك:

FROM ubuntu
ENTRYPOINT ["echo"]
CMD ["hello"]
$ docker run myimage
hello

$ docker run myimage goodbye
goodbye

$ docker run --entrypoint cat myimage /etc/hostname
mycontainer-abc123

عندما تكون كلاهما مُحددًا، ENTRYPOINT هو التنفيذ، و CMD يصبح مُدخلاته الافتراضية. يمكن تجاوز CMD بشكل حر. يمكن تجاوز ENTRYPOINT فقط إذا قمت بتمرير --entrypoint.

كل تشكيل ممكن لـ ENTRYPOINT + CMD، مُفسر

تتضمن وثائق Docker جدولًا هذا لكنها لا تُركز على الصفوف التي تُسبب مشاكلك في اليوم:

ENTRYPOINTCMDما يُنفذ بالفعل
مُحددة دائمًا في البيئة الإنتاجيةمُحددة دائمًا في البيئة الإنتاجيةخطأ — يحتاج الـ container إلى أمر من مكان ما
مُحددة دائمًا في البيئة الإنتاجية["cmd", "arg"] شكل execcmd arg
مُحددة دائمًا في البيئة الإنتاجيةcmd arg شكل shell/bin/sh -c "cmd arg"
["entry"] شكل execمُحددة دائمًا في البيئة الإنتاجيةentry
["entry"] شكل exec["arg1", "arg2"] شكل execentry arg1 arg2
["entry"] شكل execcmd arg شكل shellentry /bin/sh -c "cmd arg" — من المرجح أن يكون خطأ
entry شكل shell["arg1"] شكل exec/bin/sh -c "entry"يُتجاهل CMD بصمت
entry شكل shellcmd arg شكل shell/bin/sh -c "entry"يُتجاهل CMD بصمت

الصفرين المُشَكَّلان بـ "يُتجاهل CMD بصمت" مسؤولان عن نسبة كبيرة من جلسات تشغيل Docker. شكل shell ENTRYPOINT لا يُدمج مع CMD — بل يتجاهله بالكامل. لن يُحذرك Docker من هذا.

شكل shell مقابل شكل exec: الفخ في معالجة الإشارات

تقبل كل من التعليماتان شكلين، ويعتمد الاختيار أكثر من ما يُقرره معظم مراجعات Dockerfile.

شكل exec (نظام المصفوفة):

ENTRYPOINT ["nginx", "-g", "daemon off;"]

يُنفذ البرنامج مباشرة. يصبح رقم PID 1. عندما يُرسل Docker SIGTERM لإيقاف الـ container، يتلقى البرنامج هذه الإشارة. يعمل التوقف بسلاسة. يتم تنظيف السجلات. تُغلق الاتصالات بشكل ناجح.

شكل الشل (نص بسيط):

ENTRYPOINT nginx -g "daemon off;"

يُنفذ Docker هذا كـ /bin/sh -c "nginx -g daemon off;". يكون الـ shell رقم PID 1. عندما تصل SIGTERM إلى النظام، sh يُحصل عليها — و sh لا يُنقل الإشارات إلى العمليات الفرعية. يُبقى الـ container لمدة 10 ثوانٍ، يُحصل على SIGKILL، ويُموت دون تنظيف. كل مرة.

استخدم شكل exec. دائمًا. لكل من ENTRYPOINT و CMD.

أربعة أنماط تعمل فعليًا

النمط 1: تنفيذ ثابت، مع إعدادات قابلة للتعديل

النمط المناسب لمعظم علامات الـ container في البيئة الإنتاجية. يكون البرنامج ثابتًا، والخيارات المُدخلة قابلة للتعديل في وقت التشغيل:

ENTRYPOINT ["/app/server"]
CMD ["--port", "8080", "--env", "production"]
# Use defaults
docker run myimage

# Override at deploy time
docker run myimage --port 9090 --env staging

النمط 2: سكربت مُحيط مع exec

عندما تحتاج إلى إجراءات تمهيد قبل عملية التشغيل الرئيسية (مigrations، إدخال الأسرار، تثبيت الإشارات)، استخدم سكربت مُحيط. السطر المهم هو exec "$@" في النهاية — يُستبدل عملية الـ shell بعملية CMD، لذا يصبح البرنامج رقم PID 1:

#!/bin/sh
set -e

echo "Running migrations..."
/app/migrate

# Hand off to CMD — exec replaces shell, so /app/server becomes PID 1
exec "$@"
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["/app/server", "--port", "8080"]

إذا تجاهلت exec "$@"، يبقى الـ shell كرقم PID 1 ويُعود إلى مشاكل معالجة الإشارات.

النمط 3: CMD فقط، بدون ENTRYPOINT

مقبول للصور المُطوّرة أو علامات الـ container التي تُستخدم لتشغيل أوامر عشوائية في بيئة متماثلة:

FROM python:3.12-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

في البيئة الإنتاجية، يكون النمط 1 أو 2 أكثر أمانًا — لا ترغب في أن يُنفذ سكربت تثبيت خاطئ بشكل غير متوقع ويُستبدل خادمك بجلسة الـ shell. docker run myimage bash ما يخص دالة docker exec في هذا السياق

لا شيء.

يُنفذ أمرًا داخل علامة الـ container المُشغلة بالفعل. يتجاوزها بالكامل. لا تحتاج إلى التفكير في docker exec عندما تستخدم ENTRYPOINT لإطلاع على شيء ما — أنت تتحدث مع بيئة الـ container الحالية، وليس على إعدادات البدء. ENTRYPOINT الارتباك غالبًا ما ينشأ من الناس الذين يستخدمون docker exec mycontainer bash ويفحصون أن الأمور تعمل، ثم يتساءلون لماذا

يُظهر سلوكًا مختلفًا. هما مسارات كود منفصلة. docker exec مُراجعة قبل الإطلاق docker run استخدم شكل exec (نظام المصفوفة، وليس نصوص بسيطة)

إذا كان لديك سكربت مُحيط، ينتهي بـ

  • كلاهما ENTRYPOINT و CMD لقد قمت بتجربة
  • لإثبات أن كل مسار يعمل exec "$@"
  • يُكمل في أقل من 2 ثانية (ليس 10 — إذا كان 10، فهذا يعني وجود مشكلة في الإشارات) docker run myimage و docker run myimage --your-flag إذا أردت ملاحظات تلقائية قبل أن يُرسل Dockerfile إلى مخزن،
  • docker stop mycontainer IO Tools’ Dockerfile Linter

يُكتشف استخدام شكل shell، نقص في سكربت الـ entrypoint، وأنماط أخرى تؤدي إلى سلوك خاطئ في وقت التشغيل. Docker ENTRYPOINT مقابل CMD — علامة الـ container أضحتت لك 2 exec Docker ENTRYPOINT مقابل CMD — علامة الـ container أضحتت لك 1

هل تريد حذف الإعلانات؟ تخلص من الإعلانات اليوم

تثبيت ملحقاتنا

أضف أدوات IO إلى متصفحك المفضل للوصول الفوري والبحث بشكل أسرع

أضف لـ إضافة كروم أضف لـ امتداد الحافة أضف لـ إضافة فايرفوكس أضف لـ ملحق الأوبرا

وصلت لوحة النتائج!

لوحة النتائج هي طريقة ممتعة لتتبع ألعابك، يتم تخزين جميع البيانات في متصفحك. المزيد من الميزات قريبا!

إعلان · حذف؟
إعلان · حذف؟
إعلان · حذف؟

ركن الأخبار مع أبرز التقنيات

شارك

ساعدنا على الاستمرار في تقديم أدوات مجانية قيمة

اشتري لي قهوة
إعلان · حذف؟