المرحلة 5: النشر والإطلاق

النشر في بيئة الإنتاج

3 دقيقة للقراءة

لقد بنيت TaskFlow من الصفر -- النماذج والترحيلات ونقاط النهاية والمصادقة والاختبارات. حان الوقت الآن لتعبئته في حاوية جاهزة للإنتاج وإطلاقه.

بناء Docker متعدد المراحل

البناء متعدد المراحل يفصل بيئة البناء (حيث تثبت التبعيات وتجمّع) عن بيئة التشغيل (ما يعمل فعلياً في الإنتاج). هذا ينتج صوراً أصغر وأكثر أماناً.

# المرحلة 1: البناء -- تثبيت التبعيات
FROM python:3.12-slim AS builder

WORKDIR /app

RUN apt-get update && apt-get install -y --no-install-recommends \
    build-essential libpq-dev \
    && rm -rf /var/lib/apt/lists/*

COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# المرحلة 2: الإنتاج -- بيئة تشغيل خفيفة
FROM python:3.12-slim AS production

RUN apt-get update && apt-get install -y --no-install-recommends \
    libpq5 curl \
    && rm -rf /var/lib/apt/lists/*

# مستخدم غير جذري للأمان
RUN groupadd -r taskflow && useradd -r -g taskflow taskflow

WORKDIR /app

# نسخ الحزم المثبتة فقط من مرحلة البناء
COPY --from=builder /install /usr/local
COPY . .

RUN chown -R taskflow:taskflow /app
USER taskflow

HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD curl -f http://localhost:8000/health || exit 1

EXPOSE 8000
CMD ["gunicorn", "app.main:app", "-w", "4", "-k", "uvicorn.workers.UvicornWorker", "--bind", "0.0.0.0:8000"]

المبادئ الأساسية:

المبدأ لماذا هو مهم
بناء متعدد المراحل مرحلة البناء تُحذف؛ الصورة النهائية تحتوي فقط على تبعيات التشغيل
تثبيت إصدار الصورة الأساسية python:3.12-slim بدلاً من python:latest يمنع الأعطال المفاجئة
مستخدم غير جذري يحد من الضرر إذا تم اختراق الحاوية
HEALTHCHECK المُنسقات (Compose، ECS، K8s) تعرف متى يكون التطبيق جاهزاً فعلاً
ترتيب الطبقات COPY requirements.txt قبل COPY . لتُخزن طبقات التبعيات مؤقتاً

Docker Compose للإنتاج

احتفظ بملفات منفصلة للتطوير والإنتاج. التطوير يستخدم إعادة التحميل التلقائي وإعدادات التصحيح؛ الإنتاج يستخدم حدود الموارد وسياسات إعادة التشغيل.

# docker-compose.prod.yml
services:
  api:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    ports:
      - "8000:8000"
    env_file: .env.production
    depends_on:
      db:
        condition: service_healthy
      redis:
        condition: service_healthy
    deploy:
      resources:
        limits:
          cpus: "1.0"
          memory: 512M
    restart: unless-stopped
    networks:
      - external
      - internal

  db:
    image: postgres:18
    volumes:
      - pgdata:/var/lib/postgresql/data
    environment:
      POSTGRES_DB: taskflow
      POSTGRES_USER: taskflow
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U taskflow"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - internal

  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes --maxmemory 128mb --maxmemory-policy allkeys-lru
    volumes:
      - redisdata:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - internal

volumes:
  pgdata:
  redisdata:

networks:
  external:
  internal:
    internal: true

لاحظ internal: true على شبكة قاعدة البيانات. PostgreSQL وRedis يمكن الوصول إليهما فقط من خدمة API، ولا يُعرضان أبداً للمضيف.

إدارة البيئة

لا تُضمّن الأسرار أبداً في الكود. استخدم ملفات .env للتطوير المحلي ومخازن الأسرار المناسبة للإنتاج.

# .env.development (يُرفع للمستودع كـ .env.example بقيم فارغة)
DATABASE_URL=postgresql+asyncpg://taskflow:localpass@localhost:5432/taskflow
REDIS_URL=redis://localhost:6379/0
SECRET_KEY=dev-only-not-for-production
ENVIRONMENT=development

# .env.production (لا يُرفع أبداً -- استخدم أسرار CI/CD)
DATABASE_URL=postgresql+asyncpg://taskflow:${DB_PASSWORD}@db:5432/taskflow
REDIS_URL=redis://redis:6379/0
SECRET_KEY=${SECRET_KEY}
ENVIRONMENT=production

مع Pydantic Settings، يتم التحقق من التكوين عند بدء التشغيل:

from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    database_url: str
    redis_url: str
    secret_key: str
    environment: str = "development"
    api_v1_prefix: str = "/api/v1"

    @property
    def is_production(self) -> bool:
        return self.environment == "production"

    model_config = {"env_file": ".env"}

settings = Settings()

CI/CD مع GitHub Actions

خط أنابيب قياسي: اختبار، بناء، نشر -- يُشغل عند كل دفع إلى main وعند طلبات السحب.

# .github/workflows/ci.yml
name: CI/CD Pipeline

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

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      postgres:
        image: postgres:18
        env:
          POSTGRES_DB: taskflow_test
          POSTGRES_USER: taskflow
          POSTGRES_PASSWORD: testpassword
        ports: ["5432:5432"]
        options: >-
          --health-cmd="pg_isready -U taskflow"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=5
      redis:
        image: redis:7-alpine
        ports: ["6379:6379"]
        options: >-
          --health-cmd="redis-cli ping"
          --health-interval=10s
          --health-timeout=5s
          --health-retries=5

    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-python@v5
        with:
          python-version: "3.12"
      - run: pip install -r requirements.txt
      - run: ruff check .
      - run: pytest --cov=app tests/
        env:
          DATABASE_URL: postgresql+asyncpg://taskflow:testpassword@localhost:5432/taskflow_test
          REDIS_URL: redis://localhost:6379/0
          SECRET_KEY: test-secret-key

  build:
    needs: test
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t taskflow-api:${{ github.sha }} .

قائمة فحص الإنتاج

قبل الإطلاق، تحقق من كل عنصر:

الفئة العنصر الكيفية
الأمان مستخدم Docker غير جذري USER taskflow في Dockerfile
الأمان ترويسات الأمان Middleware: X-Content-Type-Options، X-Frame-Options، Strict-Transport-Security
الأمان CORS مقيد أصول مسموحة صريحة، لا تستخدم * أبداً في الإنتاج
الأداء عمال Gunicorn gunicorn -w 4 -k uvicorn.workers.UvicornWorker
الموثوقية فحوصات الصحة نقطة /health تُرجع 200 عندما يكون DB وRedis متاحين
الموثوقية سياسة إعادة التشغيل restart: unless-stopped في Compose
الإصدارات بادئة API جميع المسارات تحت /api/v1/
الأسرار لا مفاتيح مُضمنة جميع الأسرار من متغيرات البيئة أو مدير الأسرار

خيارات النشر (اعتباراً من 2026)

المنصة الأفضل لـ ملاحظات
Railway النشر السريع، الفرق الصغيرة Docker + إضافات PostgreSQL + Redis، تسعير بسيط
Render النشر التلقائي من Git مستوى مجاني للهوايات، PostgreSQL مُدار
Fly.io النشر على الحافة، زمن وصول منخفض نشر الحاويات عالمياً، Postgres مدمج
AWS ECS / Fargate النطاق المؤسسي نظام AWS البيئي الكامل، يحتاج تكوين أكثر

جميع المنصات الأربع تدعم النشر القائم على Docker. بالنسبة لـ TaskFlow، Railway أو Render تنقلك من الكود إلى الإنتاج في أقل من 10 دقائق.

التالي: معمل عملي حيث ستُحوّل TaskFlow إلى حاوية وتُعد خط أنابيب CI/CD الكامل. :::

اختبار

اختبار الوحدة 5: النشر والإطلاق

خذ الاختبار