التعامل مع الـ Docker Image والـ Container
السلام عليكم ورحمة الله وبركاته
يمكنك متابعة السلسلة بالترتيب أو الانتقال مباشرة إلى أي مقال:
المقدمة
حسنًا، في المقالة السابقة تعرفنا على ما هو الـ Docker وما المشاكل التي يحلها
وتعرفنا على المفاهيم الأساسية مثل الـ Image والـ Container والـ Dockerfile والـ Docker Hub
في هذه المقالة سنبدأ بالجانب العملي ونتعلم كيف نتعامل مع الـ Docker بشكل فعلي
سنبدأ بتثبيت الـ Docker ثم نتعرف على أوامر التعامل مع الـ Images والـ Containers
مع أمثلة عملية بسيطة خطوة بخطوة
تثبيت الـ Docker
أول خطوة هي تثبيت الـ Docker على جهازك
يمكنك الذهاب إلى الموقع الرسمي للـ Docker واتباع التعليمات الخاصة بنظام التشغيل الخاص بك
https://docs.docker.com/get-docker/
ستجد تعليمات تثبيت الـ Docker على Windows و MacOS و Linux
اتبع الخطوات الموجودة في الموقع وستكون جاهزًا للعمل مع الـ Docker
التأكد من تثبيت الـ Docker
بعد تثبيت الـ Docker يمكننا التأكد من أنه تم تثبيته بشكل صحيح
نقوم بفتح الـ Shell أو الـ Command Prompt ونكتب الأمر التالي:
> docker
هذا الأمر سيعرض لنا قائمة المساعدة الخاصة بأوامر الـ Docker
إذا ظهرت لك هذه القائمة فهذا يعني أن الـ Docker تم تثبيته بشكل صحيح
للتعرف على إصدار الـ Docker المثبت على جهازك يمكنك تشغيل الأمر التالي:
> docker version
Client:
Version: 28.0.4
API version: 1.48
Go version: go1.23.7
Git commit: b8034c0
Built: Tue Mar 25 15:06:08 2025
OS/Arch: linux/amd64
Context: default
Server: Docker Desktop 4.0.0 ()
Engine:
Version: 28.0.4
API version: 1.48 (minimum version 1.24)
Go version: go1.23.7
Git commit: 6430e49
Experimental: false
containerd:
Version: 1.7.26
GitCommit: 753481ec61c7c8955a23d6ff7bc8e4daed455734
runc:
Version: 1.2.5
GitCommit: v1.2.5-0-g59923ef
docker-init:
لاحظ أن المخرجات تحتوي على جزئين أساسيين:
- الـ
Client: وهو أداة الـCLIالتي نستخدمها للتفاعل مع الـDockerوكتابة الأوامر - الـ
Server: وهو الـDocker Daemonأو الـDocker Engineالذي يقوم بتنفيذ الأوامر وإدارة الـContainersوالـImagesوغيرها من الأمور
الـ Client يتواصل مع الـ Server لإدارة والتحكم في الـ Containers
بمعنى أننا عندما نكتب أمر معين في الـ Shell فإن الـ Client يرسل هذا الأمر إلى الـ Server الذي ينفذه
للحصول على معلومات أكثر تفصيلًا عن الـ Docker المثبت يمكنك تشغيل الأمر التالي:
> docker info
هذا الأمر يعطيك معلومات مفصلة جدًا عن الـ Docker
مثل عدد الـ Containers والـ Images ونوع الـ Storage Driver وغيرها من المعلومات
التفاصيل ستكون طويلة جدًا لذلك لن نعرضها هنا، يمكنك تجربة الأمر بنفسك لترى التفاصيل
قبل أن نبدأ بالأوامر العملية دعنا نفهم الفرق بين الـ Image والـ Container بشكل أعمق
ما هو الـ Docker Image ؟
الـ Docker Image هو قالب أو مخطط لإنشاء الـ Docker Container
يمكننا تشبيه الـ Image بأنه نسخة ثابتة من تطبيق أو برنامج معين
هذا البرنامج يمكن أن يكون أي شيء:
- نظام تشغيل مثل
UbuntuأوAlpine LinuxأوDebian - تطبيق مثل
NginxأوRedisأوMongoDB - لغة برمجة مثل
Node.jsأوPythonأوPHP - قاعدة بيانات مثل
MySQLأوPostgreSQL - أو مزيج من كل ما سبق حسب احتياجات تطبيقك
- يمكنك أيضًا إنشاء
Imageخاصة بك تحتوي على كل ما تحتاجه لتشغيل تطبيقك
معظم الـ Images تكون مخزنة في الـ Docker Registry مثل الـ Docker Hub
وهو كما قلنا أشبه بـ GitHub ولكن للـ Docker Images أو كأنه Package Manager للـ Images
يمكنك تحميل Images جاهزة من هناك أو رفع Images خاصة بك
ستجد فيه آلاف الـ Images الجاهزة التي يمكنك تحميلها واستخدامها مباشرة
مثل MySQL و Redis و PostgreSQL و Nginx و PHP و Python وغيرها الكثير
والتي تكون مدعومة رسميًا من قبل الشركات أو المجتمعات المختصة بها
يمكنك أيضًا إنشاء Images خاصة بك باستخدام الـ Dockerfile ورفعها على الـ Docker Hub
وسنتحدث عن الـ Dockerfile بالتفصيل في المقالة القادمة
ما هو الـ Docker Container ؟
الـ Docker Container هو نسخة تنفيذية من الـ Docker Image
عندما نقوم بتشغيل Image فإنه ينشئ Container وهو التطبيق الذي ينفذ الـ Image
يمكننا تشبيه الأمر بمفهوم الـ Classes والـ Objects في الـ OOP:
- الـ
Imageهو مثل الـClassأو الـInterfaceيعمل كقالب أو مخطط - الـ
Containerهو مثل الـObjectأو الـInstanceالذي يتم إنشاؤه من هذا القالب
يمكنك إنشاء عدة Containers من نفس الـ Image
كل Container يكون معزول عن الآخر ويعمل بشكل مستقل بذاته وله ملفاته وموارده الخاصة به
مثل الـ Object مع الـ Class يمكننا إنشاء عدة Objects من نفس الـ Class وكل Object يعمل بشكل مستقل بذاته
الـ Containers لها العديد من الخصائص:
- يمكن تشغيلها وإيقافها وإعادة تشغيلها وحذفها
- يكون معزول عن النظام الأساسي لجهازك وعن كل الـ
Containersالأخرى - يمكن أن يكون لها الـ
Networkالخاص بها - يمكن أن يكون لها الـ
Storageالخاصة بها - يمكن أن يكون لها الـ
Environment Variablesالخاصة بها - وخصائص ومميزات أخرى كثيرة سنتعرف عليها في المقالات القادمة
أوامر الـ Docker Image
الـ Docker CLI يوفر لنا العديد من الأوامر للتعامل مع الـ Images والـ Containers
وهى مقسمة إلى أوامر خاصة بكل منهما والأوامر يمكنك فهمها بسهولة من خلال اسم الأمر
سنتعامل مع ثلاثة أوامر أساسية للـ Images:
docker image pull: لتحميلImageمن الـDocker Hubdocker image list: لعرض جميع الـImagesالموجودة على جهازكdocker image remove: لحذفImageمن جهازك
هناك أوامر أخرى مثل docker image build لإنشاء Image من Dockerfile
لكن سنتعرف عليه في المقالة القادمة عندما نتحدث عن الـ Dockerfile
أو أمر docker image inspect لعرض تفاصيل الـ Image
docker image pull
الأمر docker image pull يستخدم لتحميل Image في حالة إذا كانت غير موجودة على جهازك
والأمر قد يختصر إلى docker pull فقط
> docker image pull <image-name>
دعنا نجرب تحميل Image لنظام Alpine Linux
الـ Alpine Linux هى توزيعة للـ Linux خفيفة جدًا وحجمها صغير جدًا
وتكون مجرد Operating System خام بدون أي برامج مثبتة مسبقًا
وأي Image ستجدها هكذا، مجرد البرنامج أو التطبيق بدون أي إضافات زائدة
> docker image pull alpine:latest
latest: Pulling from library/alpine
1074353eec0d: Pull complete
Digest: sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
هنا قمنا بتحميل Image الخاصة بـ Alpine Linux بإصدار latest
الـ latest هو الإصدار الافتراضي إذا لم نحدد إصدار معين
الـ Docker قام بتحميل الـ Image من الـ Docker Hub على جهازنا
يمكننا تحديد إصدار معين من الـ Image عند التحميل
على سبيل المثال، لتحميل إصدار 3.19 من Alpine Linux:
> docker image pull alpine:3.19
docker image pull alpine:3.19
3.19: Pulling from library/alpine
17a39c0ba978: Pull complete
Digest: sha256:6baf43584bcb78f2e5847d1de515f23499913ac9f12bdf834811a3145eb11ca1
Status: Downloaded newer image for alpine:3.19
docker.io/library/alpine:3.19
حاليًا لدينا على جهازنا إصدارين من Alpine Linux اصدار الـ latest والـ 3.19
docker image list
لعرض جميع الـ Images الموجودة على جهازك نستخدم الأمر docker image list أو docker images
> docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 865b95f46d98 4 weeks ago 13MB
alpine 3.19 6baf43584bcb 3 months ago 11.5MB
هنا الأمر عرض لنا كل الـ Images الموجودة على جهازنا
ويعرض لنا عدة معلومات مهمة عن كل Image منها اسم الـ Image في خانة REPOSITORY
والـ id الخاص بها في خانة IMAGE ID
ولدينا TAG وهو يعبر عن مسمى للنسخة الـ Image التي قمنا بتحميلها
والـ TAG ليس شرطًا أن يعبر عن إصدار، بمعنى أنني قد أقوم بإنشاء Image خاصة بي تستخدم لغرض معين وأعطيها TAG باسم tabarani-image-tag مثلاً
وكلمة latest مجرد مسمى أيضًا ولا يشترط أن يكون latest هو أحدث إصدار من الـ Image، فهو مجرد اسم
بمعنى الـ Image الذي افترضنا أننا قمنا بإنشائه وقلنا أن اسمه tabarani-image-tag
إذا لم أعطيه أي TAG فسيكون اسمه الافتراضي latest أيضًا برغم من أنني قد أكون أنشأت هذه الـ Image منذ فترة طويلة ولم أقم بتحديثها منذ شهور
وقد أكون استخدم اصدارات قديمة فيها
لاحظ أن حجم كل Image صغير جدًا برغم من كونه Operating System، لأنه كما قلنا الـ images تكون خالية من أي برامج إضافية
وأيضًا الـ Alpine Linux هي توزيعة خفيفة جدًا بشكل عام كما ذكرنا مقارنة بغيرها من التوزيعات
docker image remove
لحذف Image نستخدم الأمر docker image remove أو docker image rm
> docker image remove 865b95f46d98
Untagged: alpine:latest
Deleted: sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
لاحظ أننا استخدمنا الـ IMAGE ID لحذف الـ Image
لنعرض مرة أخرى الـ Images الموجودة على جهازنا:
> docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine 3.19 6baf43584bcb 3 months ago 11.5MB
لاحظ أن الـ Image الخاصة بـ latest قد تم حذفها بنجاح
ويمكننا أيضًا حذف الـ Image باستخدام اسمها مع الإصدار:
docker image remove alpine:3.19
Untagged: alpine:3.19
Deleted: sha256:6baf43584bcb78f2e5847d1de515f23499913ac9f12bdf834811a3145eb11ca1
الآن لو عرضنا الـ Images مرة أخرى:
> docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
ستلاحظ أننا لم يعد لدينا أي Images على جهازنا
لنعيد تحميل الـ Image الخاصة بـ Alpine Linux مرة أخرى لكي نتمكن من استخدامها في الأمثلة القادمة:
> docker image pull alpine:latest
latest: Pulling from library/alpine
1074353eec0d: Pull complete
Digest: sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62
Status: Downloaded newer image for alpine:latest
docker.io/library/alpine:latest
لنرى الـ Images مرة أخرى:
> docker image list
REPOSITORY TAG IMAGE ID CREATED SIZE
alpine latest 865b95f46d98 4 weeks ago 13MB
لاحظ أن الـ Image ID الخاصة بـ Alpine Linux لم تتغير بعد حذفها وإعادة تحميلها مرة أخرى
هذا لأن الـ Image ID هو hash يتم توليده عندما نقوم بإنشاء الـ Image أو في كل مرة نقوم بعمل build لها
لأننا هنا لا نقوم ببناء Image جديدة بل نقوم بتحميل نفس الـ Image من الـ Docker Hub
فالـ Image الخاصة بـ Alpine Linux لم تتغير وبالتالي الـ Image ID لم يتغير أيضًا
كل مرة نقوم بتحميل نفس الـ Image من الـ Docker Hub سنحصل على نفس الـ Image ID
لكن في تم تعديل الـ Image وإنشاء نسخة جديدة منها فسيتم توليد Image ID جديد مختلف
على أي حال سنتعرف على هذا الأمر أكثر عندما نتحدث عن إنشاء الـ Images الخاصة بنا في المقالات القادمة
وأيضًا عمود CREATED يوضح لنا متى تم إنشاء أو تعديل هذه النسخة من الـ Image وليس متى تم تحميلها على جهازنا
لذا نفهم أن نسخة alpine:latest آخر تعديل لها كان منذ 4 أسابيع
أوامر الـ Docker Container
الآن بعد أن تعرفنا على الـ Images وكيفية تحميلها وعرضها وحذفها
دعنا نتعرف على الـ Containers وكيفية التعامل معها
سنتعرف على بعض الأوامر الأساسية للـ Containers:
docker container run: لإنشاء وتشغيلContainerجديد منImagedocker container list: لعرض جميع الـContainersالموجودة على جهازكdocker container stop: لإيقافContainerقيد التشغيلdocker container start: لتشغيلContainerمتوقفdocker container remove: لحذفContainerمتوقفdocker container exec: لتنفيذ أوامر داخلContainerقيد التشغيل
docker container run
لإنشاء Container جديد من Image وتشغيله نستخدم الأمر docker container run أو docker run فقط
> docker container run <image-name>
هنا نحن نريد إنشاء Container من الـ Image الخاصة بـ Alpine Linux التي قمنا بتحميلها سابقًا
> docker container run alpine:latest
الآن الـ Docker قام بإنشاء Container جديد من الـ Image الخاصة بـ Alpine Linux
حسنًا لنتأكد من ذلك ونرى الـ Containers الموجودة على جهازنا عن طريق الأمر docker container list
ملحوظة: إذا قمت بتشغيل الأمرdocker run alpine:latestوالـImageغير موجودة على جهازك
هناDockerسيقوم تلقائيًا بتحميل الـImageمن الـDocker Hubقبل تشغيلها
لذلك يمكنك انشاء الـContainerحتى بدون تحميل الـImageمسبقًا وسيقوم الـDockerبتحميلها نيابة عنك في حالة عدم وجودها
docker container list
لعرض قائمة الـ Containers نستخدم الأمر docker container list
> docker container list
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
ستلاحظ أن القائمة فارغة ولا يوجد أي Container معروض
هذا لأن أمر docker container list يعرض فقط الـ Containers التي تعمل حاليًا
أما الـ Container الذي أنشأناه من قبل فلقد انتهى وأغلق نفسه فورًا بعد إنشائه
وسنعرف السبب في ذلك لاحقًا
لذلك لعرض جميع الـ Containers سواء كانت تعمل أو متوقفة نستخدم الـ flag المسمى --all أو -a
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6f5bce75aa7c alpine:latest "/bin/sh" 7 minutes ago Exited (0) 7 minutes ago affectionate_ishizaka
الآن نرى الـ Container الذي أنشأناه سابقًا معروض في القائمة
لدينا هنا معلومات عنه مثل الـ CONTAINER ID والـ IMAGE التي تم إنشاؤه منها
والـ STATUS الخاص به والـ NAMES الذي تم تعيينه له تلقائيًا من قبل الـ Docker
ولدينا أيضًا الـ CREATED الذي يوضح متى تم إنشاؤه
لاحظ أن قيمة الـ STATUS هى Exited (0) مما يعني أن الـ Container انتهى وأغلق نفسه فورًا بعد إنشائه
لكن لما أغلق نفسه ؟
حسنًا أنظر إلى خانة الـ COMMAND والتي توضح الأمر الذي تم تنفيذه داخل الـ Container عند إنشائه باستخدام أمر docker container run
سنرى هنا أن الأمر هو "/bin/sh" وهو الـ Shell الخاص بـ Alpine Linux
بالتالي عندما تم إنشاء الـ Container تم تشغيل الـ Shell الخاص به
لكن لسبب ما الـ Shell أغلق نفسه فورًا بعد إنشائه
هذا لأننا نحتاج أن نجعل الـ Shell يبقى مفتوحًا للتفاعل معه عن طريق بعض الـ flags الإضافية وهى -i و -t
والتي سنتعرف عليها ونشرحها لاحقًا في فقرة مخصصة في المقالة
على أي حال، في حالة تكرار تنفيذ الأمر docker container run alpine:latest عدة مرات
سيتم إنشاء Container جديد في كل مرة بنفس الطريقة
ويمكننا استخدام الـ IMAGE ID بدلاً من اسم الـ Image عند إنشاء الـ Container
لنحاول تجربة الأمر وإنشاء أكثر من Container:
> docker container run alpine:latest
> docker container run 865b95f46d98
الآن لو عرضنا الـ Containers مرة أخرى:
> docker container list --all
docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
937bbfedef93 alpine:latest "/bin/sh" 3 seconds ago Exited (0) 3 seconds ago distracted_ardinghelli
a1bf2589d733 865b95f46d98 "/bin/sh" 8 seconds ago Exited (0) 8 seconds ago compassionate_volhard
6f5bce75aa7c alpine:latest "/bin/sh" 12 minutes ago Exited (0) 12 minutes ago affectionate_ishizaka
الآن لدينا ثلاثة Containers من نفس الـ Image
لاحظ أن الـ Container الذي تم إنشاؤه باستخدام الـ IMAGE ID له نفس الـ IMAGE ID في خانة الـ IMAGE
والذي تم إنشاؤه باستخدام اسم الـ Image له اسم الـ Image في خانة الـ IMAGE
وكما ذكرنا سابقًا، فإن كل Container يعمل بشكل مستقل عن الآخر ومعزول بشكل تام عن جهازك وباقي الـ Containers
docker container remove
بعد ما أصبح لدينا عدة Containers على جهازنا
نريد حذف بعضها للتخلص من الـ Containers غير المستخدمة
لحذف Container نستخدم الأمر docker container rm أو docker rm أو docker container remove أو docker remove
في docker ستلاحظ وجود عدة أوامر تؤدي نفس الوظيفة مع اختلاف في التسمية فقط
> docker container remove 937bbfedef93
937bbfedef93
الآن لو عرضنا الـ Containers:
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a1bf2589d733 865b95f46d98 "/bin/sh" 7 minutes ago Exited (0) 7 minutes ago compassionate_volhard
6f5bce75aa7c alpine:latest "/bin/sh" 20 minutes ago Exited (0) 20 minutes ago affectionate_ishizaka
ستلاحظ أن الـ Container الذي حذفناه لم يعد موجود في القائمة
يمكنك حذف عدة Containers دفعة واحدة:
> docker container remove a1bf2589d733 6f5bce75aa7c
a1bf2589d733
6f5bce75aa7c
الآن لو عرضنا الـ Containers مرة أخرى:
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
الآن جميع الـ Containers قد تم حذفها بنجاح
تسمية الـ Container
ستلاحظ أنه عند إنشاء Container جديد من الـ Image يتم تعيين اسم تلقائي له في عمود NAMES
بمعنى أن جميع الـ Containers التي أنشأناها سابقًا كان لها أسماء مثل distracted_ardinghelli و compassionate_volhard و affectionate_ishizaka
هذه الأسماء يتم توليدها تلقائيًا من قبل الـ Docker عند إنشاء الـ Container
وتكون بديلة عن الـ CONTAINER ID الطويلة والصعبة التذكر
الـ Docker يقوم بتوليد اسم عشوائي يتكون من كلمتين: صفة و اسم عالم أو شخصية مشهورة
مثل sleepy_borg أو happy_einstein أو angry_tesla
وهذا يجعل الأسماء سهلة التذكر نوعًا ما مقارنة بالـ Container ID
يمكنك استخدام اسم الـ Container بدلاً من الـ Container ID في معظم الأوامر
على سبيل المثال، بدلاً من كتابة:
> docker container remove 937bbfedef93
يمكنك كتابة:
> docker container remove compassionate_volhard
وهذا يسهل التعامل مع الـ Containers خاصة عندما يكون لديك عدة Containers تعمل في نفس الوقت
لكن نحن لا نريدأن نعتمد على الأسماء التلقائية للـ Container
بل نحتاج في بعض الأحيان إلى تعيين أسماء مخصصة للـ Containers الخاصة بنا
لذا يوفر لنا الـ Docker طريقة لتحديد اسم مخصص للـ Container عند إنشائه
باستخدام الـ flag المسمى --name
> docker container run --name <container-name> <image-name>
لنجرب إنشاء Container جديد باسم my-alpine-container:
> docker container run --name my-alpine-container alpine:latest
الآن لو عرضنا الـ Containers:
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8f3d2a1b5c7e alpine:latest "/bin/sh" 3 seconds ago Exited (0) 3 seconds ago my-alpine-container
لاحظ أن الـ Container الجديد له الاسم الذي حددناه وهو my-alpine-container
الآن يمكننا استخدام هذا الاسم في أي أمر عوضًا عن الـ Container ID
> docker container remove my-alpine-container
my-alpine-container
ملحوظة: اسم الـContainerيجب أن لا يتكرر
بمعنى أنه لا يمكنك إنشاءContainerجديد بنفس اسمContainerموجود بالفعل
حتى لو كان الـContainerالموجود متوقفًا، يجب حذفه أولًا أو استخدام اسم مختلف
من الآن فصاعدًا سنقوم بإنشاء Containers بأسماء مخصصة لتسهيل التعامل معها في الأمثلة القادمة
وأيضًا لنعتاد على تسمية الـ Containers بأسماء واضحة تعبر عن وظيفتها
وأيضًا ستعرف أن اسم الـ Container مهم جدًا عندما نتعامل مع معظم خصائص الـ Docker لأننا يمكننا استخدام اسم الـ Container بدلاً من الـ Container ID أو بدلًا من الـ IP Address الخاص بالـ Container في الأوامر
وخصوصًا أن الأسماء تكون ثابتة وسهلة التذكر مقارنة بالـ Container ID أو الـ IP Address التي قد تتغير في كل مرة نقوم فيها بإنشاء Container جديد
تشغيل Shell داخل الـ Container
قلنا أننا عندما نقوم بتشغيل Container من Alpine Linux فإنه يبدأ وينتهي فورًا
وعرفنا من خانة الـ COMMAND أن الأمر الذي حاول الـ Alpine تشغيله هو الـ Shell الخاص به /bin/sh
لكن الـ Shell أغلق نفسه لسبب ما
عليك أن تعرف أن كل Image نحمله ثم نقوم بإنشاء Container منها
فهذا الـ Image يقوم بتنفيذ أمر معين عند تشغيل الـ Container منه
وفي حالة الـ Alpine Linux فإن الأمر الافتراضي هو تشغيل الـ Shell الخاص به
وغالبًا أي Image لنظام تشغيل Linux سيكون الأمر الافتراضي هو تشغيل الـ Shell الخاص به
وكل Image أخرى سيكون لها أمر افتراضي مختلف حسب طبيعة هذا الـ Image
على أي حال قلنا أن الـ Shell أغلق نفسه فورًا لأننا لم نحدد له أن يبقى مفتوحًا للتفاعل معه
ولكي نجعل الـ Shell يبقى مفتوحًا ونتفاعل معه علينا استخدام الأمر docker container run مع بعض الـ flags الإضافية:
-iاختصار لـinteractiveوهي تسمح بالتفاعل مع الـContainer
بمعنى أخر أنها تبقي الـSTDINمفتوحًا للتفاعل مع الـContainerوكتابة الأوامر داخله-tاختصار لـttyوهي اختصار لـteletypewriterوتقوم بتخصيصShellداخل الـContainer
بمعنى أنها تقوم بمحاكاة بيئةTerminalداخل الـContainerمما يجعل التفاعل معه أسهل
يمكننا دمج الـ -i و -t في flag واحدة -it
> docker container run -it --name my-alpine-container alpine:latest
/ #
عندما نستخدم الـ -it مع الأمر docker container run
سيقوم بإنشاء Container جديد من الـ Image الخاصة بـ Alpine Linux
وسيقوم الـ Alpine بتنفيذ الأمر الافتراضي الخاص به وهو تشغيل الـ Shell الخاص به /bin/sh
ثم بفضل الـ -it سيبقي الـ Shell مفتوحًا لكي نتفاعل معه
عندما تقوم بتنفيذ هذا الأمر ستدخل مباشرة إلى الـ Shell الخاص بالـ Container داخل الـ Alpine Linux
يمكنك كتابة أوامر Linux هنا وتنفيذها داخل الـ Container
مثل أمر ls لعرض الملفات والمجلدات التي توجد في الـ Container:
/ # ls
bin dev etc home lib media mnt opt proc root run sbin srv sys tmp usr var
ستلاحظ أن هذه هي الملفات والمجلدات الأساسية لأي نظام تشغيل Linux
وهذا يؤكد لنا أننا داخل نظام Alpine Linux داخل الـ Container
يمكنك التحقق من إصدار نظام التشغيل باستخدام الأمر cat /etc/os-release:
/ # cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.23.2
PRETTY_NAME="Alpine Linux v3.23"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://gitlab.alpinelinux.org/alpine/aports/-/issues"
أنت الآن لديك نظام Alpine Linux يعمل داخل Container ويمكنك التفاعل معه كما تريد
وتنفيذ أي أوامر Linux تريدها داخل هذا الـ Container
للخروج من الـ Container اكتب exit:
/ # exit
الآن بعد الخروج من الـ Container
إذا قمت بعرض الـ Containers مرة أخرى:
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
16704b093612 alpine:latest "/bin/sh" 3 minutes ago Exited (0) 13 seconds ago my-alpine-container
ستلاحظ أن الـ Container الذي كنا فيه قد تم إنشاؤه منذ 3 دقائق وحالته الآن Exited لأنه انتهى منذ 13 ثانية
بمعنى أننا كنا داخل هذا الـ Container لمدة 3 دقائق تقريبًا قبل أن نخرج منه
ملحوظة: عندما ننشيءContainerباستخدام-itكما فعلنا الآن
فإن الـContainerيحتفظ بإعدادات الـ-itهذه كإعدادات دائمة للـContainer
وهذا يعطي خصائص معينة للـContainerلن تجدها في حالة إنشاءContainerبدون-it
وتذكر أن الـ -it تستتخدم مع أمر الـ shell للدخول فيه والتفاعل معه
لكن لو كان الأمر الافتراضي للـ Image لا يقوم بتشغيل shell بل يقوم بتشغيل أمر آخر
فإن الـ -it لن يكون له أي تأثير لأننا لا نقوم بتشغيل shell داخل الـ Container من الأساس
docker container start
لتشغيل Container متوقف نستخدم الأمر docker container start أو docker start
> docker container start my-alpine-container
my-alpine-container
هنا قمنا بتشغيل الـ Container الذي أنشأناه سابقًا باسم my-alpine-container
وبالطبع يمكننا استخدام الـ CONTAINER ID بدلاً من الاسم
لكن كما ذكرنًا سنتعامل مع أسماء الـ Containers من الآن فصاعدًا
لكن لاحظ أن الـ Container لم يجعلنا ندخل إلى الـ Shell الخاص به مرة أخرى
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
16704b093612 alpine:latest "/bin/sh" 22 minutes ago Up 3 seconds my-alpine-container
لاحظ أن الـ STATUS الآن يظهر Up 3 seconds مما يعني أنه يعمل حاليًا
بمعنى أن الـ Container يعمل الآن في الخلفية
إذا أردنا الدخول إلى الـ Container والتفاعل معه مرة أخرى بعد إنشائه
نستخدم الأمر docker container start مع الـ flags الخاصة بالتفاعل -a و -i:
-a(اختصار لـattach): لربط الـShellالخاص بك بالـContainer-i(اختصار لـinteractive): للسماح بالتفاعل مع الـContainer
ويمكننا دمجهما في flag واحدة -ai
لاحظ أن -a يشبه -t في أنه يربط الـ Shell الخاص بك بالـ Container
لكن الفرق هو أن -t يستخدم لإنشاء Shell جديد داخل الـ Container خلال عملية الإنشاء run
أما -a يستخدم لربط الـ Shell الخاص بك بالـ Container الموجود بالفعل خلال عملية التشغيل start
> docker container start -ai my-alpine-container
/ #
الآن نحن داخل الـ Container مرة أخرى ويمكننا التفاعل معه كما فعلنا سابقًا
مثل تنفيذ أمر ls وغيره من أوامر Linux داخل الـ Container كما فعلنا سابقًا
الآن للخروج من الـ Container نكتب exit:
/ # exit
هناك أمور عليك أن تعرفها عند استخدام أمر docker container start مع الـ -a و -i
وهى أنك لا تستطيع استخدام -a في حالة إذا أنشأت الـ Container بدون -t في البداية
وإذا قمت بإنشاء Container بدون -it في البداية ثم قمت بعمل start ستجد أن حالة الـ Container تصبح Exited وليس Up
أما عندما تقوم بعمل start على Container تم إنشاؤه بـ -it في البداية فستجد أن حالة الـ Container تصبح Up وتبقى تعمل في الخلفية
وهذا السلوك بسبب أن هذه الـ flags يتم حفظها كإعدادات دائمة للـ Container عند إنشائه باستخدام docker container run -it
بالتالي فكأنها تعطي خصائص دائمة للـ Container بأننا فعلنا خواص التفاعل معه باستخدام -it
بالتالي عندما نقوم بعمل start فإنه يبدأ في الخلفية بسبب الـ flags المحفوظة سابقًا
أما في حالة إذا أنشأنا الـ Container بدون -it في البداية
فإننا عندما نقوم بعمل start فإنه يبدأ وينتهي فورًا مرة أخرى دون أن يبقى يعمل في الخلفية
لأن هذا الـ Container لا يملك إعدادات التفاعل معه عند إنشائه
ملحوظة: الـflagsمثل-itو-aiنستخدمها عندما ننفذshellأوbashأو ما شابه داخل الـContainer
ونريد أن نتفاعل مع هذا الـshellأوbash
لكن في حالة إذا كان الأمر الافتراضي للـImageلا يقوم بتشغيلshellأوbashبل يقوم بتشغيل أمر آخر
أو كان الـContainerينفذ أمر معين عند تشغيله فإن هذه الـflagsلن يكون لها أي تأثير أو فائدة
لذا استخدمها فقط عندما تنفذshellأوbashداخل الـContainerوالتفاعل معه
وكما قلنا ليس كل Image تقوم بتشغيل shell أو bash عند تشغيل Container منها
سنقوم بشرح وفهم هذه الأمور أكثر عندما نتحدث عن االـ Dockerfile وبناء الـ Images الخاصة بنا في المقالات القادمة
docker container exec
لاحظ أننا عندما نريد تنفيذ أمر معين داخل Container نضطر إلى الدخول إلى الـ Shell الخاص به أولًا
ثم كتابة الأمر الذي نريد تنفيذه ثم نخرج من الـ Shell مرة أخرى عن طريق كتابة exit
لكن ماذا لو أردنا فقط تنفيذ أمر معين داخل Container دون الحاجة إلى الدخول إلى الـ Shell الخاص به؟
هنا تأتي فكرة أمر الـ exec بحيث يمكننا تنفيذ أوامر داخل Container بدون الدخول إلى الـ Shell الخاص به
الأمر docker container exec أو docker exec يتيح لنا ذلك
يتيح لنا هذا الأمر تنفيذ أوامر داخل Container بشرط أن يكون الـ Container يعمل حاليًا وليس متوقفًا
في حالتنا الآن فالـ Container الخاص بـ Alpine Linux ليس متوقف ويمكننا التحقق من ذلك:
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
16704b093612 alpine:latest "/bin/sh" 24 minutes ago Up 2 minutes my-alpine-container
كما نرى الـ STATUS قيمتها Up مما يعني أنه يعمل حاليًا
أمر الـ exec مثل أخوته يكتب بالشكل التالي:
> docker container exec <container-id> <command>
لنفترض أننا نريد تنفيذ أمر ls داخل الـ Container:
> docker container exec my-alpine-container ls
bin dev etc home lib media mnt opt proc root ...
هنا قمنا بتنفيذ أمر ls داخل الـ Container دون الدخول إليه
الأمر تم تنفيذه وتم عرض النتيجة مباشرة من الـ Terminal الخاص بنا
docker container stop
لإيقاف Container يعمل حاليًا نستخدم الأمر docker container stop أو docker stop
> docker container stop my-alpine-container
my-alpine-container
دعنا نتحقق من أن الـ Container قد توقف
> docker container list --all
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
16704b093612 alpine:latest "/bin/sh" 26 minutes ago Exited (0) 39 seconds ago my-alpine-container
ستلاحظ أن الـ STATUS أصبح Exited مما يعني أن الـ Container قد توقف بنجاح
ملخص الأوامر
لا أريد أن استفيض في الشرح أكثر من ذلك في هذه المقالة
لأنه مازال هناك تفاصيل وأوامر كثرة، لذا سنكتفي بهذا القدر في هذه المقالة
في هذه المقالة تعرفنا على أساسيات التعامل مع الـ Docker
وتعرفنا على الفرق بين الـ Image والـ Container بشكل عملي بسيط
ثم تعلمنا الأوامر الأساسية للتعامل مع الـ Images والـ Containers
في المقالة القادمة سنشرح مثال عملي أخر باستخدام Nginx وسنقوم بإنشاء Container لتشغيل Nginx داخل Docker
إليك ملخص سريع لأهم الأوامر التي تعلمناها في هذه المقالة:
| الأمر | الوظيفة |
|---|---|
docker image pull <image> |
تحميل Image من الـ Docker Hub |
docker image list |
عرض جميع الـ Images |
docker image remove <image> |
حذف Image |
docker container run <image> |
إنشاء وتشغيل Container جديد |
docker container run --name <name> <image> |
إنشاء Container مع تعيين اسم مخصص |
docker container run -it <image> |
تشغيل Container مع الدخول للـ Shell |
docker container exec <container> <command> |
تنفيذ أمر داخل Container |
docker container list |
عرض الـ Containers العاملة |
docker container list --all |
عرض جميع الـ Containers |
docker container start <container> |
تشغيل Container متوقف |
docker container stop <container> |
إيقاف Container قيد التشغيل |
docker container remove <container> |
حذف Container متوقف |
ملحوظة: لا يمكنك حذفContainerيعمل حاليًا، لذا يجب عليك إيقافه أولًا باستخدام الأمرdocker container stop
ثم بعد ذلك يمكنك حذفه باستخدام الأمرdocker container remove
ولا يمكنك حذفImageإذا كان هناكContainerتم إنشاءه منها
لذا يجب عليك حذف جميع الـContainersالتي تم إنشاؤها من هذه الـImageأولًا، سواء كانت الـContainersتعمل أو متوقفة
ثم بعد ذلك يمكنك حذف الـImage
خاتمة
يوجد العديد من الأوامر والتفاصيل الأخرى التي يمكننا تعلمها في الـ Docker
لكن لا أريد أن أطيل عليكم بالأوامر والتفاصيل في هذه المقالة
تعرفنا في هذه المقالة على أهم الأوامر والأمور التي ستحتاجها في البداية
في باقي المقالات أو حتى في طريقك في تعلم الـ Docker ستتعلم المزيد من الأوامر والتفاصيل الأخرى