← Назад к вопросам
В чем разница между ARG и ENV в Dockerfile?
2.0 Middle🔥 171 комментариев
#DevOps и инфраструктура
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
# ARG vs ENV в Dockerfile: полное объяснение
Краткое сравнение
| Параметр | ARG | ENV |
|---|---|---|
| Доступность | Только при сборке (build-time) | При сборке и runtime |
| Видимость в контейнере | Нет | Да |
| Вариант переиспользования | --build-arg при docker build | Не переопределяется (нужен новый образ) |
| Слои образа | Не сохраняется в слое | Сохраняется в слое образа |
| История слоев | Не видна в docker history | Видна в docker history |
| Размер образа | Не влияет | Может увеличить размер |
| Пример | Версия зависимости при сборке | PORT=8000 для приложения |
ARG (Build-time Arguments)
ARG — переменная, которая существует только во время сборки образа. После завершения сборки она недоступна.
Синтаксис
ARG <name>
ARG <name>=<default_value>
Пример 1: базовое использование
FROM ubuntu:22.04
# Определяем переменную сборки
ARG PYTHON_VERSION=3.11
ARG INSTALL_DEV=false
# Используем ARG
RUN apt-get update && apt-get install -y \
python${PYTHON_VERSION} \
&& apt-get clean
RUN if [ "$INSTALL_DEV" = "true" ]; then \
apt-get install -y python${PYTHON_VERSION}-dev; \
fi
CMD ["python${PYTHON_VERSION}", "--version"]
Использование при сборке
# По умолчанию (Python 3.11)
$ docker build -t my-python .
# С переопределением
$ docker build --build-arg PYTHON_VERSION=3.10 -t my-python .
# Несколько аргументов
$ docker build \
--build-arg PYTHON_VERSION=3.9 \
--build-arg INSTALL_DEV=true \
-t my-python .
Пример 2: ARG в многоэтапной сборке
# Stage 1: Builder
FROM python:3.11 as builder
ARG BUILD_DEPS="build-essential libssl-dev"
RUN apt-get update && apt-get install -y $BUILD_DEPS
WORKDIR /build
COPY requirements.txt .
RUN pip install --user -r requirements.txt # создаёт ~/.local
# Stage 2: Runtime (гораздо меньше)
FROM python:3.11-slim
# ARG из stage 1 не доступна здесь!
# Нужно переопределить, если необходимо
ARG APP_VERSION=unknown
COPY --from=builder /root/.local /root/.local
ENV PATH=/root/.local/bin:$PATH
WORKDIR /app
COPY . .
RUN echo "App version: $APP_VERSION" # работает только на время сборки
CMD ["python", "app.py"]
$ docker build --build-arg APP_VERSION=1.2.3 -t my-app .
Важная особенность: ARG не видна в контейнере
ARG DEBUG=true
# Попытка использовать в CMD не сработает
CMD ["sh", "-c", "echo $DEBUG"] # выведет пусто!
# Нужно использовать во время сборки
RUN echo "Debug mode: $DEBUG" # это сработает
ENV (Environment Variables)
ENV — переменная окружения, доступная как при сборке образа, так и при запуске контейнера.
Синтаксис
ENV <key>=<value>
ENV <key> <value> # альтернативная форма (старый синтаксис)
Пример 1: базовое использование
FROM python:3.11
# Переменные окружения
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV APP_HOME=/app
ENV PORT=8000
WORKDIR $APP_HOME
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["python", "manage.py", "runserver", "0.0.0.0:${PORT}"]
Эти переменные доступны в контейнере:
$ docker run -it my-app
$ env | grep PYTHON
PYTHONUNBUFFERED=1
PYTHONDONTWRITEBYTECODE=1
PORT=8000
Пример 2: переопределение ENV при запуске
FROM ubuntu:22.04
ENV GREETING="Hello"
ENV NAME="World"
CMD ["sh", "-c", "echo $GREETING, $NAME!"]
# При сборке — используются значения из Dockerfile
$ docker build -t greeting .
$ docker run greeting
# Hello, World!
# При запуске — можно переопределить
$ docker run -e GREETING="Hi" -e NAME="Python" greeting
# Hi, Python!
Пример 3: multi-stage с ENV
FROM node:18 as builder
ENV NODE_ENV=production
WORKDIR /build
COPY . .
RUN npm install --production # использует ENV
RUN npm run build
# Stage 2
FROM node:18-alpine
ENV NODE_ENV=production
ENV PORT=3000
WORKDIR /app
COPY --from=builder /build/dist .
COPY --from=builder /build/node_modules ./node_modules
EXPOSE $PORT
CMD ["node", "index.js"]
Когда использовать ARG?
✅ ARG используй для:
- Версии при сборке — версия Python, версия библиотеки
ARG PYTHON_VERSION=3.11
ARG NODE_VERSION=18
RUN curl https://example.com/python-${PYTHON_VERSION}.tar.gz
- Условная сборка — собрать с dev или production зависимостями
ARG BUILD_ENV=production
RUN if [ "$BUILD_ENV" = "development" ]; then \
pip install -r requirements-dev.txt; \
else \
pip install -r requirements.txt; \
fi
- Информация о сборке — номер версии приложения, дата сборки
ARG BUILD_DATE
ARG VCS_REF
ARG VERSION
LABEL org.label-schema.build-date=$BUILD_DATE \
org.label-schema.vcs-ref=$VCS_REF \
org.label-schema.version=$VERSION
- Оптимизация размера — исключение зависимостей
ARG INCLUDE_DOCS=false
RUN if [ "$INCLUDE_DOCS" = "true" ]; then \
apt-get install -y sphinx; \
fi
Когда использовать ENV?
✅ ENV используй для:
- Конфигурация приложения — порт, хост, уровень логирования
ENV APP_PORT=8000
ENV LOG_LEVEL=INFO
ENV DATABASE_URL=postgresql://localhost/db
- Поведение интерпретатора Python
ENV PYTHONUNBUFFERED=1 # вывод в реальном времени
ENV PYTHONDONTWRITEBYTECODE=1 # не создавать .pyc файлы
ENV PYTHONHASHSEED=random # безопасность
- Переменные, которые меняются при запуске
ENV NODE_ENV=production
ENV API_KEY=default-value # переопределяется при запуске
- Переменные, которые должны быть видны приложению
ENV SERVICE_NAME=my-app
ENV SERVICE_PORT=3000
CMD ["node", "app.js"] # приложение видит эти переменные
Практический пример: Django приложение
FROM python:3.11-slim
# ARG: для настройки сборки
ARG REQUIREMENTS_FILE=requirements.txt
ARG INSTALL_DEV=false
# ENV: для конфигурации приложения
ENV PYTHONUNBUFFERED=1
ENV PYTHONDONTWRITEBYTECODE=1
ENV DJANGO_SETTINGS_MODULE=config.settings
ENV APP_HOME=/app
WORKDIR $APP_HOME
# Используем ARG при установке
COPY ${REQUIREMENTS_FILE} .
RUN pip install --no-cache-dir -r ${REQUIREMENTS_FILE}
if [ "$INSTALL_DEV" = "true" ]; then \
pip install pytest pytest-django black flake8; \
fi
COPY . .
# Используем ENV в CMD
EXPOSE $APP_PORT
CMD ["gunicorn", "config.wsgi", "--bind", "0.0.0.0:${APP_PORT:=8000}"]
Использование:
# Стандартная сборка
$ docker build -t django-app .
# С dev зависимостями
$ docker build --build-arg INSTALL_DEV=true -t django-app:dev .
# Запуск с переопределением PORT
$ docker run -e APP_PORT=9000 django-app
Слои образа и size
FROM ubuntu:22.04
# ARG не увеличивает размер образа
ARG BUILD_DEPS="gcc make"
RUN apt-get update && apt-get install -y $BUILD_DEPS && apt-get clean
# После RUN зависимости удалены, слой остаётся в истории, но не в финальном образе
# ENV увеличивает размер образа
ENV APP_CONFIG="value"
# Эта переменная хранится в метаданных образа и в контейнере
ARG можно использовать в FROM
Замечательная особенность — ARG можно использовать в инструкции FROM:
ARG BASE_IMAGE=ubuntu:22.04
FROM $BASE_IMAGE
RUN apt-get update && apt-get install -y python3
$ docker build --build-arg BASE_IMAGE=debian:bullseye -t my-app .
Итоги
ARG (Build-time):
- Существует только при сборке
- Не видна в контейнере
- Передаётся
--build-argпри сборке - Не сохраняется в слое образа
- Используй для настройки процесса сборки
ENV (Runtime):
- Существует при сборке и при запуске
- Видна в контейнере
- Может быть переопределена
-eпри запуске - Сохраняется в образе
- Используй для конфигурации приложения
Практическое правило:
- ARG = как собрать образ (версии, зависимости, параметры сборки)
- ENV = как работает приложение (конфиг, порты, логирование)