تخطَّ إلى المحتوى

🐳 شرح Docker

Docker في CI/CD

الدرس 25 من 30· ⏱ 5 دقائق قراءة· 🗓 آخر تحديث: ٢٣ يوليو ٢٠٢٦

بناء الصور في CI

أساس أي pipeline CI/CD لـ Docker: بناء الصورة، دفعها إلى registry، ثم نشرها.

GitHub Actions

# .github/workflows/docker-build.yml
name: Build and Push Docker Image

on:
  push:
    branches: [main]
    tags: ["v*"]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  build:
    runs-on: ubuntu-latest
    permissions:
      contents: read
      packages: write

    steps:
      - uses: actions/checkout@v4

      - name: Log in to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ${{ env.REGISTRY }}
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Extract metadata
        id: meta
        uses: docker/metadata-action@v5
        with:
          images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
          tags: |
            type=semver,pattern={{version}}
            type=sha,prefix=
            type=raw,value=latest,enable=${{ github.ref == 'refs/heads/main' }}

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

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

تخزين الـ Cache بين التشغيلات

- name: Build and push
  uses: docker/build-push-action@v5
  with:
    cache-from: type=gha
    cache-to: type=gha,mode=max

type=gha يستخدم GitHub Actions cache — يسرّع البناء بشكل كبير.

للـ GitLab CI:

build:
  stage: build
  script:
    - docker build --cache-from $CI_REGISTRY_IMAGE:latest -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA .
    - docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA

بناء متعدّد المنصات (Buildx)

# إنشاء builder يدعم ARM64 + AMD64
docker buildx create --name mybuilder --use

# بناء الصورة لأكثر من منصة
docker buildx build \
  --platform linux/amd64,linux/arm64 \
  -t myrepo/myapp:latest \
  --push .

في GitHub Actions:

- name: Set up QEMU
  uses: docker/setup-qemu-action@v3

- name: Set up Docker Buildx
  uses: docker/setup-buildx-action@v3

- name: Build and push multi-platform
  uses: docker/build-push-action@v5
  with:
    platforms: linux/amd64,linux/arm64
    push: true
    tags: ghcr.io/myorg/myapp:latest

⚠️ بناء ARM64 على x86_64 يستخدم QEMU محاكاة — قد يكون أبطأ. فكّر في self-hosted runners.

الدفع إلى Registries مختلفة

Docker Hub

- name: Log in to Docker Hub
  uses: docker/login-action@v3
  with:
    username: ${{ secrets.DOCKER_USERNAME }}
    password: ${{ secrets.DOCKER_PASSWORD }}

💡 هذا الأسلوب يحتاج تخزين access token ثابت كسرّ في الريبو، وتدويره يدويًا بين فترة وأخرى — وإذا تسرّب من سجلات CI أو تكوين خاطئ، يبقى صالحًا لحد ما تلغيه بنفسك.

تسجيل دخول بلا أسرار مخزّنة (OIDC)

Docker Hub تدعم الآن مصادقة OIDC (OpenID Connect) مع GitHub Actions: بدل تخزين access token ثابت، يصدر GitHub توكن JWT موقّعًا لكل تشغيل، تتحقق منه Docker Hub مقابل ruleset (قاعدة) عرّفتها مسبقًا في لوحة تحكّم Docker Home — تحدّد فيها أي مستودع وفرع يسمح له بالدخول — وترجّع توكن وصول صالح لدقائق معدودة فقط.

permissions:
  contents: read
  id-token: write # لازم لإصدار توكن OIDC

steps:
  - name: Log in to Docker Hub via OIDC
    uses: docker/login-action@v4
    with:
      username: myorg # اسم منظّمتك على Docker Hub
    env:
      DOCKERHUB_OIDC_CONNECTIONID: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }}

لاحظ عدم وجود password إطلاقًا هنا. قبل استخدام هذا، أنشئ اتصال OIDC من Docker Home وحدّد ruleset يقيّد الوصول (مثلًا repo:myorg/myapp:ref:refs/heads/main فقط)، وانسخ معرّف الاتصال لاستخدامه أعلاه.

⚠️ متاح فقط لمنظمات Docker Team أو Business أو Docker Hardened Images، أو المسجّلة في Docker Sponsored Open Source Program — غير متاح لحسابات Docker Hub الفردية المجانية.

💡 التوكن الصادر عبر OIDC صالح لدقائق فقط (300 إلى 3600 ثانية قابلة للضبط) ولا يمكن إعادة استخدامه بعد انتهاء صلاحيته — فحتى لو تسرّب من سجل CI، فائدته للمهاجم شبه معدومة.

GitHub Container Registry (GHCR)

- name: Log in to GHCR
  uses: docker/login-action@v3
  with:
    registry: ghcr.io
    username: ${{ github.actor }}
    password: ${{ secrets.GITHUB_TOKEN }}

Amazon ECR

- name: Log in to Amazon ECR
  uses: aws-actions/amazon-ecr-login@v2

النشر عبر SSH + docker-compose

- name: Deploy to VPS
  uses: appleboy/ssh-action@v1
  with:
    host: ${{ secrets.HOST }}
    username: ${{ secrets.USER }}
    key: ${{ secrets.SSH_KEY }}
    script: |
      cd /opt/myapp
      docker compose pull
      docker compose up -d --remove-orphans
      docker image prune -f

⚠️ تأكد أن docker compose مثبت على السيرفر الهدف. استخدم SSH keys وليس passwords.

فحص الأمان في Pipeline

- name: Scan Docker image for vulnerabilities
  uses: aquasecurity/trivy-action@master
  with:
    image-ref: ghcr.io/myorg/myapp:${{ github.sha }}
    format: table
    exit-code: 1
    severity: HIGH,CRITICAL
# إضافة إلى نفس الـ pipeline
- name: Run Docker Bench Security
  run: |
    docker run --rm \
      -v /var/run/docker.sock:/var/run/docker.sock \
      docker/docker-bench-security

مثال Pipeline كامل

name: Docker CI/CD Pipeline

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

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run tests
        run: |
          docker build -t myapp:test .
          docker run myapp:test npm test

  security-scan:
    runs-on: ubuntu-latest
    needs: test
    steps:
      - uses: actions/checkout@v4
      - name: Trivy scan
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: myapp:test
          exit-code: 1
          severity: HIGH,CRITICAL

  build-and-push:
    runs-on: ubuntu-latest
    needs: security-scan
    if: github.ref == 'refs/heads/main'
    steps:
      - uses: actions/checkout@v4
      - name: Log in to GHCR
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}
      - name: Build and push
        uses: docker/build-push-action@v5
        with:
          push: true
          tags: ghcr.io/myorg/myapp:latest
          cache-from: type=gha
          cache-to: type=gha,mode=max

  deploy:
    runs-on: ubuntu-latest
    needs: build-and-push
    steps:
      - name: Deploy via SSH
        uses: appleboy/ssh-action@v1
        with:
          host: ${{ secrets.HOST }}
          username: ${{ secrets.USER }}
          key: ${{ secrets.SSH_KEY }}
          script: |
            cd /opt/myapp
            docker compose pull
            docker compose up -d --remove-orphans

🎯 التالي: BuildKit وDocker Buildx

شرح Docker في CI/CD — Docker بالعربي
Docker في CI/CDDocker بالعربي · The Code Fix

📚 لمزيد من التعمّق في Docker، راجِع التوثيق الرسمي لـ Docker.

هل كان هذا الدرس مفيدًا؟