1. Обзор
2. Использование ARG
# 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 и файла.
см. также:
- 🐳 Простой веб-шаринг с использованием docker
- 🐳 Переключение пользователя в образе или контейнере Docker
- 🐳 GitLab CI: Как создавать образы Docker в Kubernetes
- 🐳Как удалить программное обеспечение docker.io на Ubuntu
- 🕵️ Игнорируем Sudo в shell скриптах, если вы работаете от имени Root
- 🐳 Как привязать контейнер без пользователя root к привилегированному порту на Linux
- 🐳 Вход в контейнер с правами Root без Sudo или пароля