Docker: تكامل CI/CD
آخر تحديث: 2026-08-26
دفع الكود ← اختبار آلي ← بناء آلي للصورة ← نشر آلي — CI/CD يحول عملية الإصدار من العمليات اليدوية إلى خط أنابيب آلي.
1. ما ستتعلمه
- سير عمل GitHub Actions الأساسي
- بناء Docker buildx متعدد المنصات
- سياسة التخزين المؤقت في CI
- عملية النشر متعدد البيئات
- الوسم التلقائي والتحكم في إصدار الصور
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.
# .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 لسير العمل
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 متعدد المعماريات (الصعوبة: ⭐⭐⭐)
# إنشاء مثيل 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 (الصعوبة: ⭐⭐⭐)
# 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
▶ مثال: سياسة الوسم التلقائي (الصعوبة: ⭐⭐)
# إجراء بيانات 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 إلى خادم (الصعوبة: ⭐⭐⭐)
# خطوة النشر في 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
7. مثال كامل: CI/CD لتطبيق Node.js
# ============================================
# .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.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.${{ secrets.XXX }}. Secrets مخزنة بشكل مشفر وتُخفى تلقائيًا في السجلات.docker compose rollback (Swarm) أو عد يدويًا إلى الإصدار السابق؛ ② احتفظ بأحدث N إصدارات موسومة في الصورة؛ للتراجع، استخدم ببساطة docker compose up -d myapp:previous-sha. التراجع التلقائي مدعوم أصليًا في Swarm و K8s.📖 ملخص
- سير عمل GitHub Actions: هيكل ثلاثي الطبقات — on(تشغيل) ← jobs ← steps
docker buildxيدعم بناء متعدد المعماريات وتصدير متقدم للتخزين المؤقتcache-from: type=ghaتسريع البناء باستخدام ذاكرة GitHub Actions المؤقتة- وسوم تلقائية: استراتيجية متعددة الوسوم Git SHA + semver + latest
- نشر SSH: استخدم
secretsلإدارة المعلومات الحساسة؛ استخدمcompose pull + upلتحقيق تحديثات بدون توقف - خط أنابيب كامل: test → build → push → deploy؛ "push" يعني النشر المباشر
📝 تمارين
- تمرين أساسي (الصعوبة: ⭐): اكتب سير عمل GitHub Actions لبناء تطبيق Flask من الدرس 12 بحيث يبني ويدفع الصورة تلقائيًا عند دفع commit إلى الفرع الرئيسي.
- تمرين متقدم (الصعوبة: ⭐⭐): استخدم
buildxلبناء صورة بمعمارية مزدوجة amd64+arm64 وادفعها إلى Docker Hub. - تحدٍ (الصعوبة: ⭐⭐⭐): أعد خط أنابيب CI/CD كامل (اختبار ← بناء ← نشر SSH)، واستخدم GitHub Secrets لإدارة مفاتيح الخادم، وتحقق من أن النشر يحدث تلقائيًا بعد الدفع.