🐳

Docker для AI-агентов: деплой за 15 минут

Контейнеризация AI-агента с нуля: Dockerfile, docker-compose, healthcheck. Продакшн-деплой с nginx-прокси, SSL-сертификатами и системой автомасштабирования. Полный цикл от локальной разработки до облачного кластера.

intermediate⏱ 18 мин
🏗 Архитектура Docker-деплоя AI-агента 🌐 Клиент ⚡ Nginx :443 SSL 🐳 FastAPI :8000 🧠 LLM API OpenAI/etc 🐋 DOCKER HOST ai-agent python:3.11-slim redis cache / очередь postgres состояние агента prometheus метрики 💾 Docker Volume

# 1. Фундамент: идеальный Dockerfile для AI-агента

Начинаем с оптимизированного 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"]

# 2. Эндпоинт /health — пульс вашего агента

Без 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

# 3. Docker Compose: оркестрация всего стека

Один 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:

# 4. Nginx reverse proxy с SSL от Let's Encrypt

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;
    }
}

# 5. Продакшн-деплой: скрипт сборки и запуска

Автоматизируем деплой. Скрипт тянет свежий код, пересобирает образ (с кэшем зависимостей), делает 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

# 6. Multi-stage билд и оптимизация размера образа

Итоговый образ должен быть минимальным. Используем .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 и балансировщик.

📖 Dockerfile Reference 📖 Compose Spec 📖 Nginx Proxy 🔗 Каталог AI-агентов