Разный env файл, но тот же yml с Docker Compose?
Я считаю довольно распространенным, что у меня есть несколько сред (например, test и prod), но контейнеры Docker, которые я хочу запустить, одинаковы в обеих средах. Единственная разница - это конфигурация приложения, которую я хочу указать с помощью env-file
. Поскольку у меня есть несколько контейнеров и зависимости между ними, я хочу использовать docker-compose. Но afaik я могу указать env-file
внутри файла docker-compose.yml
(см. docs). Если это так, мне нужно клонировать мой оригинальный docker-compose.yml
в два разных файла (один для теста и один для prod), чтобы указать на разные файлы env. Это означает, что я должен поддерживать два docker-compose.yml
файла вместо одного, и если я вношу какие-либо изменения, мне нужно обновить оба файла.
Это действительно соответствует дизайну? Почему docker-compose
не указывать --env-file
, когда я делаю docker-compose up
или docker-compose run
?
Ответы
Ответ 1
См. обновление № 2 ниже. Теперь это возможно!
Это очень востребованная функция Docker Compose. К сожалению, ответ на данный момент заключается в том, что вы не можете. Я бы рекомендовал подписаться на эти вопросы GitHub, чтобы лучше понять, когда и если эта функция будет реализована:
Проблема № 495 на самом деле наиболее прокомментирована в их репозитории выпуска на данный момент. Вы определенно не одиноки в этом, чтобы это сделать.
Update:
Последнее отслеживание проблем находится в https://github.com/docker/compose/issues/1377.
Обновление # 2:
Эта функциональность была объединена и доступна с Docker Compose 1.5.0. Для использования информации см. https://github.com/docker/compose/blob/129092b7/docs/yml.md#variable-substitution.
Ответ 2
Это не прямое включение из командной строки, но если вам требуется обход перед слияние # 1765 (исправление для # 1377) делает его выпуском, вы можете использовать extends
вместе с директивой env_file
. Для удобства файлы из приведенных ниже простых примеров воспроизводятся в этом репозитории.
Глупый простой пример
base.yml
base:
image: busybox
command: bash -c 'echo "${WHO:-Simon} says, \"${SHOUTOUT:-Silence is golden.}\""'
one.env
WHO=Da Schwartz
SHOUTOUT=Get to...
one_glue.yml
one:
extends:
file: base.yml
service: base
env_file:
- one.env
two.env
WHO=Da Schwartz
SHOUTOUT=...da choppa!
two_glue.yml
two:
extends:
file: base.yml
service: base
env_file:
- two.env
Использование
% for i in base one_glue two_glue ; do docker-compose --file "${i}.yml" up ; done
Recreating dockercomposeextendsenv_base_1...
Attaching to dockercomposeextendsenv_base_1
base_1 | Simon says, "Silence is golden."
dockercomposeextendsenv_base_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Recreating dockercomposeextendsenv_one_1...
Attaching to dockercomposeextendsenv_one_1
one_1 | Da Schwartz says, "Get to..."
dockercomposeextendsenv_one_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Recreating dockercomposeextendsenv_two_1...
Attaching to dockercomposeextendsenv_two_1
two_1 | Da Schwartz says, "...da choppa!"
dockercomposeextendsenv_two_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Даже более простой пример
Вышеупомянутое работает, если вы используете файлы .env
. Если вы не настолько ограничены, вы можете сохранить параметры переменной среды в файлах "glue" .yml
для среды:
red_glue.yml
red:
extends:
file: base.yml
service: base
environment:
- WHO=Stallion
- SHOUTOUT=I am...
blue_glue.yml
blue:
extends:
file: base.yml
service: base
environment:
- WHO=Stallion
- SHOUTOUT=...the law!
Использование
% for i in red_glue blue_glue ; do docker-compose --file "${i}.yml" up ; done
Creating dockercomposeextendsenv_red_1...
Attaching to dockercomposeextendsenv_red_1
red_1 | Stallion says, "I am..."
dockercomposeextendsenv_red_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Creating dockercomposeextendsenv_blue_1...
Attaching to dockercomposeextendsenv_blue_1
blue_1 | Stallion says, "...the law!"
dockercomposeextendsenv_blue_1 exited with code 0
Gracefully stopping... (press Ctrl+C again to force)
Немного сложнее
Для того, что стоит, подход, описанный в этом ответе, позволяет использовать разные файлы .env
для каждого экземпляра, а не для каждого вызова/среды. (Я не уверен, насколько это полезно на практике.) Другими словами, вы можете сделать что-то вроде этого:
testing.yml
# Only instance1 and instance2 are needed for testing
instance1:
extends:
file: base.yml
service: base
env_file:
- test.env # environment-specific
- instance1_test.env # instance-specific
instance2:
extends:
file: base.yml
service: base
env_file:
- test.env
- instance2_test.env
production.yml
# All four instances are used for production
instance1:
extends:
file: base.yml
service: base
env_file:
- prod.env # environment-specific
- instance1_prod.env # instance-specific
instance2:
extends:
file: base.yml
service: base
env_file:
- prod.env
- instance2_prod.env
instance3:
extends:
file: base.yml
service: base
env_file:
- prod.env
- instance3_prod.env
instance4:
extends:
file: base.yml
service: base
env_file:
- prod.env
- instance4_prod.env
Вы можете начать видеть, что extends
довольно мощный, гораздо больше, чем позволяет # 1765 merge.
Ответ 3
Хорошие яркие примеры, однако это изначально не работало для меня, пока я не обновил base.yml, чтобы вызвать оболочку пепла.
base.yml
base:
image: busybox
command: ash -c 'echo "${WHO:-Simon} says, \"${SHOUTOUT:-Silence is golden.}\""'