Это пост, в котором я покажу вам, как еще больше улучшить Dockerfile, используя многоэтапные сборки. Использование этапов сборки в ваших сборках — сложно, но есть некоторые вещи, в которых приведенные ниже знания могут вам помочь.
Возьмем примерный код Dockerfile для сборки среды исполнения проекта PHP. Почему PHP? Да просто, он всем знаком и на нем легче понять логику работы, я надеюсь 😃
FROM php:7.4.25-fpm
WORKDIR /app
COPY --from=composer:2.1.11 /usr/bin/composer /usr/bin/composer
RUN apt update && \
apt install -y \
libicu-dev=67.1-7 \
libgd-dev=2.3.0-2 \
libonig-dev=6.9.6-1.1 \
unzip=6.0-26 && \
apt purge -y --auto-remove
RUN docker-php-ext-install \
exif \
gd \
intl \
mbstring \
mysqli \
opcache \
pdo_mysql \
sockets
ENV COMPOSER_ALLOW_SUPERUSER 1
COPY composer.json .
COPY composer.lock .
RUN composer install --no-dev --no-scripts
COPY . .
RUN composer dumpautoload --optimize
Каждая зависимость в вашем образе потенциально является источником уязвимостей, и вы должны поддерживать их в актуальном состоянии. Таким образом, хорошей практикой является сохранение минимума действительно необходимых зависимостей.
Итак, давайте попробуем избавиться от composer на нашем финальном образе. Composer требуется для установки наших серверных зависимостей, но не требуется во время выполнения нашего приложения. На самом деле, вы не должны хранить его в своем окончательном образе, потому что каждое изменение, например composer update
, удаляется после перезапуска контейнера, поэтому его присутствие может даже сбивать с толку.
Вы можете избавиться от этой зависимости, используя многоэтапную сборку
FROM composer:2.1.11 AS build
WORKDIR /app
COPY composer.json .
COPY composer.lock .
RUN composer install --no-dev --no-scripts --ignore-platform-reqs
COPY . .
RUN composer dumpautoload --optimize
FROM php:7.4.25-fpm
WORKDIR /app
RUN apt update && \
apt install -y \
libicu-dev=67.1-7 \
libgd-dev=2.3.0-2 \
libonig-dev=6.9.6-1.1 \
unzip=6.0-26 && \
apt purge -y --auto-remove
RUN docker-php-ext-install \
exif \
gd \
intl \
mbstring \
mysqli \
opcache \
pdo_mysql \
sockets
COPY --from=build /app /app
Итак, что здесь произошло? Как видите, я добавил новую FROM
инструкцию перед стадией PHP. Таким образом, мы можем добавить несколько этапов в наш образ докера. Слово AS
является псевдонимом для нашей сцены, которую мы можем использовать для обозначения ее. Обращение к этапу полезно, если нам нужно что-то скопировать между этапами или использовать предыдущий этап в качестве базового изображения для другого этапа.
В этом случае я добавил этап сборки с использованием образа composer, который установит все мои зависимости и сгенерирует файлы автозагрузки моего проекта.
Теперь, когда вы начнете собирать этот образ,
- Docker сначала создаст контейнер сборки
- Когда этап сборки будет завершен, докер начнет сборку следующего этапа
Также, как видите, я добавил --ignore-platform-reqs
флаг. Этот флаг позволит вам установить ваши зависимости, даже если у вас не установлены необходимые расширения PHP. В противном случае composer может остановить процесс установки, если для некоторых пакетов требуются расширения, которых нет в базовом образе composer.