Отримайте значення змінної середовища в Dockerfile


254

Я будую контейнер для додатка з рубіном. Конфігурація мого додатка міститься в змінних оточення (завантажується всередині програми за допомогою dotenv ).

Однією з цих змінних конфігурації є загальнодоступний ip програми, який використовується внутрішньо для створення посилань. Мені потрібно додати запис dnsmasq, що вказує цей ip на 127.0.0.1 всередині контейнера, щоб він міг отримати посилання програми, як ніби він не був контейнером.

Тому я намагаюся встановити ENVв своєму Dockerfile, який би передав змінну середовища в контейнер.

Я спробував кілька речей.

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`

Все передає рядок "REQUEST_DOMAIN" замість значення змінної середовища. Чи є спосіб передати значення змінних оточення з хост-машини в контейнер?

Відповіді:


392

Ви повинні використовувати ARGдирективу у своєму Dockerfile, який призначений для цієї мети.

ARGІнструкція визначає змінну , що користувачі можуть проходити при побудові часу будівельника з командою докер збірки , використовуючи --build-arg <varname>=<value>прапор.

Отже, ваш Dockerfile матиме такий рядок:

ARG request_domain

або якщо ви бажаєте значення за замовчуванням:

ARG request_domain=127.0.0.1

Тепер ви можете посилатися на цю змінну у вашому Dockerfile:

ENV request_domain=$request_domain

тоді ви складете свій контейнер так:

$ docker build --build-arg request_domain=mydomain Dockerfile


Примітка 1: Ваше зображення не створюватиметься, якщо ви посилаєтесь на ARGсвій Dockerfile, але виключали його --build-arg.

Примітка 2: Якщо користувач вказує аргумент збірки, який не був визначений в Dockerfile, збірка видає попередження:

[Попередження] Один або декілька збірок [foo] не використовувались.


12
ARG доступний від docker v1.9 і далі.
Синесо

це підтримується, щоб будуватися віддалено на docker repo?
Джеймс Лін

4
Your image will not build if you have referenced an ARG in your Dockerfile but excluded it in --build-argви неправі. Ви можете створювати зображення з посиланнями навіть без --build-arg. Крім того, ви можете встановити значення за замовчуванням для arg збірки.
ALex_hha

1
Яке призначення лінії ENV? Для мене --build-arg + ARG вистачило.
Філ

3
ARG визначає змінну, яка буде використовуватися всередині dockerfile у наступних командах. ENV визначає змінну середовища, яка передається контейнеру.
герм

56

Отже, ви можете зробити: cat Dockerfile | envsubst | docker build -t my-target -

Потім мати Dockerfile з чимось на зразок:

ENV MY_ENV_VAR $MY_ENV_VAR

Я думаю, може виникнути проблема з деякими спеціальними символами, але це працює принаймні для більшості випадків.


13
Здається, це не працює, якщо вам потрібно додати файли з каталогу, що містить Dockerfile.
Том Хеннен

2
Дуже приємне рішення! На Mac можна отримати envsubstчастину brew install gettext. Але через можливі конфлікти із системою побудови BSD вона є "лише бочкою" і жодних символів не робиться. Однак це безпечно зробити, ln -s /usr/local/Cellar/gettext/*/bin/envsubst /usr/local/bin/щоб додати цю команду до вашої PATH. (Справді, це хвилювання /usr/local/Cellar/gettext/*/bin/envsubst
губ

1
Для уточнення коментаря @ TomHennen, трубопровід Dockerfile - docker build -це, зокрема, те, що не працює, коли ви посилаєтесь на відносні шляхи від Dockerfile, незалежно від заміни env var.
superEb

4
Re @ коментар TomHennen, в, якщо ви дійсно хочете використовувати контекстно-залежні команди , як COPY в вашому Dockerfile ви завжди можете перенаправити висновок envsubst в тимчасовий файл , а потім годувати , що в docker buildзамість цього. Приклад:, cat Dockerfile | envsubst > DockerfileWithEnvVarsто docker build -t my-target -f DockerfileWithEnvVars ., тодіrm DockerfileWithEnvVars
snark

Або ви можете використовувати губку з пакету envsubst < Dockerfile | sponge Dockerfile
moreutils

19

Альтернативою, що envsubstне втрачає можливості використовувати команди типу, COPYабо ADD, і без використання проміжних файлів, буде використання заміни процесу Баша :

docker build -f <(envsubst < Dockerfile) -t my-target .

3
на жаль, це, здається, не працює (Докер 17.09), я отримую помилкуunable to prepare context: the Dockerfile (/dev/fd/63) must be within the build context
Олександр Климечек

11

Завантажте змінні середовища з файлу, створеного під час виконання.

export MYVAR="my_var_outside"
cat > build/env.sh <<EOF
MYVAR=${MYVAR}
EOF

... потім у Dockerfile

ADD build /build
RUN /build/test.sh

де test.sh завантажує MYVAR з env.sh

#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile

4

Якщо ви просто хочете знайти та замінити всі змінні середовища ($ ExampleEnvVar) у Dockerfile, то побудуйте це, це спрацює:

envsubst < /path/to/Dockerfile | docker build -t myDockerImage . -f -


Найкраща відповідь тут, і виходячи з цього, змогла зробити: envsubst < ./Dockerfile | docker build -squash -t ${DOCKIMG}:${VERSION} . -f -де FROMрядок використовує змінну середовища.
mikequentel

-6

Додати -eключ для передачі змінних середовища в контейнер. приклад:

$ MYSQLHOSTIP=$(sudo docker inspect -format="{{ .NetworkSettings.IPAddress }}" $MYSQL_CONRAINER_ID)
$ sudo docker run -e DBIP=$MYSQLHOSTIP -i -t myimage /bin/bash

root@87f235949a13:/# echo $DBIP
172.17.0.2

6
Демієн шукає побудувати образ. -e замість цього працює з командою run.
Андрес Рестрепо
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.