Поиск по сайту:

Что такое многоэтапные сборки Docker?


Многоэтапные сборки Docker позволяют создавать файлы Dockerfile с несколькими операторами FROM. Это означает, что вы можете создавать образы, основанные на нескольких базах, что может помочь уменьшить размер окончательной сборки.

Образы Docker создаются путем выбора базового образа с помощью оператора FROM. Затем вы добавляете слои к этому образу, добавляя команды в свой Dockerfile.

С помощью многоэтапных сборок вы можете разделить файл Dockerfile на несколько разделов. Каждый этап имеет свой собственный оператор FROM, поэтому вы можете использовать более одного изображения в своих сборках. Этапы строятся последовательно и могут ссылаться на своих предшественников, поэтому вы можете копировать вывод одного слоя в следующий.

Многоэтапные сборки в действии

Давайте посмотрим, как можно создать многоэтапную сборку. Мы работаем с базовым PHP-проектом, который использует Composer для своих зависимостей и Sass для своих таблиц стилей.

Вот многоэтапный Dockerfile, который инкапсулирует всю нашу сборку:

FROM node:14 AS sass
WORKDIR /example
RUN npm install -g node-sass
COPY example.scss .
RUN node-sass example.scss example.css
 
FROM php:8.0-apache
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
COPY composer.json .
COPY composer.lock .
RUN composer install --no-dev
COPY --from=sass /example/example.css example.css
COPY index.php .
COPY src/ src

Сразу же вы заметите, что у нас есть два оператора FROM, которые разбивают наш Dockerfile на два логических раздела. Первый этап посвящен компиляции Sass, а второй фокусируется на объединении всего вместе в финальном контейнере.

Мы используем реализацию Sass node-sass. Поэтому мы начинаем с базового образа Node.JS, внутри которого мы глобально устанавливаем node-sass из npm. Затем мы используем node-sass для компиляции нашей таблицы стилей example.scss в чистый CSS example.css. Подводя итог этому этапу, мы берем базовый образ, запускаем команду и получаем вывод, который хотели бы использовать позже в нашей сборке (example.css).

На следующем этапе вводится базовый образ для нашего приложения: php8.0-apache. Последний оператор FROM в вашем Dockerfile определяет образ, который будут запускать ваши контейнеры. Наш предыдущий образ node в конечном счете не имеет отношения к контейнерам нашего приложения — он используется исключительно как удобный инструмент во время сборки.

Затем мы используем Composer для установки наших зависимостей PHP. Composer — это менеджер пакетов PHP, но он не включен в официальные образы PHP Docker. Поэтому мы копируем двоичный файл в наш контейнер из выделенного образа Composer.

Для этого нам не понадобился оператор FROM. Поскольку мы не запускаем никаких команд для изображения Composer, мы можем использовать флаг --from с COPY для ссылки на изображение. Обычно COPY копирует файлы из вашего локального контекста сборки в ваш образ; с --from и именем изображения, он создаст новый контейнер, используя это изображение, а затем скопирует из него указанный файл.

Позже наш Dockerfile снова использует COPY --from, на этот раз в другой форме. Вверху мы написали наш первый оператор FROM как FROM node:14 AS sass. Предложение AS создало именованный этап с именем sass.

Теперь мы ссылаемся на временный контейнер, созданный на этом этапе, с помощью COPY --from=sass. Это позволяет нам скопировать наш встроенный CSS в наше окончательное изображение. Остальные шаги представляют собой рутинные операции COPY, используемые для получения нашего исходного кода из нашего локального рабочего каталога.

Преимущества многоэтапных сборок

Многоэтапные сборки позволяют создавать сложные процедуры сборки с помощью одного Dockerfile. До их появления в сложных проектах было обычным делом использовать несколько файлов Dockerfile, по одному на каждом этапе их сборки. Затем их нужно было организовать с помощью написанных вручную сценариев оболочки.

При многоэтапных сборках вся наша система сборки может содержаться в одном файле. Вам не нужны никакие скрипты-оболочки, чтобы перевести ваш проект из необработанной кодовой базы в окончательный образ приложения. Обычной сборки docker -t my-image:latest . достаточно.

Это упрощение также дает возможность повысить эффективность ваших изображений. Образы Docker могут стать большими, особенно если вы используете языковую среду выполнения в качестве основы.

Возьмем официальное изображение golang: оно весит около 300 МБ. Традиционно вы можете скопировать исходный код Go в образ и использовать его для компиляции двоичного файла. Затем вы скопируете свой двоичный файл обратно на хост-компьютер, прежде чем запускать другую сборку. Здесь будет использоваться файл Dockerfile с облегченным базовым образом, таким как alpine (около 10 МБ). Вы добавите свой двоичный файл обратно, в результате чего изображение будет намного меньше, чем если бы вы использовали исходную базу golang для запуска своих контейнеров.

С многоэтапными сборками такую систему реализовать намного проще:

FROM golang:latest
WORKDIR /go
COPY app.go .
RUN go build -o my-binary
 
FROM alpine:latest
WORKDIR /app
COPY --from=build /go/my-binary .
CMD ["./my-binary"]

В восьми строках нам удалось реализовать процедуру, для которой ранее требовалось как минимум три файла — golang Dockerfile, alpine Dockerfile и сценарий оболочки для управления промежуточные шаги.

Заключение

Многоэтапные сборки могут значительно упростить создание сложных образов Docker. Они позволяют задействовать несколько взаимосвязанных шагов сборки, которые могут передавать выходные артефакты вперед.

Модель также способствует повышению эффективности сборки. Легкость, с которой вы можете ссылаться на различные базовые изображения, помогает разработчикам гарантировать, что конечный результат будет как можно меньше. Вы выиграете от снижения затрат на хранение и пропускную способность, которые могут быть значительными при использовании Docker в системе CI/CD.




Все права защищены. © Linux-Console.net • 2019-2024