Ответ
Инструкции ARG и ENV в Dockerfile обе используются для определения переменных, но имеют принципиально разные области видимости и жизненные циклы, что критично для безопасности и гибкости образов.
-
ARG(Аргументы сборки):- Назначение: Используются для передачи значений во время сборки Docker-образа (
docker build). - Видимость: Доступны только на этапе сборки, в слоях, следующих за объявлением
ARG. После завершения сборки они не сохраняются в финальном Docker-образе. - Почему это важно: Это позволяет передавать конфиденциальные данные (например, токены, пароли) на этапе сборки, не включая их в конечный образ, что повышает безопасность и уменьшает размер образа.
- Передача: Значения передаются с помощью флага
--build-arg <имя>=<значение>при вызовеdocker build. - Пример:
ARG APP_VERSION=1.0.0 ARG BUILD_DATE RUN echo "Building application version ${APP_VERSION} on ${BUILD_DATE}" # APP_VERSION и BUILD_DATE не будут доступны в запущенном контейнере
- Назначение: Используются для передачи значений во время сборки Docker-образа (
-
ENV(Переменные окружения):- Назначение: Определяют переменные окружения, которые будут доступны во время выполнения контейнера (
docker run). - Видимость: Доступны во всех последующих слоях Dockerfile после объявления и в запущенном контейнере. Они сохраняются в финальном Docker-образе.
- Почему это важно: Позволяет конфигурировать приложение внутри контейнера без пересборки образа, например, для разных сред (dev, staging, prod) или для настройки поведения приложения.
- Передача/Переопределение: Могут быть переопределены при запуске контейнера с помощью флага
-e <имя>=<значение>. - Пример:
ENV DB_HOST=localhost ENV DB_PORT=5432 CMD ["sh", "-c", "echo "Connecting to ${DB_HOST}:${DB_PORT}" && python app.py"] # DB_HOST и DB_PORT будут доступны в контейнере
- Назначение: Определяют переменные окружения, которые будут доступны во время выполнения контейнера (
Ключевое отличие:
ARG— для сборки образа, не сохраняется в нём. Используется для параметризации процесса сборки.ENV— для выполнения контейнера, сохраняется в образе. Используется для настройки поведения приложения внутри контейнера.
Ответ 18+ 🔞
О, смотри-ка, какая тема подъехала! Прямо как раз про ту самую магию, когда вроде бы и ARG, и ENV — переменные, а на деле разница, как между хуем и пальцем. Сейчас разжуём, чтобы ни у кого сомнений не осталось.
Представь, ты строишь дом (это наш образ). ARG — это как чертёж и инструменты, которые тебе привезли на стройку. Пока дом строится (docker build), ты ими вовсю пользуешься: вот тут окно поставить, тут дверь. Но как только дом построен и ты заходишь в него жить (docker run), ни чертежей, ни шуруповёрта внутри уже нет. Их съели гномы. То есть, ARG живут только на этапе сборки, а потом испаряются, нахуй.
А вот ENV — это уже обстановка в самом доме. Диван, холодильник, свет. Они уже внутри готового дома и доступны всем, кто в нём живёт (процессам в контейнере). И что важно — эту обстановку можно даже немного переставить, когда уже заехал, через -e.
Короче, запомни так:
ARG— для строителей (сборка). Всё, что нужно, чтобы собрать образ, но в финальный продукт не попадает. Идеально для всяких токенов на скачивание зависимостей — засунул, использовал, и след простыл.ENV— для жильцов (запуск). Это настройки, в которых приложение будет работать внутри контейнера. Они остаются в образе навсегда (пока не пересоберёшь).
Вот тебе наглядный пиздец, то есть пример:
# ARG — виден только при сборке, как призрак
ARG SECRET_KEY_FOR_DOWNLOAD=supersecret123
RUN curl -H "Authorization: Bearer ${SECRET_KEY_FOR_DOWNLOAD}" https://api.example.com/libs.tar.gz -o libs.tar.gz
# После этой строки SECRET_KEY_FOR_DOWNLOAD — тлен. В образе его нет. Безопасность, ёпта!
# ENV — переезжает в контейнер на ПМЖ
ENV DATABASE_URL=postgresql://prod-db:5432
ENV LOG_LEVEL=INFO
# Эти две подруги будут болтаться внутри каждого запущенного контейнера
CMD ["python", "app.py"]
А теперь главный жизненный лайфхак, от которого волосы дыбом: значение ARG можно передать в ENV. Это как взять кирпич со стройки (ARG) и вмуровать его в стену дома (ENV), чтобы он там навеки остался. Делается это просто:
ARG APP_VERSION=1.0.0
# А теперь превращаем аргумент сборки в переменную окружения
ENV APP_VERSION=${APP_VERSION}
Теперь APP_VERSION будет и при сборке доступна (как ARG), и в запущенном контейнере (как ENV). Удобно, блядь.
Итог для самых тупых (шучу, для закрепления):
- Хочешь что-то передать только на этапе стройки (версию, ссылку, токен) — юзай
ARGи спи спокойно, в образе этого не будет. - Хочешь, чтобы настройки были в самом контейнере и управляли работой приложения — это
ENV. Их можно и при сборке задать, и при запуске перебить.
Всё, теперь ты гуру. Не перепутай, а то получится пиздопроебибна, а не образ.