غيّر Docker طريقة بنائنا وشحننا وتشغيلنا للبرمجيات. بدلاً من "يعمل على جهازي"، يضمن Docker أن تطبيقك يعمل بنفس الطريقة في كل مكان - على حاسوبك المحمول، على جهاز زميلك، في CI/CD، وفي الإنتاج. في هذا الدليل، سننتقل من الصفر إلى نشر تطبيق حقيقي.
ما هو Docker؟
Docker هو منصة تحزم تطبيقك وجميع تبعياته في وحدة موحدة تسمى حاوية. الحاوية هي عملية معزولة وخفيفة الوزن تشارك نواة نظام التشغيل المضيف ولكن لها نظام ملفات وشبكة ومساحة عمليات خاصة بها.
الحاويات مقابل الأجهزة الافتراضية
| الجانب | الحاويات | الأجهزة الافتراضية |
|---|---|---|
| بدء التشغيل | ثوانٍ | دقائق |
| الحجم | ميغابايت | غيغابايت |
| نظام التشغيل | يشارك نواة المضيف | نظام تشغيل ضيف كامل |
| العزل | على مستوى العملية | على مستوى العتاد |
| الأداء | شبه أصلي | عبء إضافي من المراقب |
| الكثافة | مئات لكل مضيف | عشرات لكل مضيف |
تثبيت Docker
# macOS brew install --cask docker # Ubuntu/Debian curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER # Verify installation docker --version docker run hello-world
المفاهيم الأساسية
الصور
الصورة هي قالب للقراءة فقط يحتوي على تعليمات لإنشاء حاوية. فكر فيها كلقطة لتطبيقك وبيئته.
# Pull an image from Docker Hub docker pull node:20-alpine # List local images docker images # Remove an image docker rmi node:20-alpine
الحاويات
الحاوية هي نسخة قيد التشغيل من صورة. يمكنك إنشاء الحاويات وبدء تشغيلها وإيقافها وحذفها.
# Run a container docker run -d --name my-app -p 3000:3000 node:20-alpine # List running containers docker ps # List all containers (including stopped) docker ps -a # Stop a container docker stop my-app # Remove a container docker rm my-app # View logs docker logs my-app # Execute a command inside a running container docker exec -it my-app sh
كتابة Dockerfile
Dockerfile هو ملف نصي يحتوي على تعليمات لبناء صورة. كل تعليمة تنشئ طبقة.
Dockerfile أساسي لتطبيق Node.js
# Use an official Node.js runtime as base image FROM node:20-alpine # Set working directory WORKDIR /app # Copy package files first (better caching) COPY package.json package-lock.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Expose the port the app runs on EXPOSE 3000 # Command to run the application CMD ["node", "server.js"]
البناء والتشغيل
# Build the image docker build -t my-node-app . # Run the container docker run -d -p 3000:3000 my-node-app # Visit http://localhost:3000
البناء متعدد المراحل
البناء متعدد المراحل يبقي صور الإنتاج صغيرة عن طريق فصل بيئة البناء عن بيئة التشغيل.
# Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Production FROM node:20-alpine AS runner WORKDIR /app COPY /app/dist ./dist COPY /app/node_modules ./node_modules COPY /app/package.json ./ EXPOSE 3000 CMD ["node", "dist/server.js"]
ينتج عن هذا صورة تحتوي فقط على المخرجات المترجمة وتبعيات الإنتاج - بدون كود مصدري، بدون تبعيات تطوير، بدون أدوات بناء.
مثال متعدد المراحل لـ Next.js
FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci FROM node:20-alpine AS builder WORKDIR /app COPY /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY /app/public ./public COPY /app/.next/standalone ./ COPY /app/.next/static ./.next/static EXPOSE 3000 CMD ["node", "server.js"]
وحدات التخزين: البيانات الدائمة
بشكل افتراضي، تُفقد البيانات داخل الحاوية عند إزالة الحاوية. وحدات التخزين تحل هذه المشكلة.
# Create a named volume docker volume create my-data # Run with a volume docker run -d -v my-data:/app/data my-app # Bind mount (map host directory to container) docker run -d -v $(pwd)/data:/app/data my-app # List volumes docker volume ls
الشبكات
ينشئ Docker شبكات معزولة لتمكين الحاويات من التواصل.
# Create a custom network docker network create my-network # Run containers on the same network docker run -d --name api --network my-network my-api docker run -d --name db --network my-network postgres:16 # Containers can reach each other by name # From "api" container: postgres://db:5432
Docker Compose
يتيح لك Docker Compose تعريف وتشغيل تطبيقات متعددة الحاويات بملف YAML واحد.
docker-compose.yml
services: api: build: ./api ports: - "3000:3000" environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16-alpine environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=mydb volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" redis: image: redis:7-alpine ports: - "6379:6379" volumes: pgdata:
الأوامر
# Start all services docker compose up -d # View logs docker compose logs -f # Stop all services docker compose down # Rebuild and restart docker compose up -d --build # Scale a service docker compose up -d --scale api=3
.dockerignore
مثل .gitignore، يمنع هذا الملف نسخ الملفات غير الضرورية إلى الصورة.
node_modules .git .env *.md .next dist coverage
أفضل ممارسات الإنتاج
1. استخدم صور أساسية صغيرة
# Bad: 1GB+ FROM node:20 # Good: ~180MB FROM node:20-alpine
2. لا تشغّل كـ Root
FROM node:20-alpine RUN addgroup -S app && adduser -S app -G app USER app WORKDIR /home/app COPY . .
3. استخدم علامات صور محددة
# Bad: can change unexpectedly FROM node:latest # Good: pinned version FROM node:20.11-alpine3.19
4. استفد من ذاكرة التخزين المؤقت للبناء
رتب تعليمات Dockerfile من الأقل إلى الأكثر تغييراً:
FROM node:20-alpine WORKDIR /app # These change rarely - cached COPY package.json package-lock.json ./ RUN npm ci --only=production # This changes often - not cached COPY . .
5. فحوصات الصحة
HEALTHCHECK \ CMD wget -qO- http://localhost:3000/health || exit 1
6. استخدم متغيرات البيئة
ENV NODE_ENV=production ENV PORT=3000
ورقة مرجعية لأوامر Docker الشائعة
# Images docker build -t name:tag . # Build image docker images # List images docker rmi image_name # Remove image docker image prune # Remove unused images # Containers docker run -d -p 3000:3000 image # Run detached docker ps # List running docker stop container_name # Stop docker rm container_name # Remove docker logs -f container_name # Follow logs docker exec -it container sh # Shell into container # Compose docker compose up -d # Start services docker compose down # Stop services docker compose logs -f # Follow all logs docker compose ps # List services # Cleanup docker system prune -a # Remove everything unused
من Docker إلى Kubernetes
يدير Docker الحاويات الفردية. عندما تحتاج إلى تنسيق مئات الحاويات عبر خوادم متعددة، تحتاج إلى Kubernetes. Docker و Kubernetes متكاملان:
- Docker: يبني ويشغل الحاويات
- Kubernetes: ينسق الحاويات على نطاق واسع (الجدولة، التوسع، الإصلاح الذاتي)
إذا كنت مهتماً بالخطوة التالية، اطلع على مقالتي حول مقدمة في Kubernetes.
الخلاصة
Docker مهارة أساسية للمطورين المعاصرين. إنه يزيل التناقضات في البيئات، يبسط النشر، وهو الأساس لتنسيق الحاويات مع Kubernetes. ابدأ بـ Dockerfile بسيط، انتقل إلى Docker Compose للتطبيقات متعددة الخدمات، واعتمد البناء متعدد المراحل وأفضل ممارسات الأمان مع تقدمك.
أفضل طريقة لتعلم Docker هي حاوية مشروع تعمل عليه بالفعل. ابدأ اليوم.