Ответ
Для передачи динамических параметров из CI/CD в Docker используется механизм ARG (аргументов сборки).
1. Объявление аргумента в Dockerfile:
# Объявляем аргумент сборки
ARG APP_VERSION
ARG BUILD_ENV
# Используем его для установки переменной окружения
ENV APP_VERSION=${APP_VERSION}
ENV NODE_ENV=${BUILD_ENV}
# Или непосредственно в инструкциях
RUN echo "Building version ${APP_VERSION} for ${BUILD_ENV}"
2. Передача аргументов из CI/CD:
В GitLab CI (.gitlab-ci.yml):
build_image:
script:
- docker build
--build-arg APP_VERSION="$CI_COMMIT_TAG"
--build-arg BUILD_ENV="$CI_ENVIRONMENT_SLUG"
-t my-app:$CI_COMMIT_SHA .
В GitHub Actions:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build Docker image
run: |
docker build
--build-arg VERSION=${{ github.sha }}
--build-arg COMMIT_DATE="$(date -u)"
-t my-app:${{ github.sha }} .
3. Важные ограничения и best practices:
- Жизненный цикл: Значения
ARGдоступны только на этапеdocker build. Чтобы они были доступны в запущенном контейнере, их нужно явно скопировать вENV. - Безопасность: Не используйте
--build-argдля передачи секретов (паролей, токенов). Для этого предназначеныdocker build --secret(Docker BuildKit) или multi-stage сборка с временными файлами. - Кэширование: Изменение значения
ARGинвалидирует кэш Docker для всех последующих инструкций.
Пример с условной логикой в Dockerfile:
ARG TARGET_ENV=development
# Устанавливаем разные пакеты в зависимости от окружения
RUN if [ "$TARGET_ENV" = "production" ]; then
apt-get install -y --no-install-recommends production-packages;
else
apt-get install -y development-tools;
fi Ответ 18+ 🔞
А, слушай, тут простая, но хитрая тема — как из CI/CD пихать параметры в Docker. Ну, типа, версию сборки или окружение передать. Ёпта, без этого сейчас никуда.
1. Объявляем эти самые аргументы в Dockerfile:
Смотри, в самом начале файла пишешь ARG. Это как объявить переменную, которую потом можно будет подменить при сборке.
# Объявляем аргумент сборки
ARG APP_VERSION
ARG BUILD_ENV
# Используем его для установки переменной окружения
ENV APP_VERSION=${APP_VERSION}
ENV NODE_ENV=${BUILD_ENV}
# Или непосредственно в инструкциях
RUN echo "Building version ${APP_VERSION} for ${BUILD_ENV}"
Зачем копировать в ENV? А потому что ARG — это только для этапа сборки, чувак. Как только контейнер запустился — всё, значения испарились. А ENV — это уже внутрь контейнера, для рантайма. Без этого нихуя не заработает.
2. А теперь самое интересное — как это всё передать из CI/CD: Тут уже зависит от твоего пайплайна.
Вот как в GitLab CI (.gitlab-ci.yml) это выглядит:
build_image:
script:
- docker build
--build-arg APP_VERSION="$CI_COMMIT_TAG"
--build-arg BUILD_ENV="$CI_ENVIRONMENT_SLUG"
-t my-app:$CI_COMMIT_SHA .
Видишь эти --build-arg? Вот ими и пихаем. GitLab сам подставляет свои переменные окружения, типа номера коммита или тега. Удобно, бля.
А в GitHub Actions примерно так же, только синтаксис другой:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Build Docker image
run: |
docker build
--build-arg VERSION=${{ github.sha }}
--build-arg COMMIT_DATE="$(date -u)"
-t my-app:${{ github.sha }} .
В общем, принцип один — накатываешь флаги при вызове docker build, и всё.
3. Но есть важные подводные камни, ёбана!
- Про жизнь аргументов: Я уже говорил —
ARGживёт только покаdocker buildидёт. Хочешь, чтобы в запущенном контейнере было — копируй вENV. Иначе будешь охуевать, почему переменная пустая. - Про безопасность — это пиздец важно: Никогда, блядь, не используй
--build-argдля передачи секретов! Ни паролей, ни токенов, нихуя. Они останутся в истории сборки образа, любой, кто скачает образ, сможет их вытащить. Доверия к такому подходу — ебать ноль. Для секретов естьdocker build --secret(если BuildKit включён) или многостадийная сборка с временными файлами. - Про кэширование: Если ты меняешь значение
ARG— Docker сносит кэш нахуй для всех инструкций, которые идут после этого аргумента. Имей в виду, а то сборка будет вечность.
Вот ещё пример, если нужно по-разному собирать для dev и prod:
ARG TARGET_ENV=development
# Устанавливаем разные пакеты в зависимости от окружения
RUN if [ "$TARGET_ENV" = "production" ]; then
apt-get install -y --no-install-recommends production-packages;
else
apt-get install -y development-tools;
fi
Тут логика простая: если передали production — ставим одно, если нет (или передали development) — другое. Условные конструкции в RUN — твой друг, но не переусердствуй, а то Dockerfile превратится в пиздопроебибну.