Контейнеризация AI-агента с нуля: Dockerfile, docker-compose, healthcheck. Продакшн-деплой с nginx-прокси, SSL-сертификатами и системой автомасштабирования. Полный цикл от локальной разработки до облачного кластера.
Начинаем с оптимизированного Dockerfile. Ключевые принципы: многоэтапная сборка, минимизация слоёв, непривилегированный пользователь, кэширование зависимостей отдельно от кода. Используем python:3.11-slim как базу — он легче стандартного на 800 МБ.
# === Dockerfile === FROM python:3.11-slim AS builder # Системные зависимости — собираем с компиляцией RUN apt-get update && apt-get install -y --no-install-recommends \ gcc g++ libffi-dev curl \ && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY requirements.txt . RUN pip install --no-cache-dir --prefix=/install \ -r requirements.txt # === Финальный образ === FROM python:3.11-slim # Создаём непривилегированного пользователя RUN groupadd -r agent && useradd -r -g agent agent RUN apt-get update && apt-get install -y --no-install-recommends \ ca-certificates curl \ && rm -rf /var/lib/apt/lists/* COPY --from=builder /install /usr/local COPY --chown=agent:agent . /app USER agent WORKDIR /app # Healthcheck: проверяем что агент жив HEALTHCHECK --interval=30s --timeout=5s --retries=3 \ CMD curl -f http://localhost:8000/health || exit 1 EXPOSE 8000 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
Без healthcheck оркестратор (Docker Swarm, K8s) не узнает, что контейнер завис. Эндпоинт проверяет не только HTTP-статус, но и доступность LLM API и БД. Это критически важно для restart_policy и нулевого даунтайма.
# === health.py === import asyncio from fastapi import APIRouter, HTTPException from core.dependencies import get_llm_client, get_db router = APIRouter(tags=["health"]) @router.get("/health") async def health_check(): checks = {"status": "ok"} # Проверка LLM API (таймаут 3 секунды) try: llm = get_llm_client() await asyncio.wait_for( llm.ping(), timeout=3.0 ) checks["llm_api"] = "healthy" except Exception as e: checks["llm_api"] = f"degraded: {str(e)}" # Проверка БД try: db = get_db() await db.execute("SELECT 1") checks["database"] = "healthy" except Exception: checks["database"] = "unavailable" return checks
Один docker compose up -d — и весь стек запущен. Compose связывает агента с Redis (кеш + очереди), PostgreSQL (персистентность) и Nginx (прокси). Используем depends_on с condition для гарантированного порядка запуска.
# === docker-compose.yml === version: "3.9" services: agent: build: . container_name: ai-agent restart: unless-stopped ports: - "8000:8000" env_file: .env environment: - REDIS_URL=redis://redis:6379/0 - DATABASE_URL=postgresql+asyncpg://agent:secret@postgres:5432/agentdb - LOG_LEVEL=INFO depends_on: redis: condition: service_healthy postgres: condition: service_healthy healthcheck: test: ["CMD", "curl", "-f", "http://localhost:8000/health"] interval: 30s retries: 3 volumes: - ./logs:/app/logs redis: image: redis:7-alpine container_name: agent-redis restart: unless-stopped command: redis-server --appendonly yes --maxmemory 256mb healthcheck: test: ["CMD", "redis-cli", "ping"] interval: 5s postgres: image: postgres:16-alpine container_name: agent-postgres restart: unless-stopped environment: POSTGRES_USER: agent POSTGRES_PASSWORD: secret POSTGRES_DB: agentdb healthcheck: test: ["CMD-SHELL", "pg_isready -U agent"] interval: 5s volumes: - pgdata:/var/lib/postgresql/data volumes: pgdata:
Nginx термирует SSL, проксирует WebSocket и ограничивает rate-limit. Используем Certbot для автоматического получения и обновления сертификатов. Конфиг учитывает большие таймауты — LLM-запросы могут длиться до 60 секунд.
# === nginx.conf === server { listen 443 ssl http2; server_name agent.qantcore.space; # SSL от Certbot ssl_certificate /etc/letsencrypt/live/agent.qantcore.space/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/agent.qantcore.space/privkey.pem; # Rate limiting: 30 запросов/сек с бакетом burst=50 limit_req_zone $binary_remote_addr zone=api_limit:10m rate=30r/s; location / { limit_req zone=api_limit burst=50 nodelay; proxy_pass http://agent:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; # WebSocket support для стриминга ответов агента proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; # Таймауты для LLM-запросов proxy_read_timeout 120s; proxy_send_timeout 120s; } }
Автоматизируем деплой. Скрипт тянет свежий код, пересобирает образ (с кэшем зависимостей), делает docker compose up -d и ждёт healthcheck. Поддерживает blue-green развёртывание с нулевым даунтаймом через смену порта.
#!/bin/bash # === deploy.sh — продакшн-деплой AI-агента === set -euo pipefail IMAGE_TAG="ai-agent:$(git rev-parse --short HEAD)" COMPOSE_FILE="docker-compose.yml" echo "📦 Сборка образа $IMAGE_TAG..." docker build \ --cache-from ai-agent:latest \ -t $IMAGE_TAG \ -t ai-agent:latest \ . echo "🚀 Запуск стека..." docker compose -f $COMPOSE_FILE up -d --remove-orphans # Ждём healthcheck агента (макс 60 секунд) echo "⏳ Ожидание healthcheck..." for i in $(seq 1 30); do if curl -sf http://localhost:8000/health > /dev/null 2>&1; then echo "✅ Агент успешно запущен: $IMAGE_TAG" exit 0 fi sleep 2 done echo "❌ Healthcheck не пройден! Откат..." docker compose -f $COMPOSE_FILE down && docker compose -f $COMPOSE_FILE up -d --no-build exit 1
Итоговый образ должен быть минимальным. Используем .dockerignore чтобы исключить лишнее, multi-stage сборку для разделения build-time и runtime зависимостей, а также slim-базу. Типичный образ AI-агента с FastAPI весит 200-350 МБ вместо 1.2 ГБ.
# === .dockerignore === # Исключаем всё, что не нужно в контейнере __pycache__/ *.pyc .git/ .env.local .venv/ venv/ node_modules/ tests/ *.md .gitignore docker-compose*.yml Dockerfile logs/ .vscode/ # === Проверка размера === # docker images ai-agent --format "{{.Size}}" # → 247MB (было 1.2GB без оптимизации)
Вы получили полноценный продакшн-пайплайн для Docker-деплоя AI-агента: оптимизированный Dockerfile с multi-stage сборкой (~250 МБ финальный образ), docker-compose стек из 4 сервисов (агент, Redis, PostgreSQL, Nginx), healthcheck с проверкой LLM API и БД, SSL-терминацию через Nginx + Certbot и скрипт деплоя с автоматическим откатом при неудачном healthcheck. Следующий шаг — добавить горизонтальное масштабирование через docker compose up -d --scale agent=3 и балансировщик.