~/icsd.ir — bash
SYSTEM_ONLINE

Docker و Containerization

Docker انقلابی در deployment ایجاد کرد. هر میکروسرویس را در یک container ایزوله بسته‌بندی می‌کنیم که در هر محیطی یکسان اجرا می‌شود.

۱۰.۱ مقدمه

Docker انقلابی در deployment ایجاد کرد. هر میکروسرویس را در یک container ایزوله بسته‌بندی می‌کنیم که در هر محیطی یکسان اجرا می‌شود.

۱۰.۲ چرا Container؟

قبل از Docker: «روی سیستم من کار می‌کرد!» — مشکلی که هر developer می‌شناسد.

Container در مقابل VM


Virtual Machine:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│   App A     │ │   App B     │ │   App C     │
│  Bins/Libs  │ │  Bins/Libs  │ │  Bins/Libs  │
│  Guest OS   │ │  Guest OS   │ │  Guest OS   │ ← هر VM یک OS کامل
└─────────────┘ └─────────────┘ └─────────────┘
       Hypervisor (VMware, KVM)
                Host OS
              Hardware

Container:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│   App A     │ │   App B     │ │   App C     │
│  Bins/Libs  │ │  Bins/Libs  │ │  Bins/Libs  │  ← فقط application
└─────────────┘ └─────────────┘ └─────────────┘
        Docker Engine
              Host OS
              Hardware

نتیجه:
- Container: شروع در ثانیه، MB حافظه
- VM: شروع در دقیقه، GB حافظه
    

۱۰.۳ Dockerfile

دستورالعمل ساخت یک image. هر دستور یک layer ایجاد می‌کند.

Dockerfile پایه برای FastAPI


FROM python:3.11-slim

# Working directory
WORKDIR /app

# Install dependencies (cache-friendly: requirements اول)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copy code
COPY . .

# Non-root user
RUN useradd -m -u 1000 appuser
USER appuser

# Expose port
EXPOSE 8000

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

# Start command
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
    

Dockerfile پایه برای Django


FROM python:3.11-slim

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

WORKDIR /app

# Python deps
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Code
COPY . .

# Static files
RUN python manage.py collectstatic --noinput

# Non-root
RUN useradd -m django
USER django

EXPOSE 8000

CMD ["gunicorn", "myproject.wsgi:application", 
     "--bind", "0.0.0.0:8000", 
     "--workers", "4", 
     "--threads", "2", 
     "--timeout", "120"]
    

۱۰.۴ Multi-Stage Build

برای کاهش اندازه image، build و runtime را جدا می‌کنیم.


# Stage 1: Builder
FROM python:3.11 AS builder

WORKDIR /build

# Install build deps
RUN apt-get update && apt-get install -y 
    build-essential gcc

# Install python deps در virtualenv
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

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

# Stage 2: Runtime (slim)
FROM python:3.11-slim

# Copy فقط virtualenv از builder
COPY --from=builder /opt/venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

WORKDIR /app
COPY . .

USER 1000:1000
EXPOSE 8000
CMD ["uvicorn", "main:app", "--host", "0.0.0.0"]
    

نتیجه: اندازه image از ~1GB به ~150MB کاهش می‌یابد!

۱۰.۵ بهینه‌سازی Image

  • Base image سبک: alpine، slim، distroless
  • Layer ordering: چیزهای کمتر تغییرپذیر اول
  • Combine RUN commands: با &&
  • .dockerignore: exclude کردن فایل‌های غیرضروری
  • Multi-stage: build artifacts فقط
  • No-cache: apt و pip را با no-cache
  • Specific tags: python:3.11.7-slim نه python:latest

.dockerignore


.git
.gitignore
*.md
__pycache__
*.pyc
.pytest_cache
.coverage
.env
.venv
venv/
node_modules/
.idea/
.vscode/
docs/
tests/
    

۱۰.۶ Docker Compose

برای مدیریت چندین container در محیط dev/test.

docker-compose.yml کامل


version: "3.9"

services:
  # PostgreSQL
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_DB: shop
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: ${DB_PASSWORD}
    volumes:
      - pg_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    networks:
      - backend

  # Redis
  redis:
    image: redis:7-alpine
    command: redis-server --appendonly yes
    volumes:
      - redis_data:/data
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
    networks:
      - backend

  # RabbitMQ
  rabbitmq:
    image: rabbitmq:3.12-management-alpine
    environment:
      RABBITMQ_DEFAULT_USER: admin
      RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASSWORD}
    ports:
      - "15672:15672"  # Management UI
    volumes:
      - rabbitmq_data:/var/lib/rabbitmq
    healthcheck:
      test: rabbitmq-diagnostics check_running
      interval: 30s
    networks:
      - backend

  # User Service
  user-service:
    build:
      context: ./services/user
      dockerfile: Dockerfile
    environment:
      DATABASE_URL: postgresql://postgres:${DB_PASSWORD}@postgres/shop_users
      REDIS_URL: redis://redis:6379/0
      JWT_SECRET: ${JWT_SECRET}
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    deploy:
      replicas: 2
      restart_policy:
        condition: on-failure
    networks:
      - backend
      - frontend

  # Product Service  
  product-service:
    build: ./services/product
    environment:
      DATABASE_URL: postgresql://postgres:${DB_PASSWORD}@postgres/shop_products
      REDIS_URL: redis://redis:6379/1
      ELASTICSEARCH_URL: http://elasticsearch:9200
    depends_on:
      - postgres
      - redis
    networks:
      - backend
      - frontend

  # Order Service
  order-service:
    build: ./services/order
    environment:
      DATABASE_URL: postgresql://postgres:${DB_PASSWORD}@postgres/shop_orders
      RABBITMQ_URL: amqp://admin:${RABBITMQ_PASSWORD}@rabbitmq
    depends_on:
      - postgres
      - rabbitmq
    networks:
      - backend
      - frontend

  # API Gateway (Traefik)
  gateway:
    image: traefik:v3.0
    command:
      - "--providers.docker=true"
      - "--providers.docker.exposedByDefault=false"
      - "--entrypoints.web.address=:80"
      - "--api.dashboard=true"
      - "--api.insecure=true"
    ports:
      - "80:80"
      - "8080:8080"  # Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - frontend
    labels:
      - "traefik.enable=true"

volumes:
  pg_data:
  redis_data:
  rabbitmq_data:

networks:
  frontend:
  backend:
    internal: true  # دسترسی از بیرون ندارد
    

دستورات کلیدی


# Build و start
docker-compose up -d --build

# لاگ‌ها
docker-compose logs -f user-service

# اجرای دستور در container
docker-compose exec user-service python manage.py migrate

# Scale
docker-compose up -d --scale user-service=5

# Stop و حذف
docker-compose down -v  # -v حجم‌ها را هم پاک می‌کند
    

۱۰.۷ Networking

انواع network در Docker

  • bridge: پیش‌فرض، isolated network
  • host: استفاده از network host (بدون isolation)
  • overlay: برای multi-host (Swarm)
  • none: بدون network
  • macvlan: هر container IP فیزیکی

دسترسی بین Container ها


در شبکه custom (مثل backend بالا):
- container ها از طریق نام service به هم دسترسی دارند
- user-service می‌تواند به postgres با اسم `postgres` وصل شود
- DNS خودکار توسط Docker انجام می‌شود

از خارج:
- فقط ports که با `ports:` expose شده‌اند
- تفاوت ports vs expose:
  - ports: 8080:80  → دسترسی از host
  - expose: 80     → فقط داخل docker network
    

۱۰.۸ Volumes و Data Persistence

سه نوع mount

  • Volume: Docker مدیریت می‌کند (پیشنهاد)
  • Bind mount: path از host (برای dev مناسب)
  • tmpfs: در memory

services:
  postgres:
    volumes:
      - pg_data:/var/lib/postgresql/data    # named volume
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql  # bind mount

volumes:
  pg_data:
    driver: local
    driver_opts:
      type: none
      o: bind
      device: /data/postgres  # path روی host
    

۱۰.۹ امنیت Container

  • Non-root user: هیچ‌گاه root اجرا نکنید
  • Image scanning: Trivy، Snyk، Clair
  • Secrets management: از Docker Secrets یا Vault
  • Read-only filesystem: read_only: true
  • Capabilities: drop unused capabilities
  • Limit resources: CPU، memory limits
  • No privileged: هرگز privileged: true نگذارید
  • Update images: regularly

services:
  user-service:
    image: shop/user-service:1.2.3  # specific version
    read_only: true
    user: "1000:1000"
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    security_opt:
      - no-new-privileges:true
    deploy:
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
        reservations:
          cpus: "0.25"
          memory: 256M
    tmpfs:
      - /tmp:noexec,nosuid,size=64M
    

۱۰.۱۰ بهترین تجربیات

  1. One process per container.
  2. Stateless containers. state در volume یا DB.
  3. Use specific tags. هیچ‌گاه latest در production.
  4. Multi-stage builds.
  5. .dockerignore.
  6. Non-root user.
  7. Health checks.
  8. Log به stdout/stderr. نه فایل.
  9. Environment variables برای config.
  10. Resource limits.
  11. Image scanning در CI.
  12. Layer caching بهینه.

۱۰.۱۱ خلاصه فصل

آنچه آموختیم:
  • Container vs VM — کاربرد و تفاوت‌ها
  • Dockerfile برای Django و FastAPI
  • Multi-stage build برای کاهش اندازه
  • Docker Compose برای orchestration محلی
  • Networking و service discovery داخلی
  • Volumes برای data persistence
  • امنیت container در production
در فصل بعد: Kubernetes — orchestration در مقیاس production.

نمایش سایت

رنگ سایت
حالت نمایش
اندازهٔ متن
خوانایی

این تنظیمات فقط روی مرورگر شما ذخیره می‌شود.