الدليل العملي لتعلّم Docker للمبتدئين: من الحاويات إلى التطبيقات متعددة الخدمات
مقدمة: لماذا يُعد Docker مهارة أساسية اليوم؟
رغم أن مفهوم الحاويات البرمجية ليس جديداً، فإن ظهور Docker Engine جعل عملية تغليف التطبيقات وتشغيلها أسهل بكثير وأكثر عملية. بفضل هذا التحول، أصبح بالإمكان تشغيل التطبيق مع جميع اعتمادياته داخل بيئة معزولة وقابلة للنقل، بدلاً من إعادة إعداد كل شيء يدوياً على كل جهاز أو خادم.
تكمن أهمية Docker في أنه يختصر كثيراً من التعقيد الذي يواجه المطورين عند اختلاف أنظمة التشغيل أو إصدارات الأدوات أو طريقة النشر. وبعد إتقان أساسياته، ستتمكن من:
- تغليف معظم التطبيقات داخل حاويات قابلة للتشغيل.
- إنشاء صور مخصصة ورفعها إلى مستودعات صور عبر الإنترنت.
- إدارة عدة حاويات معاً باستخدام
Docker Compose. - بناء بيئات تطوير وإنتاج متسقة وسهلة التكرار.

المتطلبات المسبقة قبل البدء
- إلمام جيد باستخدام الطرفية في
Linux. - معرفة أساسية بلغة
JavaScriptلبعض الأمثلة التطبيقية المتقدمة.
ما هي الحاويات البرمجية Containerization؟
تشير الحاويات البرمجية إلى تغليف التطبيق مع مكتباته واعتمادياته وإعداداته الضرورية داخل حزمة موحدة تعمل بنفس السلوك تقريباً في أي بيئة. الفكرة هنا ليست مجرد نقل الملفات، بل ضمان أن التطبيق سيعمل بالشكل نفسه على جهاز المطور، وعلى جهاز زميله، وعلى خادم الإنتاج.
تخيّل أنك طورت تطبيقاً لإدارة الكتب باستخدام:
Node.jsExpress.jsSQLite3
نظرياً يبدو هذا كافياً، لكن عملياً قد تحتاج أيضاً إلى أدوات بناء مثل node-gyp، ووجود Python، وسلسلة أدوات C/C++. هنا تبدأ مشكلات التثبيت واختلاف المنصات، خصوصاً بين Windows وmacOS وLinux.
الحاويات تحل هذه الفوضى عبر ثلاث ركائز أساسية:
- تشغيل التطبيق داخل بيئة معزولة تسمى
Container. - تجميع التطبيق في ملف قابل للتوزيع يسمى
Image. - مشاركة الصور عبر مستودع مركزي يسمى
Registry.
ما هو Docker تحديداً؟
Docker هو منصة مفتوحة المصدر لتطبيق مفهوم الحاويات عملياً. يتيح لك إنشاء الحاويات، وبناء الصور، ونشرها، وسحبها من المستودعات العامة أو الخاصة، وربط عدة خدمات معاً بسهولة.
صحيح أن Docker ليس الأداة الوحيدة في هذا المجال، فهناك أدوات مثل Podman وKaniko وغيرها، لكنه يظل الخيار الأكثر شيوعاً وانتشاراً في بيئات التطوير الحديثة.
تثبيت Docker على الأنظمة المختلفة
تثبيت Docker على macOS
يُعد التثبيت على macOS من أبسط الحالات. يكفي تنزيل التطبيق الرسمي، ثم سحب أيقونته إلى مجلد التطبيقات وتشغيله.

![]()
بعد التشغيل، تحقق من نجاح التثبيت بالأمرين التاليين:
docker --version
docker-compose --version
تثبيت Docker على Windows
في Windows تحتاج أولاً إلى تفعيل WSL2، ثم تثبيت Docker Desktop. بعد اكتمال العملية، يمكن تشغيله من قائمة ابدأ أو من سطح المكتب.
![]()

للتحقق من نجاح التثبيت:
docker --version
docker-compose --version
تثبيت Docker على Linux
في Linux يختلف التثبيت باختلاف التوزيعة، لكن الفكرة متشابهة: تثبيت Docker Engine ثم تثبيت Docker Compose بشكل مستقل عند الحاجة.
بعد انتهاء التثبيت، تحقق من الإصدارات:
docker --version
docker-compose --version

أول تجربة: تشغيل Hello World في Docker
بعد تثبيت Docker، جرّب أول حاوية لك بالأمر التالي:
docker run hello-world
هذه الصورة البسيطة تؤكد أن العميل Docker Client استطاع التواصل مع الخدمة الخلفية Docker Daemon، ثم سحب الصورة من Docker Hub وتشغيل الحاوية بنجاح.
ولعرض الحاويات الحالية والسابقة:
docker ps -a
المفاهيم الأساسية في Docker
ما هي الحاوية Container؟
الحاوية هي بيئة تشغيل معزولة على مستوى التطبيق، تحتوي على الكود والاعتماديات اللازمة. وهي أخف بكثير من الآلات الافتراضية Virtual Machines لأنها لا تحمل نظام تشغيل ضيفاً كاملاً، بل تشارك نواة النظام المضيف.
هذا الفارق يمنح الحاويات سرعة أعلى واستهلاكاً أقل للموارد، مع الاحتفاظ بدرجة ممتازة من العزل.
مثال يثبت أن الحاوية تستخدم نواة النظام المضيف:
uname -a
docker run alpine uname -a
ما هي الصورة Docker Image؟
الصورة هي قالب جاهز متعدد الطبقات يُستخدم لإنشاء الحاويات. يمكن اعتبارها نسخة ثابتة وقابلة للتوزيع من التطبيق. وعند تشغيلها، يضيف Docker طبقة كتابة جديدة فوق طبقات الصورة الأصلية.
ما هو المستودع Docker Registry؟
المستودع هو المكان الذي تُخزَّن فيه الصور وتُشارك مع الآخرين. أشهر مثال هو Docker Hub، كما توجد بدائل مثل Quay، ويمكنك أيضاً إنشاء مستودعك الخاص للصور الداخلية.


معمارية Docker باختصار
تتكون المنصة من ثلاثة أجزاء رئيسية:
Docker Daemon: الخدمة الخلفية المسؤولة عن بناء الصور وتشغيل الحاويات وإدارتها.Docker Client: واجهة سطر الأوامر التي يكتب عبرها المستخدم الأوامر.REST API: الجسر الذي يمر عبره التواصل بين العميل والخدمة الخلفية.
عند تنفيذ أمر مثل docker run hello-world، يرسل العميل الطلب إلى الخدمة الخلفية، فتبحث عن الصورة محلياً، وإن لم تجدها تسحبها من المستودع ثم تنشئ الحاوية وتشغلها.
أساسيات التعامل مع الحاويات
تشغيل حاوية
docker container run <image-name>
مثال عملي:
docker container run --publish 8080:80 fhsinchy/hello-dock
نشر المنافذ Port Publishing
لأن الحاويات معزولة، لا يمكن الوصول إلى التطبيق داخلها من الخارج إلا عبر نشر منفذ:
--publish <host-port>:<container-port>
مثال:
docker container run --publish 8080:80 fhsinchy/hello-dock
ثم افتح العنوان http://127.0.0.1:8080.

التشغيل في الخلفية Detached Mode
docker container run --detach --publish 8080:80 fhsinchy/hello-dock
يعمل هذا الخيار على إبقاء الحاوية قيد التشغيل في الخلفية دون ربطها بالطرفية الحالية.
عرض الحاويات
docker container ls
docker container ls --all
تسمية الحاويات وإعادة تسميتها
docker container run --detach --publish 8888:80 --name hello-dock-container fhsinchy/hello-dock
docker container rename gifted_sammet hello-dock-container-2
إيقاف الحاويات أو قتلها
docker container stop hello-dock-container
docker container kill hello-dock-container-2
إعادة تشغيل الحاويات
docker container start hello-dock-container
docker container restart hello-dock-container-2
إنشاء حاوية دون تشغيلها
docker container create --publish 8080:80 fhsinchy/hello-dock
docker container start hello-dock
حذف الحاويات المتوقفة
docker container rm <container-id>
docker container prune
التشغيل التفاعلي
docker container run --rm -it ubuntu
يسمح الخيار -it بالتفاعل مع الصدفة داخل الحاوية.
تنفيذ أوامر داخل الحاوية
docker container run alpine uname -a
docker container run --rm busybox sh -c "echo -n my-secret | base64"
الصور في Docker: الإنشاء والإدارة
إنشاء صورة مخصصة
الخطوة الأساسية هي كتابة ملف Dockerfile يصف الحالة النهائية للصورة.
FROM ubuntu:latest
EXPOSE 80
RUN apt-get update && \
apt-get install nginx -y && \
apt-get clean && rm -rf /var/lib/apt/lists/*
CMD ["nginx", "-g", "daemon off;"]
لبناء الصورة:
docker image build .
إضافة وسم Tag للصورة
docker image build --tag custom-nginx:packaged .
عرض الصور وحذفها
docker image ls
docker image rm custom-nginx:packaged
docker image prune --force
فهم الطبقات داخل الصورة
docker image history custom-nginx:packaged
كل تعليمة في Dockerfile تنشئ طبقة جديدة. هذه البنية الطبقية تسهّل إعادة الاستخدام والتخزين المؤقت Cache وتقلل التكرار أثناء البناء.
بناء NGINX من المصدر
يمكنك تجاوز تثبيت الحزمة الجاهزة وبناء NGINX من الشيفرة المصدرية باستخدام تعليمات مثل COPY وADD وARG.
FROM ubuntu:latest
RUN apt-get update && \
apt-get install build-essential libpcre3 libpcre3-dev zlib1g zlib1g-dev libssl-dev -y && \
apt-get clean && rm -rf /var/lib/apt/lists/*
ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"
ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
RUN tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION}
RUN cd ${FILENAME} && \
./configure --sbin-path=/usr/bin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-pcre --pid-path=/var/run/nginx.pid --with-http_ssl_module && \
make && make install
RUN rm -rf /${FILENAME}
CMD ["nginx", "-g", "daemon off;"]
تحسين الصور وتقليل الحجم
الصورة العاملة ليست بالضرورة صورة جيدة. من أهم مبادئ التحسين:
- تقليل الحزم غير الضرورية بعد البناء.
- دمج الخطوات في تعليمة
RUNواحدة عندما يكون ذلك مفيداً. - اختيار صورة أساسية خفيفة.
استخدام Alpine Linux مثال ممتاز على ذلك، إذ يمنحك صوراً أخف بكثير من Ubuntu.
FROM alpine:latest
EXPOSE 80
ARG FILENAME="nginx-1.19.2"
ARG EXTENSION="tar.gz"
ADD https://nginx.org/download/${FILENAME}.${EXTENSION} .
RUN apk add --no-cache pcre zlib && \
apk add --no-cache --virtual .build-deps build-base pcre-dev zlib-dev openssl-dev && \
tar -xvf ${FILENAME}.${EXTENSION} && rm ${FILENAME}.${EXTENSION} && \
cd ${FILENAME} && \
./configure --sbin-path=/usr/bin/nginx --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --with-pcre --pid-path=/var/run/nginx.pid --with-http_ssl_module && \
make && make install && \
cd / && rm -rf /${FILENAME} && \
apk del .build-deps
CMD ["nginx", "-g", "daemon off;"]
إنشاء صور تنفيذية Executable Images
يمكن تحويل الصورة إلى أداة تنفيذية تشبه البرامج الطرفية المعتادة عبر تعليمة ENTRYPOINT.
FROM python:3-alpine
WORKDIR /zone
RUN apk add --no-cache git && \
pip install git+https://github.com/fhsinchy/rmbyext.git#egg=rmbyext && \
apk del git
ENTRYPOINT ["rmbyext"]
رفع الصور إلى الإنترنت
لمشاركة صورك عبر Docker Hub، سجّل الدخول أولاً:
docker login
ثم ابنِ الصورة مع وسم يتضمن اسم المستخدم:
docker image build --tag your-username/custom-nginx:latest .
وأخيراً ارفعها:
docker image push your-username/custom-nginx:latest
تغليف تطبيق JavaScript داخل Docker
كتابة Dockerfile للتطوير
FROM node:lts-alpine
EXPOSE 3000
USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
COPY ./package.json .
RUN npm install
COPY . .
CMD ["npm", "run", "dev"]
لبناء الصورة:
docker image build --file Dockerfile.dev --tag hello-dock:dev .
ولتشغيلها:
docker container run --rm --detach --publish 3000:3000 --name hello-dock-dev hello-dock:dev

استخدام Bind Mounts
لتمكين التحديث الفوري Hot Reload أثناء التطوير، اربط مجلد المشروع المحلي بمجلد العمل داخل الحاوية:
docker container run \
--rm \
--publish 3000:3000 \
--name hello-dock-dev \
--volume $(pwd):/home/node/app \
hello-dock:dev
لكن هذه الخطوة قد تستبدل مجلد node_modules داخل الحاوية، ما يسبب أخطاء في التشغيل.
استخدام الأحجام المجهولة Anonymous Volumes
لحل مشكلة node_modules:
docker container run \
--rm \
--detach \
--publish 3000:3000 \
--name hello-dock-dev \
--volume $(pwd):/home/node/app \
--volume /home/node/app/node_modules \
hello-dock:dev
البناء متعدد المراحل Multi-stage Builds
في بيئة الإنتاج، من الأفضل بناء التطبيق باستخدام Node.js ثم نسخ الملفات النهائية إلى صورة NGINX خفيفة:
FROM node:lts-alpine as builder
WORKDIR /app
COPY ./package.json ./
RUN npm install
COPY . .
RUN npm run build
FROM nginx:stable-alpine
EXPOSE 80
COPY --from=builder /app/dist /usr/share/nginx/html
هذه الطريقة تجعل الصورة النهائية أصغر وأكثر أماناً.

تجاهل الملفات غير الضرورية عبر .dockerignore
.git
*Dockerfile*
*docker-compose*
node_modules
هذا الملف يقلل حجم سياق البناء Build Context ويحسن سرعة الإنشاء.
أساسيات الشبكات في Docker
عند تشغيل أكثر من حاوية داخل مشروع واحد، تصبح الشبكات جزءاً محورياً من التصميم. القاعدة الذهبية هي استخدام شبكة من نوع User-defined Bridge حتى تتمكن الحاويات من الوصول إلى بعضها بأسمائها.
عرض الشبكات
docker network ls
إنشاء شبكة مخصصة
docker network create skynet
ربط حاوية بشبكة
docker network connect skynet hello-dock
أو أثناء التشغيل:
docker container run --network skynet --rm --name alpine-box -it alpine sh
داخل الحاوية، يمكنك اختبار الوصول:
ping hello-dock
فصل الحاوية عن الشبكة
docker network disconnect skynet hello-dock
حذف الشبكة
docker network rm skynet
تغليف تطبيق متعدد الحاويات: API مع قاعدة بيانات
تشغيل قاعدة البيانات
docker container run \
--detach \
--name=notes-db \
--env POSTGRES_DB=notesdb \
--env POSTGRES_PASSWORD=secret \
--network=notes-api-network \
postgres:12
استخدام الأحجام المسماة Named Volumes
docker volume create notes-db-data
ثم ربطه بحاوية قاعدة البيانات:
docker container run \
--detach \
--volume notes-db-data:/var/lib/postgresql/data \
--name=notes-db \
--env POSTGRES_DB=notesdb \
--env POSTGRES_PASSWORD=secret \
--network=notes-api-network \
postgres:12
قراءة السجلات Logs
docker container logs notes-db
بناء صورة API
FROM node:lts-alpine as builder
RUN apk add --no-cache python make g++
WORKDIR /app
COPY ./package.json .
RUN npm install --only=prod
FROM node:lts-alpine
EXPOSE 3000
ENV NODE_ENV=production
USER node
RUN mkdir -p /home/node/app
WORKDIR /home/node/app
COPY . .
COPY --from=builder /app/node_modules /home/node/app/node_modules
CMD ["node", "bin/www"]
ثم شغّل الخدمة:
docker container run \
--detach \
--name=notes-api \
--env DB_HOST=notes-db \
--env DB_DATABASE=notesdb \
--env DB_PASSWORD=secret \
--publish=3000:3000 \
--network=notes-api-network \
notes-api

تنفيذ أوامر داخل حاوية تعمل
docker container exec notes-api npm run db:migrate
وللدخول التفاعلي إلى الحاوية:
docker container exec -it notes-api sh
إدارة المشاريع متعددة الخدمات باستخدام Docker Compose
بدلاً من كتابة سلسلة طويلة من الأوامر يدوياً، يوفّر Docker Compose طريقة عملية لوصف وتشغيل المشروع كاملًا عبر ملف YAML واحد.
ملف docker-compose.yaml أساسي
version: "3.8"
services:
db:
image: postgres:12
container_name: notes-db-dev
volumes:
- notes-db-dev-data:/var/lib/postgresql/data
environment:
POSTGRES_DB: notesdb
POSTGRES_PASSWORD: secret
api:
build:
context: ./api
dockerfile: Dockerfile.dev
image: notes-api:dev
container_name: notes-api-dev
environment:
DB_HOST: db
DB_DATABASE: notesdb
DB_PASSWORD: secret
volumes:
- /home/node/app/node_modules
- ./api:/home/node/app
ports:
- 3000:3000
volumes:
notes-db-dev-data:
name: notes-db-dev-data
تشغيل الخدمات
docker-compose --file docker-compose.yaml up --detach
عرض الخدمات
docker-compose ps
تنفيذ أمر داخل خدمة تعمل
docker-compose exec api npm run db:migrate
عرض السجلات
docker-compose logs api
إيقاف الخدمات وإزالتها
docker-compose down --volumes
بناء تطبيق Full-stack باستخدام Docker Compose
في المشاريع الأكبر، قد تحتاج إلى خدمات أمامية وخلفية وموجّه طلبات Router مثل NGINX. هنا تصبح الشبكات المتعددة مفيدة جداً للفصل بين الواجهة وقاعدة البيانات والطبقة الوسيطة.
مثال على ملف Dockerfile لخدمة NGINX:
FROM nginx:stable-alpine
COPY ./development.conf /etc/nginx/conf.d/default.conf
ومثال على تعريف الشبكات داخل docker-compose.yaml:
networks:
frontend:
name: fullstack-notes-application-network-frontend
driver: bridge
backend:
name: fullstack-notes-application-network-backend
driver: bridge
بهذا الأسلوب يمكن جعل خدمة nginx متصلة بالشبكتين معاً لتوجيه الطلبات بين الواجهة الأمامية والخلفية بكفاءة.

روابط الشيفرة المصدرية
- مشاريع الأمثلة:
https://github.com/fhsinchy/docker-handbook-projects/ - المحتوى المفتوح للكتاب:
https://github.com/fhsinchy/the-docker-handbook - نسخة محدثة باستمرار:
https://docker-handbook.farhan.dev/ - النسخة المنشورة:
https://www.freecodecamp.org/news/the-docker-handbook/
الخلاصة التقنية
إذا أردنا تلخيص Docker في فكرة واحدة، فهي: توحيد بيئة التشغيل وتقليل المفاجآت. فبدلاً من أن يكون نشر التطبيق عملية حساسة مليئة بالفروقات بين الأجهزة، تصبح العملية قابلة للتكرار وموثوقة وواضحة. من الناحية التقنية، فإن أكثر ما يصنع الفارق الحقيقي ليس فقط تشغيل الحاويات، بل فهم الصور والطبقات والأحجام والشبكات والبناء متعدد المراحل. هذا الفهم هو ما يحوّل استخدام Docker من مجرد أوامر محفوظة إلى مهارة هندسية مؤثرة في جودة التطوير والنشر والإنتاج.