Как использовать переменные окружения в docker compose


218

Я хотел бы иметь возможность использовать переменные env внутри docker-compose.yml со значениями, переданными во время docker-compose up. Это пример. Я делаю это сегодня с помощью базовой команды запуска Docker, которая обернута вокруг моего собственного сценария. Есть ли способ добиться этого с помощью compose, без каких-либо оболочек для bash?

proxy:
  hostname: $hostname
  volumes:
    - /mnt/data/logs/$hostname:/logs
    - /mnt/data/$hostname:/data

2
Для других вариантов см .: docs.docker.com/compose/environment-variables
Massood Khaari

2
Это решено в последней версии compose, ваш пример будет работать так, как есть. проверьте docs.docker.com/compose/compose-file/#variable-substitution о подстановке переменных.
natbusa

1
Не забудьте приложение-докер (с июня 2018 года): stackoverflow.com/a/51007138/6309
VonC

Ответы:


93
  1. Создание template.yml, которое является вашим docker-compose.ymlс переменным окружением.
  2. Предположим, что ваши переменные окружения находятся в файле 'env.sh'
  3. Поместите приведенный ниже фрагмент кода в файл sh и запустите его.

источник env.sh; rm -rf docker-compose.yml; envsubst <"template.yml"> "docker-compose.yml";

docker-compose.ymlБудет создан новый файл с правильными значениями переменных среды.

Пример файла template.yml:

oracledb:
        image: ${ORACLE_DB_IMAGE}
        privileged: true
        cpuset: "0"
        ports:
                - "${ORACLE_DB_PORT}:${ORACLE_DB_PORT}"
        command: /bin/sh -c "chmod 777 /tmp/start; /tmp/start"
        container_name: ${ORACLE_DB_CONTAINER_NAME}

Пример файла env.sh:

#!/bin/bash 
export ORACLE_DB_IMAGE=<image-name> 
export ORACLE_DB_PORT=<port to be exposed> 
export ORACLE_DB_CONTAINER_NAME=ORACLE_DB_SERVER

@Meet Не стесняйтесь проверить мой ответ ниже, под "BASH решение", где я обрисовываю этот подход немного более тщательно.
modulitos

7
все еще нет лучшего решения на данный момент?
lvthillo

13
почему вы рекурсивно удаляете файл? (rm -rf docker-compose.yml)
moritzschaefer

@ lorenzvth7 Вы можете проверить мой ответ ниже, который я считаю более подробным: stackoverflow.com/a/33186458/1884158
modulitos

5
-1 это решение только усложняет ситуацию и должно быть обновлено в соответствии с новыми возможностями docker-compose docs.docker.com/compose/environment-variables/…
Эфрат Левитан

240

Решение DOCKER:

Похоже, что docker-compose 1.5+ включил подстановку переменных: https://github.com/docker/compose/releases

Последняя версия Docker Compose позволяет получить доступ к переменным окружения из вашего файла compose. Таким образом, вы можете получить исходные переменные окружения, а затем запустить Compose следующим образом:

set -a
source .my-env
docker-compose up -d

Затем вы можете ссылаться на переменные в docker-compose.yml, используя $ {VARIABLE}, вот так:

db:
  image: "postgres:${POSTGRES_VERSION}"

А вот дополнительная информация из документов, взятых здесь: https://docs.docker.com/compose/compose-file/#variable-substitution

Когда вы запускаете docker-compose up с этой конфигурацией, Compose ищет переменную среды POSTGRES_VERSION в оболочке и подставляет ее значение в. В этом примере Compose разрешает образ в postgres: 9.3 перед запуском конфигурации.

Если переменная окружения не установлена, Compose подставляет пустую строку. В приведенном выше примере, если POSTGRES_VERSION не установлен, значение для параметра изображения - postgres :.

Поддерживаются оба синтаксиса $ VARIABLE и $ {VARIABLE}. Расширенные функции стиля оболочки, такие как $ {VARIABLE-default} и $ {VARIABLE / foo / bar}, не поддерживаются.

Если вам нужно поместить буквенный знак доллара в значение конфигурации, используйте двойной знак доллара ($$).

И я считаю, что эта функция была добавлена ​​в этом запросе на получение доступа : https://github.com/docker/compose/pull/1765

Решение BASH:

Я заметил, что у людей есть проблемы с поддержкой переменных окружения Докера. Вместо того, чтобы иметь дело с переменными среды в Docker, давайте вернемся к основам, таким как bash! Вот более гибкий метод, использующий скрипт bash и .envфайл.

Пример файла .env:

EXAMPLE_URL=http://example.com
# Note that the variable below is commented out and will not be used:
# EXAMPLE_URL=http://example2.com 
SECRET_KEY=ABDFWEDFSADFWWEFSFSDFM

# You can even define the compose file in an env variable like so:
COMPOSE_CONFIG=my-compose-file.yml
# You can define other compose files, and just comment them out
# when not needed:
# COMPOSE_CONFIG=another-compose-file.yml

затем запустите скрипт bash в той же директории, которая должна правильно развернуть все:

#!/bin/bash

docker rm -f `docker ps -aq -f name=myproject_*`
set -a
source .env
cat ${COMPOSE_CONFIG} | envsubst | docker-compose -f - -p "myproject" up -d

Просто укажите ваши переменные env в вашем файле compose с обычным синтаксисом bash (то есть ${SECRET_KEY}для вставки SECRET_KEYиз .envфайла).

Обратите внимание, что COMPOSE_CONFIGэто определено в моем .envфайле и используется в моем скрипте bash, но вы можете легко заменить {$COMPOSE_CONFIG}его my-compose-file.ymlв скрипте bash.

Также обратите внимание, что я пометил это развертывание, назвав все свои контейнеры префиксом «myproject». Вы можете использовать любое имя, которое хотите, но оно помогает идентифицировать ваши контейнеры, чтобы вы могли легко ссылаться на них позже. Предполагая, что ваши контейнеры не имеют состояния, как и должно быть, этот сценарий быстро удалит и повторно развернет ваши контейнеры в соответствии с параметрами вашего файла .env и файлом составления YAML.

Обновление Поскольку этот ответ кажется довольно популярным, я написал сообщение в блоге, в котором более подробно описывается мой рабочий процесс развертывания Docker: http://lukeswart.net/2016/03/lets-deploy-part-1/ Это может быть полезно при добавлении более сложная конфигурация развертывания, такая как конфиги nginx, сертификаты LetsEncrypt и связанные контейнеры.


2
Вы можете просто grep foo file.textвместо cat file.text | grep foo. В моем случае мне пришлось export $(grep "^[^#]" .config | xargs) && cat docker-compose.yml | envsubst.
Хорхе Лавин

«Я заметил, что у людей есть проблемы с поддержкой переменных среды Докера» - есть ли у вас какие-либо подробности или ссылка на тикет?
16:00

Извините, я не регистрировал конкретную проблему, с которой столкнулся, и это было так давно (~ 6 месяцев), я не знаю, актуальна ли она до сих пор. Но да, некоторые функции в поддержке переменных среды Docker были с ошибками, о чем сообщали несколько пользователей. Я считаю, что теперь намного лучше. Но когда конфигурация развертывания становится значительно более сложной, я бы предпочел ее модульно использовать, используя bash для обработки логики конфигурации и Docker Compose для оркестровки контейнера.
модуль

8
PSA: это работает только с,docker-compose up а не с docker-compose run.
Kriegslustig

5
Это решение docs.docker.com/compose/compose-file/#envfile, которое я использую для добавления переменных среды из- .envпод env_file. Затем вы можете ссылаться на переменные в docker-compose.ymlиспользовании${VARIABLE}
musale

112

Кажется, что docker-compose теперь имеет встроенную поддержку переменных среды по умолчанию в файле .

все, что вам нужно сделать, это объявить ваши переменные в файле с именем, .envи они будут доступны в docker-compose.yml.

Например, для .envфайла с содержимым:

MY_SECRET_KEY=SOME_SECRET
IMAGE_NAME=docker_image

Вы можете получить доступ к вашей переменной внутри docker-compose.ymlили переслать их в контейнер:

my-service:
  image: ${IMAGE_NAME}
  environment:
    MY_SECRET_KEY: ${MY_SECRET_KEY}

4
это лучшее решение!
Ладенков Владислав

4
Это сработало и для меня. Я не знаю почему, но имя файла должно быть буквально .env, например config.env, у меня не сработало.
HBat

1
@HBat "." означает скрытый файл - это обычная процедура для локальных конфигурационных файлов
Джереми Хайек

2
Лучшее решение и мы можем добавить реквизиты / etc / environment и использовать их как среду с использованием .env. Это будет более безопасно.
Чинтхака Динадаса

24

Следующее применимо для docker-compose 3.x Установка переменных среды внутри контейнера

метод - 1 прямой метод

web:
  environment:
    - DEBUG=1
      POSTGRES_PASSWORD: 'postgres'
      POSTGRES_USER: 'postgres'

Метод - 2 Файл «.env»

Создайте файл .env в том же месте, что и docker-compose.yml.

$ cat .env
TAG=v1.5
POSTGRES_PASSWORD: 'postgres'

и ваш составной файл будет как

$ cat docker-compose.yml
version: '3'
services:
  web:
    image: "webapp:${TAG}"
    postgres_password: "${POSTGRES_PASSWORD}"

источник


2
Я хотел бы увидеть полный пример метода 1. Я не мог сделать эту работу, поэтому в итоге использовал файл .env (который работал нормально).
BobHy

20

При использовании переменных среды для томов вам необходимо:

  1. создать файл .env в той же папке, в которой находится docker-compose.yaml файл

  2. объявить переменную в .envфайле:

    HOSTNAME=your_hostname
    
  3. Изменение $hostnameв ${HOSTNAME}в docker-compose.yaml файле

    proxy:
      hostname: ${HOSTNAME}
      volumes:
        - /mnt/data/logs/${HOSTNAME}:/logs
        - /mnt/data/${HOSTNAME}:/data
    

Конечно, вы можете сделать это динамически на каждой сборке, например:

echo "HOSTNAME=your_hostname" > .env && sudo docker-compose up

9
Обратите внимание, согласно документам:The .env file feature only works when you use the docker-compose up command and does not work with docker stack deploy.
Джеймс Гентес

19

Лучший способ - указать переменные окружения вне docker-compose.ymlфайла. Вы можете использовать env_fileнастройки и определить свой файл среды в той же строке. Затем повторное создание docker должно воссоздать контейнеры с новыми переменными среды.

Вот как выглядит мой docker-compose.yml:

services:
  web:
    env_file: variables.env

Примечание: docker-compose ожидает, что каждая строка в файле env будет в VAR=VALформате. Избегайте использования exportвнутри .envфайла. Также .envфайл следует поместить в папку, в которой выполняется команда docker-compose.


2
Лучший способ действительно
Дэни

NO. Он не будет автоматически делать переменные среды доступными внутри контейнера Docker. Вы все еще должны явно упомянуть об этом в разделе среды.
KTA

6

Вы не можете ... пока. Но это альтернатива, подумайте как генератор docker-composer.yml:

https://gist.github.com/Vad1mo/9ab63f28239515d4dafd

В основном сценарий оболочки, который заменит ваши переменные. Также вы можете использовать задачу Grunt для создания файла компоновки Docker в конце процесса CI.


4

У меня есть простой сценарий bash, который я создал для этого, это просто означает, что нужно запустить его в вашем файле перед использованием: https://github.com/antonosmond/subber

По сути, просто создайте свой файл compose, используя двойные фигурные скобки для обозначения переменных среды, например:

app:
    build: "{{APP_PATH}}"
ports:
    - "{{APP_PORT_MAP}}"

Все, что находится в двойных фигурных скобках, будет заменено переменной среды с тем же именем, поэтому, если бы у меня были установлены следующие переменные среды:

APP_PATH=~/my_app/build
APP_PORT_MAP=5000:5000

при запуске subber docker-compose.ymlполученный файл будет выглядеть так:

app:
    build: "~/my_app/build"
ports:
    - "5000:5000"

2

Насколько я знаю, это незавершенное производство. Они хотят сделать это, но это еще не выпущено. См. 1377 («новый» 495 , упомянутый @Andy).

В итоге я реализовал подход «генерировать .yml как часть CI», предложенный @Thomas.


1

добавить env в файл .env

Такие как

VERSION=1.0.0

затем сохраните его в deploy.sh

INPUTFILE=docker-compose.yml
RESULT_NAME=docker-compose.product.yml
NAME=test

prepare() {
        local inFile=$(pwd)/$INPUTFILE
        local outFile=$(pwd)/$RESULT_NAME
        cp $inFile $outFile
        while read -r line; do
            OLD_IFS="$IFS"
            IFS="="
            pair=($line)
            IFS="$OLD_IFS"
               sed -i -e "s/\${${pair[0]}}/${pair[1]}/g" $outFile
            done <.env
     }
       
deploy() {
        docker stack deploy -c $outFile $NAME
}

        
prepare
deploy
    

1

Используйте файл .env для определения динамических значений в docker-compse.yml. Будь то порт или любое другое значение.

Пример docker-compose:

testcore.web:
       image: xxxxxxxxxxxxxxx.dkr.ecr.ap-northeast-2.amazonaws.com/testcore:latest
       volumes: 
            - c:/logs:c:/logs
       ports:
            - ${TEST_CORE_PORT}:80
       environment:
            - CONSUL_URL=http://${CONSUL_IP}:8500 
            - HOST=${HOST_ADDRESS}:${TEST_CORE_PORT}

Внутри .env файла вы можете определить значение этих переменных:

CONSUL_IP=172.31.28.151
HOST_ADDRESS=172.31.16.221
TEST_CORE_PORT=10002

1
env SOME_VAR="I am some var" OTHER_VAR="I am other var" docker stack deploy -c docker-compose.yml

Используйте версию 3.6:

version: "3.6"
services:
  one:
    image: "nginx:alpine"
    environment:
      foo: "bar"
      SOME_VAR:
      baz: "${OTHER_VAR}"
    labels:
      some-label: "$SOME_VAR"
  two:
    image: "nginx:alpine"
    environment:
      hello: "world"
      world: "${SOME_VAR}"
    labels:
      some-label: "$OTHER_VAR"

Я получил это по этой ссылке https://github.com/docker/cli/issues/939


1

Начиная с версии 1.25.4, docker-compose поддерживает опцию, --env-fileкоторая позволяет вам указывать файл, содержащий переменные.

Ваш должен выглядеть так:

hostname=my-host-name

И команда:

docker-compose --env-file /path/to/my-env-file config
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.