← Назад к вопросам

В чем разница между ARG и ENV в Dockerfile?

2.0 Middle🔥 171 комментариев
#DevOps и инфраструктура

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

# ARG vs ENV в Dockerfile: полное объяснение

Краткое сравнение

ПараметрARGENV
ДоступностьТолько при сборке (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 используй для:

  1. Версии при сборке — версия Python, версия библиотеки
ARG PYTHON_VERSION=3.11
ARG NODE_VERSION=18

RUN curl https://example.com/python-${PYTHON_VERSION}.tar.gz
  1. Условная сборка — собрать с 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
  1. Информация о сборке — номер версии приложения, дата сборки
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
  1. Оптимизация размера — исключение зависимостей
ARG INCLUDE_DOCS=false

RUN if [ "$INCLUDE_DOCS" = "true" ]; then \
    apt-get install -y sphinx; \
    fi

Когда использовать ENV?

ENV используй для:

  1. Конфигурация приложения — порт, хост, уровень логирования
ENV APP_PORT=8000
ENV LOG_LEVEL=INFO
ENV DATABASE_URL=postgresql://localhost/db
  1. Поведение интерпретатора Python
ENV PYTHONUNBUFFERED=1  # вывод в реальном времени
ENV PYTHONDONTWRITEBYTECODE=1  # не создавать .pyc файлы
ENV PYTHONHASHSEED=random  # безопасность
  1. Переменные, которые меняются при запуске
ENV NODE_ENV=production
ENV API_KEY=default-value  # переопределяется при запуске
  1. Переменные, которые должны быть видны приложению
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 = как работает приложение (конфиг, порты, логирование)