Короткий ответ
Multi-stage build позволяет использовать «тяжёлый» этап с компиляторами для сборки зависимостей, а в финальный образ скопировать только готовые артефакты на «тонкий» базовый образ, не включая инструменты сборки и кэш pip, которые не нужны в runtime.
Как это работает подробнее
в Dockerfile можно объявить несколько стадий FROM ... AS builder, а в финальной стадии командой COPY --from=builder забрать только нужные файлы; промежуточные слои не попадают в итоговый образ.
Пример кода
Пример конфигурации
FROM python:3.12 AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --target=/install -r requirements.txt
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /install /usr/local/lib/python3.12/site-packages
COPY . .
CMD ["gunicorn", "app:app", "--bind", "0.0.0.0:8000"]Что использовать на практике
- Рекомендация. особенно полезно для зависимостей с C-расширениями, требующих компилятор — он нужен только на этапе установки; финальный образ на базе
slim/alpineполучается значительно меньше и с меньшей поверхностью атаки.
Подводные камни
- Риск. копировать в финальную стадию весь
/usr; выбирать alpine без проверки совместимости — musl libc может конфликтовать с пакетами, собранными под glibc.