Docker для AI-проектов: полное руководство
Полное руководство по Docker для AI-проектов. GPU-ускорение, NVIDIA Container Toolkit, Docker Model Runner, оптимизация образов и деплой моделей.
«У меня всё работает локально» — фраза, которая похоронила десятки AI-проектов на этапе деплоя. Разные версии CUDA, конфликты Python-зависимостей, несовместимость драйверов — всё это превращает перенос модели с ноутбука разработчика на сервер в квест. Docker решает эту проблему: вы упаковываете модель, зависимости, рантайм и GPU-конфигурацию в один контейнер, который идентично работает где угодно.
В этом руководстве — от базовой контейнеризации AI-проекта до продвинутых техник: GPU-ускорение через NVIDIA Container Toolkit, запуск LLM локально через Docker Model Runner, оптимизация образов multi-stage сборками и production-деплой.
Почему Docker критически важен для AI
В классической разработке контейнеризация — удобство. В AI/ML — необходимость. Типичный AI-проект тянет за собой десятки зависимостей с жёсткими требованиями к версиям: PyTorch 2.6 работает с CUDA 12.4, но ломается с 12.6; TensorFlow требует определённую версию cuDNN; даже NumPy между мажорными версиями ломает обратную совместимость.
docker pull, и окружение готово.Вот что Docker даёт AI-разработчику:
| Проблема | Без Docker | С Docker |
|---|---|---|
| Версии CUDA/cuDNN | Ручная установка, конфликты | Зафиксированы в образе |
| Python-зависимости | pip install ломает системный Python | Изолированы в контейнере |
| Воспроизводимость | «У меня работает» | Идентичное окружение везде |
| Деплой модели | Ручная настройка сервера | docker run и готово |
| Масштабирование | Сложная оркестрация | Kubernetes + Docker = стандарт |
| Совместная работа | README на 3 страницы | docker compose up |
Docker-образ — это не просто упаковка кода. Это снимок всего окружения: ОС, драйверы, библиотеки, модель, конфигурация. Один артефакт от эксперимента до продакшена.
GPU-ускорение: NVIDIA Container Toolkit
Большинство AI-задач требуют GPU. Docker из коробки не видит видеокарты — для этого нужен NVIDIA Container Toolkit (ранее nvidia-docker). Он связывает контейнер с GPU хоста через Container Device Interface (CDI).
Установка
На хосте с Ubuntu и установленным NVIDIA-драйвером:
# Добавляем репозиторий NVIDIA
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
# Устанавливаем
sudo apt-get update && sudo apt-get install -y nvidia-container-toolkit
# Конфигурируем Docker runtime
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
Проверка
docker run --rm --gpus all nvidia/cuda:12.4.0-base-ubuntu22.04 nvidia-smi
Если вы видите таблицу с информацией о GPU — всё работает.
GPU в Docker Compose
services:
inference:
image: pytorch/pytorch:2.6.0-cuda12.4-cudnn9-runtime
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1 # или "all" для всех GPU
capabilities: [gpu]
volumes:
- ./models:/app/models
ports:
- "8000:8000"
graph LR
A[Приложение в контейнере] --> B[NVIDIA Container Toolkit]
B --> C[NVIDIA Driver на хосте]
C --> D[GPU — CUDA Cores]
B --> E[CDI — Container Device Interface]
E --> C
Контейнеризация AI-проекта: от Dockerfile до деплоя
Базовые образы для AI
Выбор базового образа определяет размер контейнера, производительность и набор доступных библиотек.
| Образ | Размер | GPU | Когда использовать |
|---|---|---|---|
python:3.12-slim | ~150 MB | Нет | CPU-инференс, обработка данных |
pytorch/pytorch:2.6.0-cuda12.4-cudnn9-runtime | ~5.5 GB | Да | PyTorch + GPU-инференс |
tensorflow/tensorflow:2.18.0-gpu | ~6 GB | Да | TensorFlow + GPU |
nvidia/cuda:12.4.0-devel-ubuntu22.04 | ~3.5 GB | Да | Кастомная сборка с CUDA |
huggingface/transformers-pytorch-gpu | ~8 GB | Да | HuggingFace Transformers |
runtime (только библиотеки для запуска) и devel (компилятор nvcc, заголовочные файлы). Для инференса всегда берите runtime — он на 2–3 GB легче. devel нужен только если вы компилируете CUDA-код внутри контейнера.Multi-stage сборка для ML-проекта
Multi-stage build — ключевая техника для оптимизации AI-образов. Идея: собираем зависимости в тяжёлом билд-контейнере, а в финальный образ копируем только нужное.
# === Стадия 1: установка зависимостей ===
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# === Стадия 2: финальный образ ===
FROM python:3.12-slim AS runtime
WORKDIR /app
# Копируем установленные пакеты из builder
COPY --from=builder /install /usr/local
COPY . .
# Не запускаем от root
RUN useradd -m appuser
USER appuser
EXPOSE 8000
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "8000"]
Для GPU-проектов с PyTorch:
# === Build stage ===
FROM pytorch/pytorch:2.6.0-cuda12.4-cudnn9-devel AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# === Runtime stage ===
FROM pytorch/pytorch:2.6.0-cuda12.4-cudnn9-runtime
WORKDIR /app
COPY --from=builder /install /opt/conda
COPY . .
EXPOSE 8000
CMD ["python", "serve.py"]
Результат multi-stage сборки: финальный образ на 30–50% легче, чем при однослойной сборке. Для образов на базе CUDA это экономия 2–4 GB.
Оптимизация размера образа
AI-образы печально известны своим размером. Несколько приёмов:
# 1. Объединяйте RUN-команды — меньше слоёв
RUN apt-get update && \
apt-get install -y --no-install-recommends libgl1 libglib2.0-0 && \
rm -rf /var/lib/apt/lists/*
# 2. Используйте --no-cache-dir для pip
RUN pip install --no-cache-dir torch torchvision
# 3. Удаляйте ненужное после установки
RUN pip install --no-cache-dir flash-attn && \
find /opt/conda -name "*.pyc" -delete && \
find /opt/conda -name "__pycache__" -type d -exec rm -rf {} +
# 4. Используйте .dockerignore
# .dockerignore:
# .git
# __pycache__
# *.pyc
# data/raw/
# wandb/
# checkpoints/
graph TD
A[Dockerfile] --> B{Multi-stage?}
B -->|Да| C[Build stage: devel-образ]
C --> D[Установка зависимостей]
D --> E[Runtime stage: runtime-образ]
E --> F[Копирование только нужного]
F --> G[Финальный образ: минимальный размер]
B -->|Нет| H[Один слой: всё вместе]
H --> I[Образ +2-4 GB лишнего]
Docker Model Runner: LLM прямо в Docker
В 2025 году Docker представил Model Runner — встроенный инструмент для запуска LLM локально. Модели хранятся как OCI-артефакты (тот же стандарт, что и для Docker-образов) и запускаются через OpenAI-совместимый API.
Как это работает
# Скачиваем модель
docker model pull ai/llama3.2:3B-Q8_0
# Запускаем инференс
docker model run ai/llama3.2:3B-Q8_0 "Объясни Docker в одном абзаце"
Model Runner поднимает API на localhost:12434, совместимый с OpenAI SDK. Любой инструмент, работающий с OpenAI API, можно направить на Model Runner:
from openai import OpenAI
client = OpenAI(
base_url="http://localhost:12434/engines/llama3.2/v1/",
api_key="not-needed"
)
response = client.chat.completions.create(
model="ai/llama3.2:3B-Q8_0",
messages=[{"role": "user", "content": "Что такое контейнеризация?"}]
)
print(response.choices[0].message.content)
Движки инференса
| Движок | GPU | Платформы | Назначение |
|---|---|---|---|
| llama.cpp | Metal, CUDA, Vulkan | Все | Умолчание, универсальный |
| vLLM | NVIDIA CUDA | Linux x86_64, Windows WSL2 | Высокая пропускная способность |
| Diffusers | NVIDIA CUDA | Linux | Генерация изображений |
Model Runner в Docker Compose
services:
app:
build: .
environment:
- OPENAI_BASE_URL=http://model-runner.docker.internal/engines/llama3.2/v1/
ports:
- "8080:8080"
model-runner:
provider:
type: model
options:
model: ai/llama3.2:3B-Q8_0
docker compose up поднимает и приложение, и модель. Для команд, где Docker уже в стеке, это упрощает workflow.Production-деплой: чеклист и паттерны
Контейнеризация — половина дела. Для продакшена нужны дополнительные паттерны.
Health Checks
HEALTHCHECK --interval=30s --timeout=10s --retries=3 \
CMD curl -f http://localhost:8000/health || exit 1
Для ML-сервисов health check должен проверять не только HTTP-ответ, но и доступность модели:
@app.get("/health")
async def health():
try:
# Проверяем что модель загружена и GPU доступен
dummy = torch.tensor([1.0]).to(device)
return {"status": "ok", "gpu": torch.cuda.is_available()}
except Exception as e:
return JSONResponse(status_code=503, content={"status": "error"})
Управление ресурсами
services:
model-api:
image: my-model:latest
deploy:
resources:
limits:
memory: 16G
reservations:
memory: 8G
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
# Перезапуск при падении
restart: unless-stopped
# Логирование
logging:
driver: json-file
options:
max-size: "50m"
max-file: "3"
Полный docker-compose.yml для AI-сервиса
version: "3.9"
services:
api:
build:
context: .
dockerfile: Dockerfile
ports:
- "8000:8000"
volumes:
- model-cache:/app/models
environment:
- MODEL_NAME=llama-3.2-3b
- DEVICE=cuda
- NUM_WORKERS=2
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: 1
capabilities: [gpu]
restart: unless-stopped
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
interval: 30s
timeout: 10s
retries: 3
redis:
image: redis:7-alpine
volumes:
- redis-data:/data
prometheus:
image: prom/prometheus:latest
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
ports:
- "9090:9090"
volumes:
model-cache:
redis-data:
docker scout cves перед деплоем.Пайплайн от разработки до продакшена
graph LR
A[Разработка] --> B[Dockerfile + compose]
B --> C[CI: Build + Test]
C --> D[Registry: Push образа]
D --> E{Окружение}
E --> F[Staging: docker compose]
E --> G[Production: Kubernetes]
F --> H[Тесты + мониторинг]
H --> G
Заключение
Docker стал стандартом де-факто для AI-проектов — от экспериментов на ноутбуке до production-инференса с GPU-кластерами. Вот ключевые выводы:
- NVIDIA Container Toolkit — обязательный компонент для GPU-проектов. Установка занимает минуты, а проблемы с CUDA-совместимостью исчезают навсегда.
- Multi-stage сборки сокращают размер AI-образов на 30–50%. Разделяйте
develиruntimeстадии. - Docker Model Runner упрощает работу с LLM, встраивая инференс в привычный Docker-workflow с OpenAI-совместимым API.
- Production-деплой требует health checks, лимитов ресурсов, логирования и сканирования безопасности — Docker Compose покрывает всё это декларативно.
Начните с контейнеризации текущего проекта: напишите Dockerfile, добавьте .dockerignore, настройте Compose — и вы получите окружение, которое одинаково работает у каждого в команде и на каждом сервере.
Источники
- Docker Docs — Model Runner
- NVIDIA Container Toolkit — Install Guide
- Docker — Introducing Docker Model Runner
- Docker — Run LLMs Locally with Docker
- Docker — Model Runner + vLLM Integration
- Docker Docs — Multi-stage Builds
- RunPod — Docker Essentials for AI Developers
- Neptune.ai — Best Practices Docker for Machine Learning