Docker: تدريب عملي شامل
آخر تحديث: 2026-08-26
هذا هو المشروع النهائي لهذه الدورة — يجمع المعرفة من جميع الدروس الـ 23 لنشر microservice كامل من الصفر إلى بيئة الإنتاج.
1. ما ستتعلمه
- تصميم بنية Microservices كاملة
- تطوير عملي متعدد المراحل من البداية إلى النهاية
- تنسيق متعدد الخدمات باستخدام Compose
- نشر CI/CD آلي
- إعداد نظام المراقبة والتنبيهات
2. قصة تسليم في 3 أيام
(1) التحدي: الانتقال من المحلي إلى الإنتاج في 3 أيام
كُلف تشارلي بمهمة: نشر منصة تجارة إلكترونية من التطوير المحلي إلى بيئة الإنتاج في ثلاثة أيام. تتكون البنية من واجهة React أمامية، Go API، PostgreSQL، Redis، و RabbitMQ — خمس خدمات وصفر عمليات آلية.
(2) حل لأدوات Docker الشاملة
استخدم تشارلي أدوات Docker الشاملة لإكمال المشروع في يومين: كتابة Dockerfile ← التنسيق بـ Compose ← نشر CI/CD آلي ← المراقبة والتنبيهات.
(3) الفائدة: اكتمل وتم التسليم في يومين
من النشر اليدوي إلى الأتمتة الكاملة، أكملنا تصميم البنية، التحويل إلى حاويات، التنسيق، CI/CD، والمراقبة في يومين فقط — هذه هي قيمة إتقان مهارات Docker الشاملة.
3. تصميم البنية الشاملة
(1) نظرة عامة على البنية
graph TB
USER["المتصفح"] --> ING["Nginx<br/>:80<br/>React SPA + وكيل API"]
ING -->|"api/"| API1["Go API #1<br/>:8080"]
ING -->|"api/"| API2["Go API #2<br/>:8080"]
ING -->|"api/"| API3["Go API #3<br/>:8080"]
API1 --> PG["PostgreSQL<br/>:5432<br/>قاعدة البيانات الرئيسية"]
API2 --> PG
API3 --> PG
API1 --> REDIS["Redis<br/>:6379<br/>ذاكرة تخزين مؤقت"]
API2 --> REDIS
API3 --> MQ["RabbitMQ<br/>:5672<br/>طابور الرسائل"]
MQ --> WRK["Worker<br/>مهام خلفية"]
PROM["Prometheus<br/>:9090<br/>مقاييس"] --> GRAF["Grafana<br/>:3000<br/>لوحات المعلومات"]
PROM --> API1
PROM --> PG
PROM --> REDIS
(2) قائمة الخدمات
| الخدمة | مجموعة التقنيات | الصور | المنافذ |
|---|---|---|---|
| Nginx | وكيل عكسي + ملفات ثابتة | مستضافة ذاتيًا (متعددة المراحل) | 80 |
| Go API | REST API | مستضافة ذاتيًا (متعددة المراحل) | 8080 |
| PostgreSQL | قاعدة بيانات علائقية | postgres:15-alpine | 5432 |
| Redis | ذاكرة تخزين مؤقت + جلسات | redis:7-alpine | 6379 |
| RabbitMQ | طابور الرسائل | rabbitmq:3-management | 5672/15672 |
| Worker | معالجة المهام الخلفية | مستضافة ذاتيًا (نفس صورة API) | - |
| Prometheus | جمع المقاييس | prom/prometheus | 9090 |
| Grafana | لوحة معلومات مرئية | grafana/grafana | 3000 |
4. Dockerfile الواجهة الأمامية (React + Nginx)
▶ مثال: بناء متعدد المراحل لـ Dockerfile الواجهة الأمامية (الصعوبة: ⭐⭐⭐)
DOCKERFILE
# ============================================
# المرحلة 1: بناء تطبيق React
# ============================================
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# ============================================
# المرحلة 2: الخدمة باستخدام Nginx
# ============================================
FROM nginx:1.25-alpine
# نسخ ملفات البناء
COPY --from=builder /app/dist /usr/share/nginx/html
# نسخ تكوين Nginx لتوجيه SPA
COPY nginx.conf /etc/nginx/conf.d/default.conf
# الأمان: مستخدم غير root
RUN chown -R nginx:nginx /usr/share/nginx/html && \
chown -R nginx:nginx /var/cache/nginx && \
chown -R nginx:nginx /var/log/nginx
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=5s \
CMD wget -qO- http://localhost/ || exit 1
CMD ["nginx", "-g", "daemon off;"]
5. Dockerfile الخلفية (Go متعدد المراحل)
▶ مثال: بناء متعدد المراحل لـ Dockerfile الخلفية (الصعوبة: ⭐⭐⭐)
DOCKERFILE
# ============================================
# المرحلة 1: ترجمة برنامج Go الثنائي
# ============================================
FROM golang:1.22-alpine AS builder
RUN apk add --no-cache git
WORKDIR /src
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -ldflags="-w -s" -o /app/server
# ============================================
# المرحلة 2: وقت تشغيل أدنى
# ============================================
FROM alpine:3.19
RUN apk --no-cache add ca-certificates tzdata curl && \
adduser -D -u 1000 appuser
WORKDIR /app
COPY --from=builder /app/server .
RUN chown -R appuser:appuser /app
USER appuser
EXPOSE 8080
HEALTHCHECK --interval=15s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost:8080/health || exit 1
CMD ["/app/server"]
6. تنسيق Docker Compose
▶ مثال: docker-compose.prod.yml كامل (الصعوبة: ⭐⭐⭐)
YAML
# ============================================
# docker-compose.prod.yml - Full stack
# ============================================
services:
nginx:
build:
context: ./frontend
dockerfile: Dockerfile
ports:
- "80:80"
depends_on:
api:
condition: service_healthy
restart: unless-stopped
networks:
- frontend
- backend
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
api:
build:
context: ./api
dockerfile: Dockerfile
environment:
DATABASE_URL: postgresql://appuser:${DB_PASSWORD}@postgres:5432/${DB_NAME}
REDIS_URL: redis://redis:6379
RABBITMQ_URL: amqp://guest:${MQ_PASSWORD}@rabbitmq:5672
deploy:
replicas: 3
resources:
limits:
cpus: "1.0"
memory: 512M
depends_on:
postgres:
condition: service_healthy
redis:
condition: service_healthy
restart: unless-stopped
networks:
- backend
- db-net
- cache-net
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
interval: 15s
timeout: 5s
retries: 3
start_period: 10s
logging:
driver: json-file
options:
max-size: "10m"
max-file: "5"
worker:
build:
context: ./api
dockerfile: Dockerfile
command: ["/app/server", "worker"]
environment:
DATABASE_URL: postgresql://appuser:${DB_PASSWORD}@postgres:5432/${DB_NAME}
RABBITMQ_URL: amqp://guest:${MQ_PASSWORD}@rabbitmq:5672
depends_on:
postgres:
condition: service_healthy
rabbitmq:
condition: service_healthy
restart: unless-stopped
networks:
- backend
- db-net
postgres:
image: postgres:15-alpine
environment:
POSTGRES_USER: appuser
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: ${DB_NAME}
volumes:
- pg-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U appuser"]
interval: 5s
timeout: 5s
retries: 5
restart: unless-stopped
networks:
- db-net
redis:
image: redis:7-alpine
command: redis-server --appendonly yes --requirepass ${REDIS_PASSWORD}
volumes:
- redis-data:/data
healthcheck:
test: ["CMD", "redis-cli", "-a", "${REDIS_PASSWORD}", "ping"]
interval: 10s
timeout: 5s
restart: unless-stopped
networks:
- cache-net
rabbitmq:
image: rabbitmq:3-management-alpine
environment:
RABBITMQ_DEFAULT_PASS: ${MQ_PASSWORD}
ports:
- "15672:15672"
volumes:
- mq-data:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"]
interval: 15s
timeout: 10s
restart: unless-stopped
networks:
- backend
prometheus:
image: prom/prometheus:latest
volumes:
- ./monitoring/prometheus.yml:/etc/prometheus/prometheus.yml:ro
- prometheus-data:/prometheus
ports:
- "9090:9090"
restart: unless-stopped
networks:
- backend
- db-net
- cache-net
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
GF_SECURITY_ADMIN_PASSWORD: ${GRAFANA_PASSWORD}
volumes:
- grafana-data:/var/lib/grafana
depends_on:
- prometheus
restart: unless-stopped
networks:
- backend
volumes:
pg-data:
redis-data:
mq-data:
prometheus-data:
grafana-data:
networks:
frontend:
backend:
db-net:
internal: true
cache-net:
internal: true
7. تكوين CI/CD
(1) مسار GitHub Actions الكامل
YAML
# .github/workflows/deploy.yml
name: Build and Deploy
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ${{ secrets.REGISTRY }}
username: ${{ secrets.REGISTRY_USER }}
password: ${{ secrets.REGISTRY_PASS }}
- name: Build and push API
uses: docker/build-push-action@v5
with:
context: ./api
push: true
tags: ${{ secrets.REGISTRY }}/api:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Build and push Frontend
uses: docker/build-push-action@v5
with:
context: ./frontend
push: true
tags: ${{ secrets.REGISTRY }}/frontend:${{ github.sha }}
cache-from: type=gha
cache-to: type=gha,mode=max
- name: Deploy to production
uses: appleboy/ssh-action@v1
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SSH_KEY }}
script: |
cd /opt/ecommerce
export API_TAG=${{ github.sha }}
export FRONTEND_TAG=${{ github.sha }}
docker compose -f docker-compose.prod.yml pull
docker compose -f docker-compose.prod.yml up -d --remove-orphans
docker image prune -f
8. تكوين المراقبة
(1) تكوين Prometheus
YAML
# monitoring/prometheus.yml
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'api'
static_configs:
- targets: ['api:8080']
metrics_path: /metrics
- job_name: 'postgres'
static_configs:
- targets: ['postgres-exporter:9187']
- job_name: 'redis'
static_configs:
- targets: ['redis-exporter:9121']
- job_name: 'rabbitmq'
static_configs:
- targets: ['rabbitmq:15692']
9. النشر والتحقق
(1) قائمة التحقق من النشر
| الخطوة | الإجراء | التحقق |
|---|---|---|
| 1 | docker compose -f docker-compose.prod.yml up -d --build |
docker compose ps الكل Up |
| 2 | زيارة http://localhost |
صفحة React تظهر بشكل صحيح |
| 3 | curl http://localhost/api/health |
{"status":"ok"} |
| 4 | زيارة http://localhost:3000 |
صفحة تسجيل الدخول Grafana |
| 5 | زيارة http://localhost:15672 |
صفحة إدارة RabbitMQ |
| 6 | docker compose logs api |
لا أخطاء في سجلات API |
(2) جدول المقارنة: Bare Metal مقابل Docker مقابل K8s
| البُعد | النشر على المعدن مباشرة | Docker Compose | Kubernetes |
|---|---|---|---|
| وقت النشر | 1–2 يوم | 30 دقيقة | 1–2 يوم (الإعداد الأولي) |
| قابلية التكرار | ❌ | ✅ | ✅ |
| التوسع التلقائي | ❌ | ❌ | ✅ HPA |
| الشفاء الذاتي | ❌ | سياسة إعادة التشغيل | ✅ إعادة بناء تلقائية |
| تحديثات بدون توقف | صعب | إعادة تشغيل Compose | ✅ تحديثات متدرجة |
| المراقبة | يدوي | Prometheus+Grafana | مدمجة + Prometheus |
| التعقيد | منخفض | متوسط | عالٍ |
10. مثال كامل: نشر Full-Stack بنقرة واحدة
BASH
# ============================================
# شرح كامل: نشر Full-Stack
# ============================================
# 1. إنشاء ملف .env (لا تقم أبدًا بـ commit لهذا الملف)
cat > .env << 'EOF'
DB_PASSWORD=secure_db_pass_2024
DB_NAME=ecommerce
REDIS_PASSWORD=secure_redis_pass
MQ_PASSWORD=secure_mq_pass
GRAFANA_PASSWORD=admin123
EOF
# 2. بناء وبدء جميع الخدمات
docker compose -f docker-compose.prod.yml up -d --build
# 3. انتظار تهيئة الخدمات
sleep 30
# 4. التحقق من جميع الخدمات
docker compose -f docker-compose.prod.yml ps
echo "=== Health Checks ==="
docker compose -f docker-compose.prod.yml ps --format "table {{.Name}}\t{{.Status}}"
# 5. اختبار API
curl -s http://localhost/api/health
# 6. التحقق من اتصال قاعدة البيانات
docker compose -f docker-compose.prod.yml exec postgres pg_isready -U appuser
# 7. الوصول إلى المراقبة
echo "Grafana: http://localhost:3000 (admin/${GRAFANA_PASSWORD})"
echo "RabbitMQ: http://localhost:15672 (guest/${MQ_PASSWORD})"
echo "Prometheus: http://localhost:9090"
# 8. عرض السجلات المجمعة
docker compose -f docker-compose.prod.yml logs --tail 50 api
# 9. توسيع API إذا لزم الأمر
docker compose -f docker-compose.prod.yml up -d --scale api=5
# 10. التنظيف
docker compose -f docker-compose.prod.yml down
❓ أسئلة شائعة
س ما مدى تعقيد microservices مقارنة بالبنية المتجانسة؟
ج يزداد التعقيد التشغيلي بشكل كبير — تكوين الشبكة، اكتشاف الخدمات، تجميع السجلات، والتتبع الموزع كلها تمثل تحديات جديدة. ومع ذلك، تشمل الفوائد النشر المستقل، التوسع المستقل، وعزل الأعطال. توصية: الفرق الصغيرة (<5 أشخاص) يجب أن تستخدم بنية متجانسة معيارية، بينما الفرق الأكبر يجب أن تستخدم microservices. لا تتبنى microservices لمجرد التبني.
س كيف تنفذ ترحيل قاعدة البيانات في CI/CD؟
ج أضف خطوات الترحيل قبل خطوات النشر: ① بناء صورة الترحيل؛ ②
docker run --rm migrate:latest alembic upgrade head؛ ③ نشر الإصدار الجديد. نقطة رئيسية: يجب أن تكون الترحيلات متوافقة مع الإصدارات السابقة — يجب أن يدعم الكود الجديد هيكلي الجدول القديم والجديد.س كيف يمكن دمج سجلات الخدمات المتعددة؟
ج هناك ثلاث طرق: ① ELK Stack (Elasticsearch + Logstash + Kibana) — المعيار الصناعي؛ ② Loki + Grafana (خفيف الوزن، موصى به للبيئات السحابية الأصلية)؛ ③ خدمات التسجيل من مزودي السحابة (AWS CloudWatch / Alibaba Cloud SLS). الكل يتبع: stdout الحاوية ← المجمع ← التخزين المركزي ← لوحة البحث.
س كيف أُعد HTTPS في بيئة الإنتاج؟
ج تكوين TLS في حاوية Nginx: ① شهادة Let's Encrypt مجانية + تجديد تلقائي عبر Certbot؛ ② وضع الوكيل العكسي: Nginx يتولى TLS، بينما الاتصال الداخلي يستخدم HTTP؛ ③ موازن الحمل لدى مزود السحابة يتولى TLS (ALB/SLB)، لذا لا تحتاج الحاوية إلى شهادة.
س كيف تراقب صحة مجموعة microservices بالكامل؟
ج التركيبة الذهبية لـ Prometheus و Grafana: ① Prometheus يجمع البيانات من نقاط نهاية /metrics لكل خدمة؛ ② Grafana يعرض لوحات المعلومات وقواعد التنبيه؛ ③ المقاييس الرئيسية: زمن استجابة API (P50/P95/P99)، معدل الخطأ، استخدام CPU/الذاكرة، وعدد اتصالات قاعدة البيانات. راقب أولاً، ثم حسّن.
📖 ملخص
- Microservices كاملة = واجهة أمامية + API + قاعدة بيانات + ذاكرة تخزين مؤقت + MQ + مراقبة + CI/CD
- واجهة أمامية متعددة المراحل: بناء Node ← تشغيل Nginx؛ حجم الصورة انخفض من 1 جيجابايت إلى 25 ميجابايت
- خلفية متعددة المراحل: ترجمة Go ← تنفيذ Alpine؛ حجم الصورة انخفض من 780 ميجابايت إلى 15 ميجابايت
- Compose: عزل الشبكة (db-net internal) + فحوصات الصحة + حدود الموارد + تدوير السجلات
- CI/CD: push → build → push → نشر SSH — آلي بالكامل بدون تدخل يدوي
- Prometheus + Grafana: جمع المقاييس + التصور + التنبيهات — أساسي للعمليات
📝 تمارين
- تمرين أساسي (الصعوبة: ⭐): صمم مخطط بنية microservices لنظام مدونة (Nginx + API + قاعدة بيانات + ذاكرة تخزين مؤقت)، واذكر الصورة والمنفذ لكل خدمة.
- تمرين متقدم (الصعوبة: ⭐⭐): انشر هذه البنية باستخدام تقنية Docker الشاملة، واكتب ملف
docker-compose.prod.yml، وابدأ التطبيق بنجاح. - تحدٍ (الصعوبة: ⭐⭐⭐): أعد لوحة مراقبة Prometheus + Grafana، وأضف لوحات لزمن استجابة API ومعدل الأخطاء، وكوّن قواعد تنبيه بالبريد الإلكتروني.