🐳 Копирование переменных между этапами в многоэтапной сборке Docker

Как скопировать переменные в образе Docker

by itisgood

1. Обзор

Функция многоступенчатых сборок в Docker позволяет разработчикам создавать последовательность сборок, каждая из которых имеет свой собственный набор инструкций.
Это помогает оптимизировать размер результирующего образа.
Одной из проблем многоэтапных сборок является копирование переменных между этапами.
Копирование переменных между этапами важно, поскольку позволяет нам повторно использовать значения на последующих этапах сборки.
В этом уроке мы рассмотрим три различных метода копирования переменных между этапами многоэтапной сборки Docker: использование ARG, использование ENV и использование файла.
Мы узнаем, как работает каждый из методов, а также рассмотрим пример, иллюстрирующий их использование.

2. Использование ARG

Самый простой способ копирования переменных между этапами многоэтапной сборки Docker – это использование ARG.
Мы можем использовать переменные ARG в процессе сборки и передавать их команде docker build в качестве аргументов сборки.
Давайте рассмотрим Dockerfile для копирования переменных в многоэтапной сборке:
# Stage 1
FROM alpine AS stage1
ARG MY_VAR
RUN echo MY_VAR value is $MY_VAR

# Stage 2
FROM alpine AS stage2
ARG MY_VAR
RUN echo MY_VAR is still set to: $MY_VAR

В этом примере мы определяем переменную MY_VAR с помощью ARG на обоих этапах.

Затем мы используем команду RUN для печати значения MY_VAR на каждом этапе.

Чтобы собрать образ и передать значение MY_VAR в качестве аргумента сборки, выполните следующую команду:

$ docker build --build-arg MY_VAR=somevalue -t my_image .

Система установит значение MY_VAR в “somevalue” во время процесса сборки:

$ docker build --build-arg MY_VAR=somevalue -t my_image .
Sending build context to Docker daemon  2.048kB
Step 1/6 : FROM alpine AS stage1
 ---> b2aa39c304c2
Step 2/6 : ARG MY_VAR
 ---> Running in 38b3ef3093c3
Removing intermediate container 38b3ef3093c3
 ---> 5619deec98e2
Step 3/6 : RUN echo MY_VAR value is $MY_VAR
 ---> Running in 1bf3db328de6
MY_VAR value is somevalue
Removing intermediate container 1bf3db328de6
 ---> 5e9f9bc1255a
Step 4/6 : FROM alpine AS stage2
 ---> b2aa39c304c2
Step 5/6 : ARG MY_VAR
 ---> Running in 19d18d18f055
Removing intermediate container 19d18d18f055
 ---> 842a58a44c8e
Step 6/6 : RUN echo MY_VAR is still set to: $MY_VAR
 ---> Running in 88ba4ea6188b
MY_VAR is still set to: somevalue
Removing intermediate container 88ba4ea6188b
 ---> 6b912736db48
Successfully built 6b912736db48
Successfully tagged my_image:latest

В приведенном выше выводе хорошо видно, что значение ARG MY_VAR сохраняется на обоих этапах.

3. Использование ENV

Еще один способ копирования переменных между этапами многоэтапной сборки Docker – это использование ENV.

Мы можем использовать ENV для установки переменных, которые будут доступны в процессе сборки и сохранятся в результирующем образе.

Для примера создадим простой Dockerfile:

FROM alpine:latest as base
ENV MY_ENV="my_env"

FROM base
RUN echo ${MY_ENV}

Здесь мы создали переменную окружения MY_ENV на первом этапе Dockerfile.

Теперь эта переменная доступна для всех последующих этапов, которые создаются с помощью первого этапа.

Теперь давайте соберем образ Docker с помощью следующей команды:

$  docker build --no-cache  -t my_image .
Sending build context to Docker daemon   5.12kB
Step 1/4 : FROM alpine:latest as base
 ---> b2aa39c304c2
Step 2/4 : ENV MY_ENV="my_env"
 ---> Running in 7ffd89e261a2
Removing intermediate container 7ffd89e261a2
 ---> 17e87c9864c3
Step 3/4 : FROM base
 ---> 17e87c9864c3
Step 4/4 : RUN echo ${MY_ENV}
 ---> Running in 337470d2041d
my_env
Removing intermediate container 337470d2041d
 ---> 8e6abc31f316
Successfully built 8e6abc31f316
Successfully tagged my_image:latest

В приведенном выше выводе команда echo на шаге 4 выводит значение MY_ENV из первой стадии Dockerfile.

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

Переменные ARG передаются во время сборки и доступны только в процессе сборки, в то время как переменные ENV задаются в Dockerfile и могут быть доступны на последующих этапах.

4. Использование файла

Подход ARG полезен, когда нам нужно передать значение переменной от одного этапа к другому в процессе сборки. Он также полезен, когда мы хотим сделать значение переменной доступным в процессе сборки, но не в конечном образе.

Это связано с тем, что переменные ARG доступны только в процессе сборки и не сохраняются в конечном образе.

Другой способ копирования переменных между этапами многоэтапной сборки Docker – использование файла.

Этот метод предполагает запись значения переменной в файл на одном этапе, а затем чтение файла на другом этапе.

Для примера приведем простой Dockerfile:

# Stage 1 - Build
FROM alpine AS build

# Write the variable value to a file
RUN echo "hello" > /tmp/myvar

# Stage 2 - Run
FROM alpine AS run

# Copy the variable value from the previous stage using a file
COPY --from=build /tmp/myvar /tmp/myvar
# Read the variable value from the file
RUN MY_VAR=$(cat /tmp/myvar) && echo "Running the app with MY_VAR=$MY_VAR"

В этом примере у нас есть два этапа: “build” и “run”.

На этапе “сборка” значение “hello” записывается в файл /tmp/myvar.

На этапе “run” мы копируем файл с предыдущего этапа и читаем его содержимое с помощью команды cat.

Затем мы устанавливаем переменную окружения MY_VAR в значение файла и выводим его с помощью команды echo.

$ docker build --no-cache -t my_image .
Sending build context to Docker daemon  7.168kB
Step 1/6 : FROM alpine AS build
 ---> b2aa39c304c2
Step 2/6 : RUN echo "hello" > /tmp/myvar
 ---> Running in db7cbe1a060f
Removing intermediate container db7cbe1a060f
 ---> 3c64d471fe3a
Step 3/6 : RUN echo "Building the app..."
 ---> Running in 08c4d8024c53
Building the app...
Removing intermediate container 08c4d8024c53
 ---> 4cc6f20768e5
Step 4/6 : FROM alpine AS run
 ---> b2aa39c304c2
Step 5/6 : COPY --from=build /tmp/myvar /tmp/myvar
 ---> 3dc259424cb6
Step 6/6 : RUN MY_VAR=$(cat /tmp/myvar) && echo "Running the app with MY_VAR=$MY_VAR"
 ---> Running in 961f02320a71
Running the app with MY_VAR=hello
Removing intermediate container 961f02320a71
 ---> 1a8c5349f42b
Successfully built 1a8c5349f42b
Successfully tagged my_image:latest

В приведенном выше выводе мы видим, что значение MY_VAR (шаг 6) доступно на втором этапе.

Мы также можем проверить содержимое файла внутри докер-контейнера:

$ docker run --rm my_image /bin/sh -c "cat /tmp/myvar"
hello

Такой подход удобен, когда нам нужно сделать переменную доступной в конечном образе.

Мы можем записать значение переменной в файл на одном этапе, а затем скопировать его на другой этап.

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

5. Заключение

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

см. также:

You may also like

Leave a Comment