Как передать аргументы (ARG) внутрь Dockerfile во время сборки?

«Как передать аргументы (ARG) внутрь Dockerfile во время сборки?» — вопрос из категории Docker, который задают на 23% собеседований Devops Инженер. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Для параметризации сборки Docker-образа используются инструкции ARG (аргументы сборки). Они позволяют динамически менять версии ПО, пути, флаги компиляции и т.д.

Базовый синтаксис:

  1. Объявление аргумента в Dockerfile:
    FROM alpine:3.18
    # Объявляем аргумент с значением по умолчанию
    ARG APP_VERSION="1.0.0"
    # Аргумент без значения по умолчанию (должен быть передан)
    ARG BUILD_ENV
  2. Использование аргумента в инструкциях:
    RUN echo "Building version ${APP_VERSION} for environment ${BUILD_ENV}"
    # ARG можно использовать для задания ENV
    ENV APP_VERSION=${APP_VERSION}
  3. Передача значения при сборке через --build-arg:
    docker build 
    --build-arg APP_VERSION=2.5.0 
    --build-arg BUILD_ENV=production 
    -t myapp:latest .

Практический пример из опыта — сборка Java-приложения:

# Используем ARG для указания версии Maven и JDK
ARG MAVEN_VERSION=3.9.6
ARG JDK_VERSION=17

FROM maven:${MAVEN_VERSION}-eclipse-temurin-${JDK_VERSION} AS builder
WORKDIR /app
COPY pom.xml .
# Скачиваем зависимости (кешируем этот слой)
RUN mvn dependency:go-offline
COPY src ./src
RUN mvn clean package -DskipTests

FROM eclipse-temurin:${JDK_VERSION}-jre
ARG JAR_FILE="target/*.jar"
COPY --from=builder /app/${JAR_FILE} /app/app.jar
ENTRYPOINT ["java", "-jar", "/app/app.jar"]

Сборка с кастомными аргументами:

docker build --build-arg JDK_VERSION=21 --build-arg MAVEN_VERSION=3.9.5 -t myapp:jdk21 .

Важные особенности (Scope):

  • ARG существуют только на этапе сборки и не остаются в финальном образе или его истории. Чтобы значение сохранилось в контейнере на время выполнения, его нужно явно присвоить переменной ENV.
  • Каждый ARG «живет» только в одном этапе сборки. Если нужно использовать один и тот же аргумент в нескольких FROM (многоступенчатая сборка), его нужно объявить повторно в каждом нужном этапе.
  • Предопределенные ARG: Docker предоставляет несколько предопределенных ARG, таких как HTTP_PROXY, VERSION и др., которые можно использовать без объявления.