MLOps Path

3.1.2 · блок 3

Dockerfile: сборка образа и multi-stage

Dockerfile: сборка образа и multi-stage

Зачем это нужно

docker run из чужого образа — это потребление. В MLOps вы создаёте образы: inference API, worker обучения, утилита валидации данных. Dockerfile — декларативный рецепт сборки, который лежит в Git рядом с кодом. Хороший Dockerfile ускоряет CI, уменьшает образ и снижает риск «случайно затащили секрет или dev-зависимость в прод».

Плохой Dockerfile — частая причина долгих пайплайнов и уязвимостей: образ на 3 ГБ с Jupyter и gcc в продакшене inference.

Основные идеи

Базовые инструкции. Типичная последовательность:

Порядок слоёв = скорость CI. Сначала файлы, которые меняются редко:


FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

Multi-stage build. Для C++ или сборки wheel иногда нужны компилятор и dev-заголовки — в runtime они не нужны. Multi-stage: первый stage собирает бинарник, второй копирует только результат:


FROM python:3.11 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip wheel --no-cache-dir -r requirements.txt -w /wheels

FROM python:3.11-slim
WORKDIR /app
COPY --from=builder /wheels /wheels
RUN pip install --no-cache-dir /wheels/*
COPY . .
CMD ["python", "-m", "app"]

Итоговый образ меньше и без gcc, build-essential.

.dockerignore. Как .gitignore: исключает .git, __pycache__, .venv, большие датасеты. Иначе они попадут в контекст сборки и замедлят docker build.

Безопасность и практика. Не запускайте приложение от root без необходимости; не копируйте секреты через ARG/ENV в образ; используйте конкретные теги базового образа (3.11-slim, не latest). Для ML: модель можно копировать в образ (малые модели) или монтировать том / качать из S3 при старте (крупные модели).

Как это выглядит на практике

Задача: упаковать сервис классификации с FastAPI.

1. Создайте requirements.txt с fastapi, uvicorn, scikit-learn.

2. Напишите Dockerfile по шаблону выше.

3. Соберите: docker build -t spam-classifier:1.0.0 .

4. Проверьте размер: docker images spam-classifier

5. Запустите с пробросом порта и проверьте /predict.

В Jenkins (модуль 3.2) тот же Dockerfile выполнится на agent: docker builddocker push registry.company/spam-classifier:${BUILD_NUMBER}. Изменение одной строки в app.py пересоберёт только последние слои — пайплайн станет быстрее.

Если inference на C++ (libtorch), первый stage компилирует .so, второй содержит только runtime-библиотеки — образ для GPU-сервера не раздувается инструментами сборки.

Что сделать после занятия

Официальные материалы

Открыть интерактивную версию