Docker: تكامل CI/CD

آخر تحديث: 2026-08-26

دفع الكود ← اختبار آلي ← بناء آلي للصورة ← نشر آلي — CI/CD يحول عملية الإصدار من العمليات اليدوية إلى خط أنابيب آلي.

1. ما ستتعلمه



2. قصة حقيقية لمطور

(1) نقطة الألم: عمليات SSH يدوية مطلوبة لكل نشر

في كل مرة تنشر فيها أليس، يجب عليها يدويًا الدخول عبر SSH إلى الخادم، وسحب الكود، وبناء الصورة، وإعادة تشغيل الحاوية. العملية هي: ssh server → git pull → docker build → docker stop → docker run. كل نشر يستغرق 15 دقيقة، ومع 3-4 إصدارات في الأسبوع، تهدر ساعة كاملة أسبوعيًا في مهام متكررة. والأسوأ من ذلك، أنها أدخلت أمرًا خاطئًا عن طريق الخطأ أثناء إصدار في منتصف الليل.

(2) حل باستخدام GitHub Actions CI/CD

كتب بوب سير عمل باستخدام GitHub Actions: دفع الكود ← اختبار آلي ← بناء الصورة ← دفع إلى المستودع ← نشر عبر SSH.

YAML
# .github/workflows/deploy.yml
name: Build and Deploy
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: docker/setup-buildx-action@v3
      - uses: docker/build-push-action@v5
        with:
          push: true
          tags: myorg/myapp:${{ github.sha }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

(3) الوقت المستغرق: ساعة/أسبوع ← 0 دقائق

النشر مؤتمت بالكامل — أليس ببساطة تدفع الكود، ويصبح مباشرًا تلقائيًا في غضون 5 دقائق. انخفض العمل اليدوي من ساعة أسبوعيًا إلى 0، مع صفر أخطاء بشرية.



3. هيكل سير عمل GitHub Actions

(1) هيكل YAML لسير العمل

100%
graph LR
    PUSH["git push"] --> TRIGGER["on: push"]
    TRIGGER --> JOB1["Job: test"]
    JOB1 --> JOB2["Job: build"]
    JOB2 --> JOB3["Job: deploy"]
الحقل الغرض مثال
name اسم سير العمل Build and Deploy
on شرط التشغيل push, pull_request
jobs تعريف المهمات build, test, deploy
runs-on بيئة التشغيل ubuntu-latest
steps خطوات التنفيذ checkout, build, push

(1) مقارنة ثلاث استراتيجيات CI/CD

المنصة الميزات حالات الاستخدام
GitHub Actions تكامل أصلي مع GitHub، 2000 دقيقة مجانية/شهر مشاريع مفتوحة المصدر + استضافة GitHub
GitLab CI أصلي لـ GitLab، Runner مستضاف ذاتيًا GitLab محلي
Jenkins منصة CI/CD راسخة مع مجموعة واسعة من الإضافات المؤسسات التقليدية + خطوط أنابيب معقدة


4. بناء Docker buildx متعدد المنصات

▶ مثال: بناء buildx متعدد المعماريات (الصعوبة: ⭐⭐⭐)

BASH
# إنشاء مثيل builder لـ buildx
docker buildx create --name multiarch --use

# البناء لـ amd64 + arm64 في وقت واحد
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myorg/myapp:latest \
  --push .

# فحص المنصات المبنية
docker buildx imagetools inspect myorg/myapp:latest

(1) buildx مقابل build العادي

البُعد docker build docker buildx
معماريات متعددة ❌ يمكن فقط بناء المعمارية الحالية ✅ بناء معماريات متعددة في وقت واحد
تصدير التخزين المؤقت ❌ تخزين مؤقت محلي ✅ gha/registry/s3
تنسيق المخرجات صورة محلية Image/OCI/tar/registry
بناء متوازي


5. استراتيجية التخزين المؤقت في CI

(1) مقارنة أنواع التخزين المؤقت

النوع الصيغة الموقع سيناريوهات الاستخدام
gha cache-from: type=gha ذاكرة GitHub Actions المؤقتة GitHub Actions CI
registry cache-from: type=registry Docker Registry أي منصة CI
local cache-from: type=local نظام الملفات المحلي Runner مستضاف ذاتيًا

▶ مثال: تكوين التخزين المؤقت في CI (الصعوبة: ⭐⭐⭐)

YAML
# GitHub Actions مع ذاكرة بناء مؤقتة
- uses: docker/build-push-action@v5
  with:
    context: .
    push: true
    tags: myorg/myapp:${{ github.sha }}
    cache-from: type=gha
    cache-to: type=gha,mode=max

▶ مثال: سياسة الوسم التلقائي (الصعوبة: ⭐⭐)

YAML
# إجراء بيانات Docker الوصفية للوسم التلقائي
- uses: docker/metadata-action@v5
  id: meta
  with:
    images: myorg/myapp
    tags: |
      type=sha,prefix=
      type=ref,event=branch
      type=semver,pattern={{version}}
      type=raw,value=latest,enable={{is_default_branch}}


6. خطوات النشر عبر SSH

▶ مثال: النشر عبر SSH إلى خادم (الصعوبة: ⭐⭐⭐)

YAML
# خطوة النشر في GitHub Actions
- name: Deploy to server
  uses: appleboy/ssh-action@v1
  with:
    host: ${{ secrets.SERVER_HOST }}
    username: ${{ secrets.SERVER_USER }}
    key: ${{ secrets.SSH_PRIVATE_KEY }}
    script: |
      cd /opt/myapp
      docker compose pull
      docker compose up -d --remove-orphans
      docker image prune -f
🔒 الأمان: خزن المعلومات الحساسة مثل عناوين الخادم ومفاتيح SSH باستخدام GitHub Secrets؛ لا تدرجها في ملف YAML. أضفها تحت Settings → Secrets and variables → Actions.



7. مثال كامل: CI/CD لتطبيق Node.js

YAML
# ============================================
# .github/workflows/deploy.yml
# CI/CD كامل: test → build → push → deploy
# ============================================

name: CI/CD Pipeline

on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  REGISTRY: docker.io
  IMAGE_NAME: myorg/myapp

jobs:
  # ---------- المهمة 1: الاختبار ----------
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Run tests
        run: |
          docker build --target builder -t test-image .
          docker run test-image npm test

  # ---------- المهمة 2: البناء والدفع ----------
  build:
    needs: test
    runs-on: ubuntu-latest
    if: github.event_name == 'push'
    steps:
      - uses: actions/checkout@v4

      - uses: docker/setup-buildx-action@v3

      - uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ secrets.DOCKER_USERNAME }}
          password: ${{ secrets.DOCKER_PASSWORD }}

      - uses: docker/metadata-action@v5
        id: meta
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=sha,prefix=
            type=raw,value=latest

      - uses: docker/build-push-action@v5
        with:
          context: .
          push: true
          tags: ${{ steps.meta.outputs.tags }}
          cache-from: type=gha
          cache-to: type=gha,mode=max

  # ---------- المهمة 3: النشر ----------
  deploy:
    needs: build
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.SERVER_HOST }}
          username: ${{ secrets.SERVER_USER }}
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            cd /opt/myapp
            docker compose pull
            docker compose up -d --remove-orphans
            docker image prune -f
            echo "Deployed at $(date)"

❓ أسئلة شائعة

س ما الفرق بين buildx و build العادي؟
ج buildx هو امتداد CLI لـ Docker BuildKit. مزاياه الرئيسية: ① بناء متزامن لمعماريات متعددة (amd64+arm64)؛ ② تصدير متقدم للتخزين المؤقت (gha/registry)؛ ③ بناء متوازي. يوصي GitHub Actions دائمًا باستخدام buildx.
س كيف أشارك ذاكرة طبقات Docker المؤقتة في CI؟
ج استخدم cache-from: type=gha (GitHub Actions) أو type=registry (للاستخدام العام). ذاكرة GHA المؤقتة مخزنة في ذاكرة GitHub Actions المؤقتة وتتم مشاركتها تلقائيًا بين سير العمل في نفس المستودع. ذاكرة registry المؤقتة مخزنة في بيان خاص داخل السجل ويمكن استخدامها من قبل أي منصة CI.
س كيف أبني صورًا متعددة المعماريات؟
ج docker buildx build --platform linux/amd64,linux/arm64 -t myapp:latest --push .. ستحتاج إلى محاكي QEMU (docker/setup-qemu-action) و buildx builder. مخرجات البناء هي قائمة بيانات، تختار تلقائيًا الصورة للمعمارية الحالية أثناء docker pull.
س كيف تُدار بيانات الاعتماد الحساسة في CI/CD؟
ج GitHub Secrets (Settings → Secrets). مفاتيح SSH وكلمات مرور قاعدة البيانات وبيانات اعتماد السجل كلها مخزنة في Secrets ويُشار إليها في YAML باستخدام ${{ secrets.XXX }}. Secrets مخزنة بشكل مشفر وتُخفى تلقائيًا في السجلات.
س كيف يمكنني التراجع تلقائيًا في حالة فشل النشر؟
ج هناك طريقتان: ① أضف فحص صحة إلى سكريبت النشر؛ إذا فشل، استخدم docker compose rollback (Swarm) أو عد يدويًا إلى الإصدار السابق؛ ② احتفظ بأحدث N إصدارات موسومة في الصورة؛ للتراجع، استخدم ببساطة docker compose up -d myapp:previous-sha. التراجع التلقائي مدعوم أصليًا في Swarm و K8s.

📖 ملخص


📝 تمارين

  1. تمرين أساسي (الصعوبة: ⭐): اكتب سير عمل GitHub Actions لبناء تطبيق Flask من الدرس 12 بحيث يبني ويدفع الصورة تلقائيًا عند دفع commit إلى الفرع الرئيسي.
  2. تمرين متقدم (الصعوبة: ⭐⭐): استخدم buildx لبناء صورة بمعمارية مزدوجة amd64+arm64 وادفعها إلى Docker Hub.
  3. تحدٍ (الصعوبة: ⭐⭐⭐): أعد خط أنابيب CI/CD كامل (اختبار ← بناء ← نشر SSH)، واستخدم GitHub Secrets لإدارة مفاتيح الخادم، وتحقق من أن النشر يحدث تلقائيًا بعد الدفع.
Web-Tutorial.com

فريق Web-Tutorial التقني

منصة دروس برمجية يديرها عدة مطورين. كل درس يتم كتابته ومراجعته بواسطة مطورين متخصصين في المجال. نعمل على ضمان دقة وموثوقية المحتوى — إذا لاحظت أي مشكلة، فيرجى إخبارنا.

100%