Docker والحاويات

تشغيل الحاويات

18 دقيقة الدرس 3 من 30

تشغيل الحاويات

معرفة كيفية سحب صورة هي مجرد أساسيات. المهارة الحقيقية تكمن في معرفة كيفية إطلاق الحاوية وفحصها والتحكم فيها وتصحيح أخطائها في بيئة الإنتاج — والسبب وراء كل خيار. على نطاق الشركات الكبرى، يؤدي سوء فهم خيار واحد إلى عملية جامحة تستنزف الموارد، أو تسريب سر في السجلات، أو حاوية تتوقف بصمت دون إعادة تشغيل. تغطي هذه الدرس دورة حياة الحاوية الكاملة عبر docker run وأدواته المساعدة.

بنية أمر docker run الكاملة

كل استدعاء لـ docker run يُنشئ حاوية جديدة من صورة، ويشغّل عملية واحدة (PID 1)، وينتهي عند انتهاء تلك العملية. الصيغة هي:

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

أهم الخيارات التي يجب استيعابها:

  • -d / --detach — التشغيل في الخلفية؛ طباعة معرّف الحاوية والعودة إلى الطرفية. هذا هو الوضع الافتراضي للخدمات التي تعمل باستمرار.
  • -it — تخصيص طرفية وهمية (-t) وإبقاء STDIN مفتوحاً (-i). يُستخدمان معاً للأصداف التفاعلية. لا تجمعهما مع -d للخدمات.
  • --name — تعيين اسم محدد. بدونه يُولّد Docker اسماً عشوائياً — يصعب إدارته على نطاق واسع.
  • --rm — إزالة الحاوية تلقائياً عند انتهائها. ضروري لحاويات التصحيح المؤقتة وعمليات CI لمنع امتلاء القرص.
  • -p HOST:CONTAINER — نشر منفذ. -p 8080:80 يربط منفذ المضيف 8080 بمنفذ الحاوية 80.
  • -e KEY=VALUE — حقن متغير بيئة. الطريقة المفضلة لتمرير الإعدادات؛ لا تُضمّن الأسرار في الصور أبداً.
  • --env-file FILE — حقن جماعي لمتغيرات البيئة من ملف. استخدمه لقوائم الإعدادات الطويلة أو الأسرار في CI.
  • --restart — سياسة إعادة التشغيل: no (الافتراضي)، always، on-failure[:N]، unless-stopped. تستخدم خدمات الإنتاج unless-stopped كي تنجو من إعادة تشغيل المضيف مع إمكانية إيقافها عمداً.
  • --memory / --cpus — حدود صارمة للموارد. بدونها، يمكن لحاوية واحدة جامحة أن تُجوّع الحاويات المجاورة على نفس المضيف.
  • --user — تجاوز UID/GID وقت التشغيل. استخدمه لتجنب التشغيل بصلاحيات root داخل الحاوية.
  • --read-only — تركيب نظام ملفات الحاوية للقراءة فقط. يُجبر العملية على الكتابة فقط في وحدات التخزين المُركّبة صراحةً — وهو إجراء أمني متعمق.
# حاوية خلفية، مُسمّاة، بسياسة إعادة تشغيل وحدود موارد ومتغير بيئة docker run -d \ --name api-server \ --restart unless-stopped \ --memory 512m \ --cpus 1.5 \ -p 8080:8080 \ -e DATABASE_URL=postgres://user:pass@db:5432/app \ --user 1000:1000 \ myorg/api-server:v2.4.1 # صدفة تفاعلية مؤقتة (تُحذف تلقائياً عند الخروج) docker run --rm -it ubuntu:24.04 bash # تنفيذ أمر محدد داخل صورة دون تعديلها docker run --rm alpine:3.20 sh -c "apk add --no-cache curl && curl -sI https://example.com"
تثبيت الصورة متطلب إنتاجي. استخدم دائماً وسماً محدداً (يُفضَّل التجزئة مثل @sha256:abc123…) في إعدادات الإنتاج. latest مؤشر متغير يتبدل بصمت ويجعل التراجع عن التغييرات مستحيلاً.

دورة حياة الحاوية

تمر الحاوية بحالات محددة جيداً. فهم هذه الحالات ضروري لكتابة فحوصات الصحة ومنطق إعادة التشغيل.

Docker container lifecycle state machine Created Running Paused Exited Removed start pause unpause stop/kill restart rm
دورة حياة حاوية Docker: Created → Running → Paused / Exited → Removed.

أوامر دورة الحياة الأساسية:

# تشغيل/إيقاف/إعادة تشغيل بالاسم docker start api-server docker stop api-server # يرسل SIGTERM، ينتظر 10 ثوانٍ، ثم SIGKILL docker stop --time 30 api-server # يمنح العملية 30 ثانية لإتمام الطلبات docker restart api-server docker kill api-server # SIGKILL فوري -- تجنب في الإنتاج # إيقاف مؤقت/استئناف (SIGSTOP -- يجمّد cgroups) docker pause api-server docker unpause api-server # سرد الحاويات docker ps # العاملة فقط docker ps -a # الكل، بما فيها الموقوفة docker ps --filter status=exited --filter name=api # إزالة الحاويات الموقوفة docker rm api-server docker rm -f api-server # إزالة قسرية حتى وإن كانت تعمل docker container prune # إزالة كل الحاويات الموقوفة
docker stop مقابل docker kill: افضل دائماً stop. فهو يرسل SIGTERM أولاً، مما يمنح تطبيقك الوقت لمسح المخازن المؤقتة وإغلاق اتصالات قاعدة البيانات وإتمام الطلبات الجارية. kill يرسل SIGKILL فوراً وقد يُفسد الحالة. المهلة الافتراضية 10 ثوانٍ غالباً قصيرة جداً لقواعد البيانات — اضبطها لكل خدمة باستخدام --time.

بث السجلات

يقرأ الأمر docker logs من مشغّل السجلات المُهيَّأ للحاوية. المشغّل الافتراضي (json-file) يكتب stdout/stderr في ملف JSON على المضيف. في الإنتاج، تنتقل إلى مشغّل يشحن السجلات إلى نظام مركزي (Loki، Splunk، CloudWatch)، لكن docker logs يبقى لا غنى عنه في التصحيح المحلي.

# متابعة السجلات (مثل tail -f) docker logs -f api-server # آخر 100 سطر docker logs --tail 100 api-server # منذ مدة نسبية docker logs --since 10m api-server docker logs --since "2025-10-01T08:00:00" api-server # إضافة الطوابع الزمنية (يضيفها Docker، لا التطبيق) docker logs -t api-server # دمج: متابعة مع طوابع زمنية من آخر 50 سطر docker logs -ft --tail 50 api-server
اكتب السجلات إلى stdout/stderr دائماً. تكتب تطبيقات Twelve-Factor سجلاتها إلى stdout؛ يتولى وقت التشغيل (Docker، Kubernetes، systemd) توجيهها إلى أي مستودع مُهيَّأ. لا تكتب السجلات في ملف داخل الحاوية — ستفقدها عند إزالة الحاوية وستملأ نظام الملفات بصمت.

تنفيذ أوامر في حاوية قيد التشغيل

يُولّد docker exec عملية جديدة داخل فضاء أسماء حاوية تعمل بالفعل. لا يمس PID 1. هذه هي الأداة الصحيحة لتصحيح الأخطاء الحية — وليس إعادة تشغيل الحاوية.

# فتح صدفة تفاعلية docker exec -it api-server bash docker exec -it api-server sh # إن لم يكن bash مثبتاً (صور Alpine) # تنفيذ أمر واحد بدون تفاعل docker exec api-server env | grep DATABASE docker exec api-server ps aux # التشغيل بمستخدم محدد (مثلاً root للفحص المتميز) docker exec -u root api-server cat /etc/passwd # فحص المنافذ المفتوحة من داخل الحاوية docker exec -it api-server ss -tlnp # فحص استخدام ذاكرة cgroup من الداخل docker exec api-server cat /sys/fs/cgroup/memory.current
لا تُثبّت أدوات التصحيح في صور الإنتاج لتمكين جلسات exec. استخدم الصور عديمة التوزيع أو الصور الصغيرة، وخطّط للتصحيح عبر الحاويات المؤقتة (Kubernetes) أو الحاوية الجانبية. تثبيت curl أو strace أو tcpdump في حاوية إنتاج تعمل يوسّع سطح الهجوم بشكل كبير. خطّط لاستراتيجية مراقبتك قبل وقوع الحوادث.

فحص حالة الحاوية

يُعيد docker inspect التمثيل الكامل بتنسيق JSON لحاوية أو صورة — وحدات التركيب، إعداد الشبكة، متغيرات البيئة، حدود الموارد، حالة فحص الصحة، رموز الخروج، والمزيد. وهو المصدر الموثوق للحقيقة حول تهيئة الحاوية الحية.

# مخرج JSON كامل docker inspect api-server # استخراج حقول محددة بقوالب Go docker inspect --format '{{.State.Status}}' api-server docker inspect --format '{{.State.ExitCode}}' api-server docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' api-server docker inspect --format '{{json .HostConfig.Resources}}' api-server | python3 -m json.tool # استهلاك الموارد في الوقت الفعلي (CPU، ذاكرة، I/O شبكة وقرص) docker stats api-server docker stats --no-stream api-server # لقطة واحدة، مناسبة للنصوص البرمجية docker stats --no-stream --format "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}"
سير عمل التصحيح في الإنتاج: عند تصرف الحاوية بشكل غير متوقع، التسلسل المعتاد هو: (1) docker ps للتحقق من الحالة، (2) docker logs لقراءة المخرجات الأخيرة، (3) docker inspect للتحقق من الإعدادات (متغيرات البيئة، وحدات التركيب، عداد إعادة التشغيل)، (4) docker stats لاستبعاد استنزاف الموارد، (5) docker exec للتحقيق الحي إذا كانت الحاوية لا تزال تعمل.

نسخ الملفات من وإلى الحاويات

أحياناً تحتاج إلى سحب ملف إعداد أو نتيجة عملية من حاوية تعمل للفحص، أو دفع ملف مؤقت للداخل للاختبار. يتعامل docker cp مع ذلك بدون وحدة تخزين مُركّبة.

# نسخ من الحاوية إلى المضيف docker cp api-server:/app/config/settings.json ./local-settings.json # نسخ من المضيف إلى الحاوية docker cp ./debug.conf api-server:/app/config/debug.conf

تجميع كل شيء: أمر تشغيل مُقوّى للإنتاج

هذا ما يبدو عليه أمر docker run الآمن والجاهز للإنتاج لواجهة API ويب — كل خيار مقصود:

docker run -d \ --name payments-api \ --restart unless-stopped \ --memory 1g --memory-swap 1g \ --cpus 2 \ --pids-limit 200 \ --read-only \ --tmpfs /tmp:size=100m \ --cap-drop ALL \ --cap-add NET_BIND_SERVICE \ --security-opt no-new-privileges \ -p 127.0.0.1:8080:8080 \ --env-file /etc/secrets/payments.env \ --user 1001:1001 \ myorg/payments-api:sha256-abc123

هذا النمط — صلاحيات Linux الدنيا، نظام ملفات للقراءة فقط، سقوف صريحة للموارد، ربط المنافذ بحلقة الاسترجاع فقط — هو خط الأساس الذي تطبقه المنظمات الهندسية الواعية أمنياً على كل حاوية إنتاج قبل أن تفكر في طبقة المُنسّق (Kubernetes) فوقها.