Как передать переменные среды в контейнеры Docker?

Я новичок в Docker, и неясно, как получить доступ к внешней базе данных из контейнера. Это лучший способ жестко запрограммировать строку подключения?

# Dockerfile
ENV DATABASE_URL amazon:rds/connection?string

person AJcodez    schedule 27.05.2015    source источник


Ответы (14)


Вы можете передавать переменные среды в ваши контейнеры с помощью флага -e.

Пример из сценария запуска:

sudo docker run -d -t -i -e REDIS_NAMESPACE='staging' \ 
-e POSTGRES_ENV_POSTGRES_PASSWORD='foo' \
-e POSTGRES_ENV_POSTGRES_USER='bar' \
-e POSTGRES_ENV_DB_NAME='mysite_staging' \
-e POSTGRES_PORT_5432_TCP_ADDR='docker-db-1.hidden.us-east-1.rds.amazonaws.com' \
-e SITE_URL='staging.mysite.com' \
-p 80:80 \
--link redis:redis \  
--name container_name dockerhub_id/image_name

Или, если вы не хотите, чтобы значение в командной строке, где оно будет отображаться ps и т. Д., -e может извлечь значение из текущей среды, если вы просто укажете его без =:

sudo PASSWORD='foo' docker run  [...] -e PASSWORD [...]

Если у вас много переменных среды и особенно если они должны быть секретными, вы можете использовать env-файл:

$ docker run --env-file ./env.list ubuntu bash

Флаг --env-file принимает имя файла в качестве аргумента и ожидает, что каждая строка будет в формате VAR = VAL, имитируя аргумент, переданный в --env. Строки комментариев должны иметь префикс #.

person errata    schedule 27.05.2015
comment
Есть ли более простой способ сделать это? Действительно раздражает необходимость каждый раз заново создавать контейнер с разными переменными. Может храниться в файле? - person Jason Axelson; 27.07.2016
comment
Я сохраняю команды запуска докера в сценариях оболочки (./start_staging.sh и т. Д.), А затем выполняю их удаленно с помощью Ansible. - person errata; 28.07.2016
comment
Мне не удается заставить вторую версию работать; Я устанавливаю PASSWORD = foo в среде, затем передаю --env PASSWORD, и только слово PASSWORD отображается в config.json контейнера; у каждой другой переменной среды есть ключ и значение. Я использую Docker 1.12.1. - person Kevin Burke; 20.09.2016
comment
@KevinBurke: Сделайте export PASSWORD=foo вместо этого, и переменная будет передана в docker run как переменная среды, заставляя docker run -e PASSWORD работать. - person qerub; 25.11.2016
comment
для ясности: -e в командной строке и ENV в Dockerfile делают одно и то же? - person Inderpartap Cheema; 07.10.2020
comment
Допустим, я использую .env файл и указываю env-файл в изображении nginx в docker-compose.yml. Все отлично работает. Как мне сделать этот .env доступным в рабочей среде каждый раз, когда новый Контейнер будет создаваться автоматически с Kubernetes без раскрытия моих секретных паролей и ключей? - person KeitelDOG; 17.12.2020
comment
Болезненно я узнал, что вы должны передавать все значения -e перед именем образа докера, иначе не возникнет ошибка и ни одна из переменных не будет иметь значения! - person Jalal; 16.02.2021
comment
Что такое флаг -d? - person Steffi Keran Rani J; 27.04.2021
comment
Флаг -d или --detached служит для запуска контейнера в фоновом режиме и печати идентификатора контейнера, как описано в выходных данных docker run --help. Более подробную информацию можно найти в соответствующей документации - person artu-hnrq; 22.06.2021

Вы можете передать параметры -e с помощью команды docker run .., как указано здесь и как указано @errata.

Однако возможный недостаток этого подхода заключается в том, что ваши учетные данные будут отображаться в списке процессов, в которых вы их запускаете.

Чтобы сделать его более безопасным, вы можете записать свои учетные данные в файл конфигурации и сделать docker run с --env-file, как указано здесь. Затем вы можете контролировать доступ к этому файлу конфигурации, чтобы другие пользователи, имеющие доступ к этому компьютеру, не видели ваши учетные данные.

person Sabin    schedule 27.05.2015
comment
Я добавил еще один способ решения этой проблемы в ответ @errata. - person Bryan; 29.05.2015
comment
Будьте осторожны с --env-file, когда вы используете --env, ваши значения env будут заключаться в кавычки / экранироваться со стандартной семантикой любой оболочки, которую вы используете, но при использовании --env-file значения, которые вы получите внутри вашего контейнера, будут другими. Команда docker run просто считывает файл, выполняет очень простой синтаксический анализ и передает значения в контейнер, это не эквивалентно тому, как ведет себя ваша оболочка. Небольшая ошибка, о которой следует помнить, если вы конвертируете несколько записей --env в --env-file. - person Shorn; 05.10.2016
comment
Чтобы уточнить ответ Шорна, при использовании файла env мне пришлось поместить очень длинное значение переменной среды в одну строку, поскольку, похоже, нет никакого способа поместить в нее разрыв строки или разделить ее на несколько строк, например: $ MY_VAR = stuff $ MY_VAR = $ MY_VAR еще материал - person Jason White; 18.11.2016

Если вы используете docker-compose в качестве метода раскрутки вашего контейнера (ов), на самом деле есть полезный способ передать переменную среды, определенную на вашем сервере, в контейнер Docker.

Допустим, в вашем docker-compose.yml файле вы запускаете базовый контейнер hapi-js, и код выглядит так:

hapi_server:
  container_name: hapi_server
  image: node_image
  expose:
    - "3000"

Предположим, что на локальном сервере, на котором находится ваш проект докера, есть переменная среды с именем «NODE_DB_CONNECT», которую вы хотите передать своему контейнеру hapi-js, и вы хотите, чтобы ее новое имя было «HAPI_DB_CONNECT». Затем в файле docker-compose.yml вы должны передать локальную переменную среды в контейнер и переименовать ее следующим образом:

hapi_server:
  container_name: hapi_server
  image: node_image
  environment:
    - HAPI_DB_CONNECT=${NODE_DB_CONNECT}
  expose:
    - "3000"

Надеюсь, это поможет вам избежать жесткого кодирования строки подключения к базе данных в любом файле в вашем контейнере!

person Marquistador    schedule 21.10.2016
comment
Это не сработает. Эти переменные не передаются в контейнер. - person Frondor; 11.05.2018
comment
@Frondor правда? Согласно этим документам, похоже, что и должно. - person darda; 05.05.2019
comment
Проблема с этим подходом заключается в том, что вы фиксируете переменные среды из файла docker-compose.yml в репозиторий git, чего делать не следует. Как это обойти? в идеале у вас должен быть отдельный файл env, который gitignored и может импортировать / загружать в Dockerfile или docker-compose.yml - person Khaled Osman; 26.09.2019

Используя docker-compose, вы можете наследовать переменные env в docker-compose.yml и, следовательно, в любых файлах Dockerfile, вызываемых docker-compose для создания образов. Это полезно, когда команда Dockerfile RUN должна выполнять команды, специфичные для среды.

(ваша оболочка RAILS_ENV=development уже существует в среде)

docker-compose.yml:

version: '3.1'
services:
  my-service: 
    build:
      #$RAILS_ENV is referencing the shell environment RAILS_ENV variable
      #and passing it to the Dockerfile ARG RAILS_ENV
      #the syntax below ensures that the RAILS_ENV arg will default to 
      #production if empty.
      #note that is dockerfile: is not specified it assumes file name: Dockerfile
      context: .
      args:
        - RAILS_ENV=${RAILS_ENV:-production}
    environment: 
      - RAILS_ENV=${RAILS_ENV:-production}

Dockerfile:

FROM ruby:2.3.4

#give ARG RAILS_ENV a default value = production
ARG RAILS_ENV=production

#assign the $RAILS_ENV arg to the RAILS_ENV ENV so that it can be accessed
#by the subsequent RUN call within the container
ENV RAILS_ENV $RAILS_ENV

#the subsequent RUN call accesses the RAILS_ENV ENV variable within the container
RUN if [ "$RAILS_ENV" = "production" ] ; then echo "production env"; else echo "non-production env: $RAILS_ENV"; fi

Таким образом, мне не нужно указывать переменные среды в файлах или docker-compose _9 _ / _ 10_ командах:

docker-compose build
docker-compose up
person joshweir    schedule 05.10.2017
comment
У них должно быть одно и то же имя? Это немного сбивает с толку ... И как мне переопределить аргументы, если я хочу вместо этого запустить разработку? - person CyberMew; 14.06.2018
comment
@CyberMew Да, они должны быть одинаковыми для вашей среды, docker-compose и Dockerfile. Если вы хотите вместо этого запустить разработку, перед запуском сборки docker-compose запустите RAILS_ENV = development в своем терминале, чтобы установить переменную среды, таким образом docker-compose, и, в свою очередь, Dockerfile унаследует это значение из вашей среды. - person joshweir; 14.06.2018

Используйте значение -e или --env для установки переменных среды (по умолчанию []).

Пример из сценария запуска:

 docker run  -e myhost='localhost' -it busybox sh

Если вы хотите использовать несколько сред из командной строки, перед каждой переменной среды используйте флаг -e.

Пример:

 sudo docker run -d -t -i -e NAMESPACE='staging' -e PASSWORD='foo' busybox sh

Примечание. Убедитесь, что имя контейнера указано после переменной среды, а не до нее.

Если вам нужно установить много переменных, используйте флаг --env-file

Например,

 $ docker run --env-file ./my_env ubuntu bash

Для получения любой другой помощи загляните в справку Docker:

 $ docker run --help

Официальная документация: https://docs.docker.com/compose/environment-variables/

person Vishnu Mishra    schedule 29.01.2017
comment
Зачем нам ubuntu bash? Применимо ли это к изображениям, созданным с помощью ubuntu в качестве базового образа или ко всем изображениям? - person Reyansh Kharga; 12.10.2019
comment
@ReyanshKharga ubuntu - это имя изображения, а bash - это команда, которую вы выполняете. bash дает вам терминал (хотя я думаю, что он вам нужен для интерактивного терминала). - person Brandon; 23.09.2020

Есть хороший прием, как передать переменные среды хост-машины в контейнер докеров:

env > env_file && docker run --env-file env_file image_name

Используйте эту технику очень осторожно, потому что env > env_file сбросит ВСЕ переменные ENV хост-машины в env_file и сделает их доступными в работающем контейнере.

person Alex T    schedule 22.11.2018

Другой способ - использовать возможности /usr/bin/env:

docker run ubuntu env DEBUG=1 path/to/script.sh
person sanmai    schedule 17.04.2018

Проблема заключалась в том, что я помещал --env-файл в конец команды

docker run -it --rm -p 8080:80 imagename --env-file ./env.list

Исправить

docker run --env-file ./env.list -it --rm -p 8080:80 imagename
person T Brown    schedule 01.10.2020
comment
Я сделал эту глупую ошибку. Спасибо @T Brown. - person Paresh Dudhat; 09.05.2021

Для Amazon AWS ECS / ECR вам следует управлять переменными среды (особенно секретами) через частную корзину S3. См. Сообщение в блоге Как управлять секретами для приложений на основе контейнерных сервисов Amazon EC2 с помощью Amazon S3 и Docker.

person Joseph Juhnke    schedule 27.03.2017
comment
Или хранилище параметров SSM - person joshweir; 10.07.2019

Мы также можем использовать переменную среды хост-машины, используя флаг -e и $:

Перед запуском следующей команды необходимо экспортировать (означает установить) локальные переменные env.

docker run -it -e MG_HOST=$MG_HOST -e MG_USER=$MG_USER -e MG_PASS=$MG_PASS -e MG_AUTH=$MG_AUTH -e MG_DB=$MG_DB -t image_tag_name_and_version 

Используя этот метод, вы можете автоматически установить переменную среды с вашим именем. В моем случае (MG_HOST, MG_USER)

Кроме того:

Если вы используете python, вы можете получить доступ к этой переменной среды внутри докера с помощью

import os
host,username,password,auth,database=os.environ.get('MG_HOST'),os.environ.get('MG_USER'),os.environ.get('MG_PASS'),os.environ.get('MG_AUTH'),os.environ.get('MG_DB')
person Mobin Al Hassan    schedule 25.02.2020

Если у вас есть переменные среды в env.sh локально и вы хотите настроить их при запуске контейнера, вы можете попробовать

COPY env.sh /env.sh
COPY <filename>.jar /<filename>.jar
ENTRYPOINT ["/bin/bash" , "-c", "source /env.sh && printenv && java -jar /<filename>.jar"]

Эта команда запускает контейнер с оболочкой bash (мне нужна оболочка bash, поскольку source - это команда bash), создает файл env.sh (который устанавливает переменные среды) и выполняет файл jar.

env.sh выглядит так,

#!/bin/bash
export FOO="BAR"
export DB_NAME="DATABASE_NAME"

Я добавил команду printenv только для того, чтобы проверить, работает ли фактическая исходная команда. Вам, вероятно, следует удалить его, когда вы убедитесь, что исходная команда работает нормально или переменные среды появятся в ваших журналах докеров.

person akilesh raj    schedule 23.03.2018
comment
при таком подходе вам придется перестраивать образ докера каждый раз, когда вы хотите передать другой / измененный набор env. Передача envs во время docker --run --env-file ./somefile.txt - превосходный / динамический подход. - person Dmitry Shevkoplyas; 23.03.2018
comment
@DmitryShevkoplyas Согласен. В моем случае нет возможности указать --env-file arg для команды docker run. Например, если вы развертываете приложение с помощью движка приложений Google, а приложению, работающему внутри контейнера, требуются переменные среды, установленные внутри контейнера докеров, у вас нет прямого подхода к установке переменных среды, поскольку вы не контролируете docker run команда. В таком случае у вас может быть сценарий, который расшифровывает переменные env с помощью, скажем, KMS, и добавляет их в env.sh, который можно использовать для установки переменных env. - person akilesh raj; 25.03.2018
comment
вы можете использовать команду POSIX . (точка), доступную в обычном sh вместо source. (source совпадает с .) - person go2null; 24.03.2019
comment
Имейте в виду, что сигналы не дойдут до вашего исполняемого файла, если вы заключите вызов в команду оболочки. По сути, вы не сможете прервать свой процесс без лишнего bash fu. - person David Weber; 20.02.2021

Использование jq для преобразования env в JSON:

env_as_json=`jq -c -n env`
docker run -e HOST_ENV="$env_as_json" <image>

для этого требуется jq версии 1.6 или новее

это вытесняет env хоста как json, по сути, как в Dockerfile:

ENV HOST_ENV  (all env from the host as json)
person Alexander Mills    schedule 22.05.2019
comment
Как эта линия работает на вас ?: docker run -e HOST_ENV="$env_as_json" <image>? В моем случае Docker, похоже, не разрешает переменные или подоболочки (${} или $()) при передаче в качестве аргументов докера. Например: A=123 docker run --rm -it -e HE="$A" ubuntu, затем внутри этого контейнера: root@947c89c79397:/# echo $HE root@947c89c79397:/# .... Переменная HE этого не делает. - person Perplexabot; 20.02.2020

docker run --rm -it --env-file <(bash -c 'env | grep <your env data>') Это способ поиска данных, хранящихся в .env, и их передачи в Docker без небезопасного хранения (так что вы не можете просто посмотреть docker history и получить ключи.

Скажем, у вас в .env загружено множество материалов AWS, например:

AWS_ACCESS_KEY: xxxxxxx
AWS_SECRET: xxxxxx
AWS_REGION: xxxxxx

запуск докера с командой `` docker run --rm -it --env-file ‹(bash -c 'env | grep AWS_') захватит все это и безопасно передаст для доступа изнутри контейнера.

person MadDanWithABox    schedule 22.05.2020

вот как я смог это решить

docker run --rm -ti -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_SESSION_TOKEN -e AWS_SECURITY_TOKEN amazon/aws-cli s3 ls

еще один пример:

export VAR1=value1
export VAR2=value2

$ docker run --env VAR1 --env VAR2 ubuntu env | grep VAR
VAR1=value1
VAR2=value2
person EDU_EVER    schedule 10.06.2020