Передать переменные среды из докер-компоновки в контейнер на этапе сборки

Я пытаюсь создать конфигурацию для нескольких сред с одним Dockerfile, несколькими docker-compose файлами и несколькими envoronment_variables файлами. Мне нужно, чтобы он использовал другой файл с зависимостями python для каждой среды.

Скажем, мы создаем службу web в двух средах: development и production. Для этого я создаю следующую структуру файлов:

docker-compose-dev.yml
docker-compose-prod.yml
envs/
  dev.env
  prod.env
web/
  Dockerfile
  requirements_dev.txt 
  requirements_prod.txt

Цель состоит в том, чтобы создать собственное имя файла requirements_*.txt в Dockerfile в процессе build. Согласно документации, я пробовал этот наивный подход, который, похоже, не работает:

  • Определите имя как переменную среды:
    • envs/dev.env: REQUIREMENTS=requirements_dev.txt
    • envs/prod.env: REQUIREMENTS=requirements_prod.txt
  • Используйте эту переменную среды в Dockerfile:

    FROM python:3.5
    ENV PYTHONUNBUFFERED 1
    ENV APP_ROOT /usr/src/app
    ...
    COPY $REQUIREMENTS $APP_ROOT/
    RUN pip install -r $APP_ROOT/$REQUIREMENTS
    
  • Импортируйте соответствующее определение в конфигурацию docker-compose:

    version: '2'
    
    services:
        web:
            build: ./web
            env_file:
                - envs/dev.env   # in docker-compose-dev.yml
                - envs/prod.env   # in docker-compose-prod.yml
            ...
    

Когда я запускаю docker-compose up --build docker-compose-dev.yml, переменная $REQUIREMENTS не определена в процессе сборки.

В документации docker-compose есть заметка об этом:

Примечание. Если ваша служба указывает параметр сборки, переменные, определенные в файлах среды, не будут автоматически отображаться во время сборки. Используйте опцию args для сборки для определения переменных среды построения.

Но для использования опции ARG в Dockerfile, например ARG REQUIREMENTS, нужна соответствующая опция args в docker-compose, например:

services:
    web:
        build:
            context: ./web
            args:
                - REQUIREMENTS

Тем не менее, с этой конфигурацией мои тесты также потерпели неудачу, потому что, согласно документации, значение переменной REQUIREMENTS в файле Dockerfile взято из

среда, в которой выполняется компоновка

Следовательно, он принимает значение из моей оболочки, но не из envs/dev.env.

Итак, мой вопрос:

Возможно ли передать переменную среды из env_file в docker-compose в Dockerfile во время сборки без установки переменных локально в моей оболочке?

Ответ 1

Ваш docker-compose.yml должен выглядеть так:

version: '2'
services:
  web:
    build:
      context: ./web
      args:
        REQUIREMENTS: "requirements_dev.txt"

Ваш Dockerfile должен определить аргумент сборки с помощью ARG следующим образом:

FROM python:3.5
ENV PYTHONUNBUFFERED 1
ENV APP_ROOT /usr/src/app
ARG REQUIREMENTS
...
COPY $REQUIREMENTS $APP_ROOT/
RUN pip install -r $APP_ROOT/$REQUIREMENTS

Я проверил это и создал мини-функциональную демонстрацию на Github:

https://github.com/jannikweichert/stackoverflow-41747843