Почему подстановка переменных не работает при использовании нескольких env_files в docker-compose.yml?
Я пытаюсь получить файл, содержащий docker, работающий с несколькими .env
файлами, и мне не повезло. Я пытаюсь установить три .env
файла:
- глобальные параметры, одинаковые для всех экземпляров контейнера.
- настройки, зависящие от среды (материал только для теста или разработчика)
- локальные настройки - переопределяемые вещи, которые разработчик может потребовать изменить, если у них есть конфликты, например, с номером порта
Мой docker-compose.yml
файл выглядит следующим образом:
version: '2'
services:
db:
env_file:
- ./.env
- ./.env.${ENV}
- ./.env.local
image: postgres
ports:
- ${POSTGRES_PORT}:5432
.env
выглядит следующим образом:
POSTGRES_USER=myapp
и .env.development
выглядит следующим образом:
POSTGRES_PASSWORD=supersecretpassword
POSTGRES_HOST=localhost
POSTGRES_PORT=25432
POSTGRES_DB=myapp_development
.env.local
в этом случае не существует.
После запуска ENV=development docker-compose up
я получаю следующий вывод:
$ ENV=development docker-compose up
WARNING: The POSTGRES_PASSWORD variable is not set. Defaulting to a blank string.
WARNING: The POSTGRES_DB variable is not set. Defaulting to a blank string.
WARNING: The POSTGRES_PORT variable is not set. Defaulting to a blank string.
ERROR: The Compose file './docker-compose.yml' is invalid because:
services.db.ports is invalid: Invalid port ":5432", should be [[remote_ip:]remote_port[-remote_port]:]port[/protocol]
Из этого сообщения об ошибке выглядит, что ни одна из моих переменных среды не используется. Я просто обновился до новейшей доступной документации докеры - также - те же ошибки:
$ docker-compose --version
docker-compose version 1.8.0-rc1, build 9bf6bc6
Любые идеи здесь? Было бы неплохо иметь один docker-compose.yml
, который будет работать в нескольких средах.
Ответы
Ответ 1
Имейте в виду, что существуют две разные среды, в которых вы определяете переменные. Хост-компьютер, на котором выполняется команда создания докеры, и сам контейнер (запуск службы db в вашем случае).
В вашем файле docker-compose.yml
есть доступ к вашим переменным среды хоста. Следовательно, ENV
доступен из команды docker-compose
, но не в ваших файлах .env
.
Наоборот, значение для ENV
недоступно внутри контейнера, но все переменные, определенные в ваших файлах .env
, будут.
Я не знаю, действительно ли вам нужен ваш контейнер db
для доступа к переменным, определенным на вашем .env.development
. Но, по крайней мере, кажется, что ваша хост-машина должна иметь содержимое этого файла, поэтому, когда вызывается команда docker-compose, определяется переменная POSTGRES_PORT
.
Чтобы исправить вашу конкретную проблему, вам нужно будет также определять переменные среды на вашей главной машине, а не только для контейнера. Вы можете сделать что-то вроде этого:
#Set for host
ENV=development
#Also sets the variables on the host
source ./.env.$ENV
#POSTGRES_PORT defined in .env.development is used here
docker-compose up
#since env_file also contains .env.development, the variables will be reachable from the container.
Надеюсь, что это поможет.
Ответ 2
Чтобы применить разные/несколько env_files в зависимости от рабочей среды, такой как разработка/подготовка/производство, я думаю, что лучший способ для docker-compose - это использовать несколько docker-compose yml файлов.
Например:
1. Начните с базового файла, который определяет каноническую конфигурацию для сервисов.
docker-compose.yml
web:
image: example/my_web_app:latest
env_file:
- .env
2. Добавить файл переопределения для разработки, как следует из его названия, может содержать переопределения конфигурации для существующих служб или совершенно новых служб.
докер-compose.override.yml
web:
build: .
volumes:
- '.:/code'
ports:
- 8883:80
env_file:
- .env.dev
Когда вы запускаете docker-compose up
он автоматически читает переопределения.
3. Создайте другой файл переопределения для продакшен среды.
докер-compose.prod.yml
web:
ports:
- 80:80
env_file:
- .env.prod
Для развертывания с этим рабочим файлом Compose вы можете запустить
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
Заметка
Моя версия Docker:
$ docker -v
Docker version 18.06.1-ce, build e68fc7a
$ docker-compose -v
docker-compose version 1.22.0, build f46880fe
Ссылка: https://docs.docker.com/compose/extends/
Ответ 3
во время чтения этой страницы: https://docs.docker.com/compose/environment-variables/
и, исходя из моего понимания, вы должны сделать следующее:
для глобальных переменных (которые не должны меняться), создайте файл env следующим образом:
VAR1=VALUE1
VAR2=VALUE2
а для остальных (которые могут измениться) вы должны добавить свое имя в среду в файле docker-compose.yml следующим образом:
environment:
- VAR1
- VAR2
это приведет к значениям VAR1 и VAR2 из оболочки, в которой вы выполняете компоновку docker.
Надеюсь, это поможет.
Ответ 4
Существует неверное представление о файле .env и опции env_file в docker-compose.yml, поскольку это очень неоднозначно. Шин очень хорошо отмечает это в проблеме с github. Docker-compose не использует env_file. Я просто процитирую его резюме:
-
Подстановка переменных в вашем файле docker-compose.yml будет извлечена (в порядке убывания приоритета) из вашей оболочки и вашего файла .env.
-
Переменные, доступные в вашем контейнере, представляют собой комбинацию значений, найденных в ваших файлах env_file, и значений, описанных в разделе среды службы.
-
Это два совершенно разных набора функций.