Что такое многоэтапные сборки (multi-stage builds) в Docker и зачем они нужны?

Ответ

Многоэтапная сборка (multi-stage build) — это возможность использовать несколько инструкций FROM в одном Dockerfile для разделения процесса сборки приложения и создания финального образа.

Основная цель — уменьшить размер итогового Docker-образа, исключив из него зависимости и инструменты, необходимые только для сборки (компиляторы, SDK, dev-зависимости).

Как это работает:

  1. Первый этап (сборщик): Используется базовый образ со всеми инструментами. В нем компилируется код, устанавливаются зависимости, собираются артефакты.
  2. Второй этап (финальный): Используется минималистичный базовый образ (например, alpine или -slim). В него копируются только необходимые для запуска артефакты из первого этапа с помощью флага --from.

Пример для Python-приложения:

# --- Этап 1: Сборка зависимостей ---
# Используем полный образ Python для установки пакетов
FROM python:3.9 as builder

WORKDIR /app

# Создаем виртуальное окружение
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# Устанавливаем зависимости
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# --- Этап 2: Финальный образ ---
# Используем легковесный образ для запуска
FROM python:3.9-slim

WORKDIR /app

# Копируем только виртуальное окружение с зависимостями из этапа 'builder'
COPY --from=builder /opt/venv /opt/venv

# Копируем исходный код
COPY . .

# Указываем путь к исполняемым файлам из venv
ENV PATH="/opt/venv/bin:$PATH"

# Запускаем приложение
CMD ["python", "app.py"]

Преимущества:

  • Уменьшение размера образа: Финальный образ не содержит ненужных слоев с инструментами сборки.
  • Повышение безопасности: Меньше установленных пакетов — меньше потенциальных уязвимостей.
  • Упрощение CI/CD: Весь процесс сборки описан в одном Dockerfile.

Ответ 18+ 🔞

Да ты посмотри, какая хитрая штука придумана, блядь! Многоэтапная сборка, называется. Это когда в одном Dockerfile можно нагородить несколько этапов, и каждый из них — как отдельная, блядь, вселенная.

Основная фишка, понятное дело, — чтобы итоговый образ не весил как чугунный мост, ёпта. Выкинуть нахуй всё лишнее: эти твои компиляторы, SDK, тонны dev-зависимостей, которые нужны только чтобы собрать приложение, а потом они как манда с ушами торчат в финальном контейнере и места жрут.

Работает это, блядь, как по нотам:

  1. Этап первый, сборщик: Берёшь жирный образ, забитый всеми инструментами до упора. Тут ты свой код компилируешь, зависимости ставишь — в общем, творишь, что хочешь.
  2. Этап второй, финальный: Берёшь образ-голыш, какой-нибудь alpine тощий. И копируешь в него из первого этапа только готовые артефакты, что для запуска нужны. Всё остальное — на свалку истории, в рот меня чих-пых!

Смотри, как для Python-приложения выглядит:

# --- Этап 1: Сборка зависимостей ---
# Тут живёт жирный питон со всеми потрохами
FROM python:3.9 as builder

WORKDIR /app

# Делаем виртуальное окружение, чтоб не засорять систему
RUN python -m venv /opt/venv
ENV PATH="/opt/venv/bin:$PATH"

# Ставим зависимости в это окружение
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# --- Этап 2: Финальный образ ---
# А тут уже питон-скелет, голый и тощий
FROM python:3.9-slim

WORKDIR /app

# Волшебство! Тащим из первого этапа только готовый venv
COPY --from=builder /opt/venv /opt/venv

# Копируем свой код
COPY . .

# Пути прописываем
ENV PATH="/opt/venv/bin:$PATH"

# Поехали!
CMD ["python", "app.py"]

И какие, блядь, плюсы?

  • Размер, ёбта! Финальный образ легче пуха. Никакого хлама.
  • Безопасность, мать её. Меньше пакетов — меньше дырок, куда всякие пидарасы могут пролезть.
  • CI/CD радуется. Всё в одном файле, не надо городить огород из скриптов. Красота, блядь!