مقدمة
دوكر هو برنامج يُسهّل عملية إدارة عمليات التطبيقات داخل الحاويات. تُمكّنك الحاويات من تشغيل تطبيقاتك في عمليات معزولة الموارد. وهي تُشبه الآلات الافتراضية، لكن الحاويات أكثر قابلية للنقل، وأقل استهلاكًا للموارد، وأقل اعتمادًا على نظام التشغيل المُضيف.
للحصول على مقدمة مفصلة عن المكونات المختلفة لحاوية Docker، راجع The Docker Ecosystem: An Introduction to Common Components.
في هذا الدرس التعليمي، ستقوم بتثبيت واستخدام Docker Community Edition (CE) على Ubuntu 20.04. ستقوم بتثبيت Docker نفسه، والعمل مع الحاويات والصور، ودفع صورة إلى مستودع Docker.
ملحوظة
ستُرشدك هذه المقالة خلال عملية تثبيت Docker على خادم Ubuntu. إذا كنت ترغب في طريقة سهلة وسريعة لنشر تطبيق Docker على خادم مباشر، فراجع منصة تطبيقات DigitalOcean.
المتطلبات الأساسية
لمتابعة هذا الشرح، ستحتاج إلى ما يلي:
- تم إعداد خادم Ubuntu 20.04 باتباع دليل الإعداد الأولي لخادم Ubuntu 20.04، بما في ذلك مستخدم sudo غير الجذر وجدار الحماية.
- كما هو موضح في الخطوتين 7 و 8، ستحتاج إلى حساب Docker Hub إذا كنت ترغب في إنشاء صورك الخاصة ودفعها إلى Docker Hub.
الخطوة 1 - تثبيت Docker
قد لا تكون حزمة تثبيت Docker المتوفرة في مستودع Ubuntu الرسمي هي أحدث إصدار. لضمان حصولك على أحدث إصدار، سنقوم بتثبيت Docker من مستودع Docker الرسمي. وللقيام بذلك، سنضيف مصدر حزمة جديد، ونضيف مفتاح GPG من Docker للتأكد من صحة التنزيلات، ثم نثبت الحزمة.
أولاً، قم بتحديث قائمة الباقات المتاحة لديك:
sudo apt update
بعد ذلك، قم بتثبيت بعض الحزم الأساسية التي ستسمح لـ apt باستخدام الحزم عبر HTTPS:
sudo apt install apt-transport-https ca-certificates curl software-properties-common
ثم أضف مفتاح GPG الخاص بمستودع Docker الرسمي إلى نظامك:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
أضف مستودع Docker إلى مصادر APT:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu focal stable"
سيؤدي هذا أيضًا إلى تحديث قاعدة بيانات الحزم الخاصة بنا بحزم Docker من المستودع المضاف حديثًا.
تأكد من أنك تقوم بالتثبيت من مستودع Docker بدلاً من مستودع Ubuntu الافتراضي:
apt-cache policy docker-ce
سترى مخرجات كهذه، على الرغم من أن رقم إصدار Docker قد يكون مختلفًا:
docker-ce:
Installed: (none)
Candidate: 5:19.03.9~3-0~ubuntu-focal
Version table:
5:19.03.9~3-0~ubuntu-focal 500
500 https://download.docker.com/linux/ubuntu focal/stable amd64 Packagesلاحظ أن docker-ce غير مثبت، ولكنه مرشح للتثبيت من مستودع Docker لنظام Ubuntu 20.04 (canonical).
وأخيراً، قم بتثبيت Docker:
sudo apt install docker-ce
يجب الآن تثبيت Docker، وتشغيل الخدمة، وتفعيل بدء العملية عند بدء التشغيل. تأكد من أنها تعمل:
sudo systemctl status docker
ينبغي أن تكون النتيجة مشابهة لما يلي، مما يشير إلى أن الخدمة تعمل بشكل صحيح:
Output
● docker.service - Docker Application Container Engine
Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2020-05-19 17:00:41 UTC; 17s ago
TriggeredBy: ● docker.socket
Docs: https://docs.docker.com
Main PID: 24321 (dockerd)
Tasks: 8
Memory: 46.4M
CGroup: /system.slice/docker.service
└─24321 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sockيوفر لك تثبيت Docker ليس فقط خدمة Docker (البرنامج الخفي)، بل أيضًا أداة سطر أوامر Docker أو عميل Docker. سنتناول في بقية هذا الدليل كيفية استخدام أمر Docker.
الخطوة 2 - تشغيل أمر Docker بدون استخدام sudo (اختياري)
افتراضيًا، لا يمكن تشغيل أمر docker إلا بواسطة المستخدم الجذر أو مستخدم ضمن مجموعة docker، التي تُنشأ تلقائيًا أثناء عملية تثبيت Docker. إذا حاولت تشغيل أمر docker بدون إضافة sudo قبله أو بدون أن تكون ضمن مجموعة docker، فستحصل على مخرجات مشابهة لما يلي:
Output
docker: Cannot connect to the Docker daemon. Is the docker daemon running on this host?.
See 'docker run --help'.إذا كنت ترغب في تجنب كتابة sudo عند تشغيل أمر docker، فأضف اسم المستخدم الخاص بك إلى مجموعة docker:
sudo usermod -aG docker ${USER}
لتطبيق عضوية المجموعة الجديدة، قم بتسجيل الخروج من الخادم ثم تسجيل الدخول مرة أخرى، أو اكتب ما يلي:
su - ${USER}
للمتابعة، سيُطلب منك إدخال كلمة مرور المستخدم الخاصة بك.
تأكد من إضافة المستخدم الخاص بك إلى مجموعة docker عن طريق كتابة الأمر التالي:
groups
sammy sudo docker
إذا كنت بحاجة إلى إضافة مستخدم إلى مجموعة Docker لم تقم بتسجيل الدخول به، فقم بتحديد اسم المستخدم هذا بشكل صريح باستخدام:
sudo usermod -aG docker usernameيفترض باقي هذا المقال أنك تُشغّل أمر docker كمستخدم ضمن مجموعة docker. إذا كنت لا ترغب في ذلك، يُرجى إضافة الأمر sudo إلى نهاية الأوامر.
لننتقل الآن إلى فحص أمر docker.
الخطوة 3 - استخدام أمر Docker
يتضمن استخدام Docker تمرير سلسلة من الخيارات والأوامر متبوعة بالوسائط. الصيغة كالتالي:
docker [option] [command] [arguments]
لعرض جميع الأوامر الفرعية المتاحة، اكتب:
dockerابتداءً من Docker 19، تتضمن القائمة الكاملة للأوامر الفرعية المتاحة ما يلي:
Output
attach Attach local standard input, output, and error streams to a running container
build Build an image from a Dockerfile
commit Create a new image from a container's changes
cp Copy files/folders between a container and the local filesystem
create Create a new container
diff Inspect changes to files or directories on a container's filesystem
events Get real time events from the server
exec Run a command in a running container
export Export a container's filesystem as a tar archive
history Show the history of an image
images List images
import Import the contents from a tarball to create a filesystem image
info Display system-wide information
inspect Return low-level information on Docker objects
kill Kill one or more running containers
load Load an image from a tar archive or STDIN
login Log in to a Docker registry
logout Log out from a Docker registry
logs Fetch the logs of a container
pause Pause all processes within one or more containers
port List port mappings or a specific mapping for the container
ps List containers
pull Pull an image or a repository from a registry
push Push an image or a repository to a registry
rename Rename a container
restart Restart one or more containers
rm Remove one or more containers
rmi Remove one or more images
run Run a command in a new container
save Save one or more images to a tar archive (streamed to STDOUT by default)
search Search the Docker Hub for images
start Start one or more stopped containers
stats Display a live stream of container(s) resource usage statistics
stop Stop one or more running containers
tag Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE
top Display the running processes of a container
unpause Unpause all processes within one or more containers
update Update configuration of one or more containers
version Show the Docker version information
wait Block until one or more containers stop, then print their exit codes
للاطلاع على الخيارات المتاحة لأمر معين، اكتب:
docker docker-subcommand --help
لعرض معلومات النظام الكاملة حول Docker، استخدم ما يلي:
docker info
دعونا نستكشف بعض هذه الأوامر. سنبدأ بالعمل مع الصور.
الخطوة 4 - العمل مع صور Docker
تُبنى حاويات Docker من صور Docker. بشكل افتراضي، يسحب Docker هذه الصور من Docker Hub، وهو سجل Docker تديره شركة Docker، الشركة المسؤولة عن مشروع Docker. يمكن لأي شخص استضافة صور Docker الخاصة به على Docker Hub، لذا ستجد صورًا مُستضافة هناك لمعظم التطبيقات وتوزيعات Linux التي تحتاجها.
للتحقق مما إذا كان بإمكانك الوصول إلى الصور وتنزيلها من Docker Hub، اكتب ما يلي:
docker run hello-world
تُظهر النتائج أن برنامج Docker يعمل بشكل صحيح:
Output
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
0e03bdcc26d7: Pull complete
Digest: sha256:6a65f928fb91fcfbc963f7aa6d57c8eeb426ad9a20c7ee045538ef34847f44f1
Status: Downloaded newer image for hello-world:latest
Hello from Docker!
This message shows that your installation appears to be working correctly.
...لم يتمكن Docker في البداية من العثور على صورة hello-world محليًا، لذا قام بتنزيلها من Docker Hub، وهو المستودع الافتراضي. بعد تنزيل الصورة، أنشأ Docker حاويةً منها، ثم تم تشغيل التطبيق داخل الحاوية وعرض الرسالة.
يمكنك البحث عن الصور المتوفرة على Docker Hub باستخدام أمر docker مع الأمر الفرعي search. على سبيل المثال، للبحث عن صورة Ubuntu، اكتب:
docker search ubuntu
يقوم البرنامج النصي بفحص Docker Hub ويعرض قائمة بجميع الصور التي تتطابق أسماؤها مع عبارة البحث. في هذه الحالة، سيكون الناتج مشابهاً لما يلي:
Output
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 10908 [OK]
dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interface … 428 [OK]
rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 244 [OK]
consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 218 [OK]
ubuntu-upstart Upstart is an event-based replacement for th… 108 [OK]
ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with
...
في عمود "رسمي"، يشير "موافق" إلى صورة تم إنشاؤها ودعمها من قِبل الشركة القائمة على المشروع. بعد تحديد الصورة التي ترغب في استخدامها، يمكنك تنزيلها إلى جهاز الكمبيوتر الخاص بك باستخدام الأمر الفرعي "سحب".
قم بتشغيل الأمر التالي لتنزيل صورة أوبونتو الرسمية إلى جهاز الكمبيوتر الخاص بك:
docker pull ubuntu
سوف ترى الناتج التالي:
Output
Using default tag: latest
latest: Pulling from library/ubuntu
d51af753c3d3: Pull complete
fc878cd0a91c: Pull complete
6154df8ff988: Pull complete
fee5db0ff82f: Pull complete
Digest: sha256:747d2dbbaaee995098c9792d99bd333c6783ce56150d1b11e333bbceed5c54d7
Status: Downloaded newer image for ubuntu:latest
docker.io/library/ubuntu:latestبعد تنزيل الصورة، يمكنك تشغيل حاوية باستخدامها عبر الأمر الفرعي `run`. وكما رأيت في مثال "hello-world"، إذا لم يتم تنزيل الصورة عند تشغيل Docker باستخدام الأمر الفرعي `run`، يقوم عميل Docker أولاً بتنزيل الصورة، ثم يُشغّل حاوية باستخدامها.
لعرض الصور التي تم تنزيلها على جهاز الكمبيوتر الخاص بك، اكتب:
docker images
سيكون الناتج مشابهًا للشكل التالي:
Output
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 1d622ef86b13 3 weeks ago 73.9MB
hello-world latest bf756fb1ae65 4 months ago 13.3kBكما سترى لاحقًا في هذا البرنامج التعليمي، يمكن تعديل الصور التي تستخدمها لتشغيل الحاويات واستخدامها لإنتاج صور جديدة، والتي يمكن تحميلها إلى Docker Hub أو سجلات Docker الأخرى (هذا هو المصطلح التقني).
دعونا نستكشف كيفية عمل الحاويات بمزيد من التفصيل.
الخطوة 5 - تشغيل حاوية Docker
إن حاوية "hello-world" التي شغّلتها في الخطوة السابقة هي مثال على حاوية تعمل وتتوقف بعد إرسال رسالة اختبار. لكن الحاويات قد تكون أكثر فائدة من ذلك بكثير، ويمكن أن تكون تفاعلية. فهي في النهاية تشبه الآلات الافتراضية، ولكنها أكثر كفاءة في استخدام الموارد.
على سبيل المثال، لنقم بتشغيل حاوية باستخدام أحدث صورة لنظام أوبونتو. يمنحك الجمع بين الخيارين -i و -t إمكانية الوصول التفاعلي إلى واجهة سطر الأوامر الخاصة بالحاوية:
docker run -it ubuntu
يجب أن يتغير سطر الأوامر الخاص بك ليعكس حقيقة أنك تعمل الآن داخل حاوية، ويجب أن يبدو كالتالي:
Output
root@d9b100f2f636:/#لاحظ مُعرّف الحاوية في سطر الأوامر. في هذا المثال، هو d9b100f2f636. ستحتاج إلى مُعرّف الحاوية لاحقًا لتحديدها عند رغبتك في إزالتها.
الآن يمكنك تشغيل أي أمر داخل الحاوية. على سبيل المثال، لنقم بتحديث قاعدة بيانات الحزم داخل الحاوية. لست بحاجة إلى إضافة sudo قبل أي أمر، لأنك تعمل بصلاحيات المستخدم الجذر داخل الحاوية.
apt updateثم قم بتثبيت أي تطبيق فيه. لنقم بتثبيت Node.js:
apt install nodejs
سيتم تثبيت Node.js من مستودع أوبونتو الرسمي. بعد اكتمال التثبيت، تأكد من تثبيت Node.js.
node -v
سترى رقم الإصدار في نافذة الأوامر الخاصة بك:
Output
v10.19.0أي تغييرات تقوم بإجرائها داخل حاوية ستنطبق فقط على تلك الحاوية.
للخروج من الحاوية، اكتب exit في موجه الأوامر.
لننتقل الآن إلى إدارة الحاويات في نظامنا.
الخطوة 6 - إدارة حاويات دوكر
بعد استخدام Docker لفترة، ستجد العديد من الحاويات النشطة (قيد التشغيل) وغير النشطة على جهازك. لعرض الحاويات النشطة، استخدم الأمر التالي:
docker ps
سوف ترى إخراجًا مشابهًا لما يلي:
Output
CONTAINER ID IMAGE COMMAND CREATED
في هذا الدرس التعليمي، قمت بتشغيل حاويتين. واحدة من صورة hello-world والأخرى من صورة Ubuntu. لم تعد أي من الحاويتين تعمل، لكنهما لا تزالان موجودتين على نظامك.
لعرض جميع الحاويات - النشطة وغير النشطة، قم بتشغيل الأمر docker ps مع الخيار -a:
docker ps -a
سوف ترى إخراجًا مشابهًا لهذا:
1c08a7a0d0e4 ubuntu "/bin/bash" 2 minutes ago Exited (0) 8 seconds ago quizzical_mcnulty
a707221a5f6c hello-world "/hello" 6 minutes ago Exited (0) 6 minutes ago youthful_curie
لعرض آخر حاوية قمت بإنشائها، مرر إليها الخيار -l:
docker ps -l
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c08a7a0d0e4 ubuntu "/bin/bash" 2 minutes ago Exited (0) 40 seconds ago quizzical_mcnulty
لبدء تشغيل حاوية متوقفة، استخدم الأمر docker start متبوعًا بمعرّف الحاوية أو اسمها. لنبدأ تشغيل الحاوية التي تعمل بنظام أوبونتو والتي تحمل المعرّف 1c08a7a0d0e4:
docker start 1c08a7a0d0e4docker start 1c08a7a0d0e4
سيبدأ تشغيل الحاوية ويمكنك استخدام الأمر docker ps لعرض حالتها:
Output
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1c08a7a0d0e4 ubuntu "/bin/bash" 3 minutes ago Up 5 seconds quizzical_mcnulty
لإيقاف حاوية قيد التشغيل، استخدم الأمر docker stop متبوعًا بمعرّف الحاوية أو اسمها. سنستخدم هذه المرة الاسم الذي خصصه Docker للحاوية، وهو quizical_mcnulty.
docker stop quizzical_mcnulty
عندما تقرر أنك لم تعد بحاجة إلى الحاوية، قم بإزالتها باستخدام الأمر `docker rm`، مع استخدام مُعرّف الحاوية أو اسمها. استخدم الأمر `docker ps -a` للعثور على مُعرّف الحاوية أو اسمها المرتبط بصورة `hello-world` وإزالتها.
docker rm youthful_curie
يمكنك بدء حاوية جديدة وتسميتها باستخدام الخيار --name. كما يمكنك استخدام الخيار --rm لإنشاء حاوية تُحذف تلقائيًا بعد إيقافها. لمزيد من المعلومات حول هذه الخيارات وغيرها، راجع أمر المساعدة الخاص بتشغيل الأمر docker run.
يمكن تحويل الحاويات إلى صور يمكنك استخدامها لإنشاء حاويات جديدة. دعونا نرى كيف يتم ذلك.
الخطوة 7 - إجراء تغييرات على حاوية في صورة Docker
عند تشغيل صورة Docker، يمكنك إنشاء الملفات وتعديلها وحذفها تمامًا كما تفعل مع الآلة الافتراضية. تُطبّق التغييرات التي تُجريها على تلك الحاوية فقط. يمكنك تشغيلها وإيقافها، ولكن عند حذفها نهائيًا باستخدام أمر docker rm، تُفقد التغييرات إلى الأبد.
يوضح لك هذا القسم كيفية حفظ حالة الحاوية كصورة Docker جديدة.
بعد تثبيت Node.js داخل حاوية Ubuntu، أصبح لديك الآن حاوية قيد التشغيل من صورة، لكن هذه الحاوية تختلف عن الصورة التي استخدمتها لإنشائها. مع ذلك، قد ترغب في استخدام حاوية Node.js هذه كأساس لصور جديدة لاحقًا.
ثم قم بإجراء التغييرات على نسخة صورة Docker جديدة باستخدام الأمر التالي.
docker commit -m "What you did to the image" -a "Author Name" container_id repository/new_image_name
يُستخدم الخيار -m لعرض رسالة تأكيد تُساعدك أنت والآخرين على معرفة التغييرات التي أجريتها، بينما يُستخدم الخيار -a لتحديد المُنشئ. أما مُعرّف الحاوية (container_id) فهو المُعرّف الذي حددته سابقًا في هذا الدليل عند بدء جلسة Docker التفاعلية. ما لم تُنشئ مستودعات إضافية في Docker Hub، فسيكون هذا عادةً اسم مستخدم Docker Hub الخاص بك.
على سبيل المثال، بالنسبة للمستخدم sammy، الذي يحمل معرف الحاوية d9b100f2f636، سيكون الأمر كما يلي:
docker commit -m "added Node.js" -a "sammy" d9b100f2f636 sammy/ubuntu-nodejs
عند تحميل صورة، تُحفظ الصورة الجديدة محليًا على جهازك. لاحقًا في هذا الدرس، ستتعلم كيفية تحميل صورة إلى سجل Docker، مثل Docker Hub، ليتمكن الآخرون من الوصول إليها.
إعادة عرض صور Docker ستعرض الصورة الجديدة بالإضافة إلى الصورة القديمة التي اشتُقت منها:
docker images
سترى الناتج على النحو التالي:
Output
REPOSITORY TAG IMAGE ID CREATED SIZE
sammy/ubuntu-nodejs latest 7c1f35226ca6 7 seconds ago 179MB
...
في هذا المثال، ubuntu-nodejs هي صورة جديدة مُشتقة من صورة Ubuntu الموجودة على Docker Hub. يُشير اختلاف الحجم إلى التغييرات التي أُجريت. في هذا المثال، كان التغيير هو تثبيت NodeJS. لذا، في المرة القادمة التي تحتاج فيها إلى تشغيل حاوية باستخدام Ubuntu مع تثبيت NodeJS مُسبقًا، يُمكنك ببساطة استخدام الصورة الجديدة.
يمكنك أيضًا إنشاء صور من ملف Dockerfile، مما يسمح لك بأتمتة تثبيت البرامج في صورة جديدة. مع ذلك، فإن هذا خارج نطاق هذا الشرح.
والآن دعونا نشارك الصورة الجديدة مع الآخرين حتى يتمكنوا من إنشاء حاويات منها.
الخطوة 8 - نقل صور Docker إلى مستودع Docker
الخطوة المنطقية التالية بعد إنشاء صورة جديدة من صورة موجودة هي مشاركتها مع عدد محدود من أصدقائك، أو مع العالم أجمع على Docker Hub، أو مع أي من سجلات Docker الأخرى التي يمكنك الوصول إليها. لإرسال صورة إلى Docker Hub أو أي سجل Docker آخر، يجب أن يكون لديك حساب هناك.
يشرح هذا القسم كيفية رفع صورة Docker إلى Docker Hub. لمعرفة كيفية إنشاء سجل Docker خاص بك، راجع كيفية إعداد سجل Docker خاص على Ubuntu 18.04.
لرفع صورتك، قم أولاً بتسجيل الدخول إلى Docker Hub.
docker login -u docker-registry-username
سيُطلب منك المصادقة باستخدام كلمة مرور Docker Hub الخاصة بك. إذا أدخلت كلمة المرور الصحيحة، فستنجح عملية المصادقة.
ملاحظة: إذا كان اسم مستخدم سجل Docker الخاص بك مختلفًا عن اسم المستخدم المحلي الذي استخدمته لإنشاء الصورة، فستحتاج إلى وسم صورتك باسم مستخدم السجل الخاص بك. بالنسبة للمثال الموضح في الخطوة الأخيرة، ستكتب ما يلي:
docker tag sammy/ubuntu-nodejs docker-registry-username/ubuntu-nodejs
يمكنك بعد ذلك استخدام صورتك باستخدام:
docker push docker-registry-username/docker-image-name
لدفع صورة ubuntu-nodejs إلى مستودع Sami، سيكون الأمر كما يلي:
docker push sammy/ubuntu-nodejs
قد تستغرق عملية تحميل الصور بعض الوقت، ولكن بمجرد اكتمالها، سيبدو الناتج كالتالي:
Output
The push refers to a repository [docker.io/sammy/ubuntu-nodejs]
e3fbbfb44187: Pushed
5f70bf18a086: Pushed
a3b5c80a4eba: Pushed
7f18b442972b: Pushed
3ce512daaf78: Pushed
7aae4540b42d: Pushed
...بعد تحميل صورة إلى سجل، يجب أن تظهر في لوحة تحكم حسابك، كما هو موضح في الصورة أدناه.
إذا نتج عن محاولة الدفع هذا النوع من الخطأ، فمن المحتمل أنك لم تسجل الدخول:
Output
The push refers to a repository [docker.io/sammy/ubuntu-nodejs]
e3fbbfb44187: Preparing
5f70bf18a086: Preparing
a3b5c80a4eba: Preparing
7f18b442972b: Preparing
3ce512daaf78: Preparing
7aae4540b42d: Waiting
unauthorized: authentication requiredسجّل الدخول إلى حسابك في Docker وحاول الدفع مرة أخرى. ثم تأكد من وجوده في صفحة مستودع Docker Hub الخاصة بك.
يمكنك الآن استخدام الأمر docker pull sammy/ubuntu-nodejs لسحب الصورة إلى جهاز جديد واستخدامها لتشغيل حاوية جديدة.
نتيجة
في هذا الدرس، قمت بتثبيت Docker، والتعامل مع الصور والحاويات، ورفع صورة مُعدّلة إلى Docker Hub. الآن وقد تعرّفت على الأساسيات، استكشف دروس Docker الأخرى على مجتمع DigitalOcean.










