Obtenir la valeur de la variable d'environnement dans Dockerfile

254

Je construis un conteneur pour une application ruby. La configuration de mon application est contenue dans des variables d'environnement (chargées à l'intérieur de l'application avec dotenv ).

L'une de ces variables de configuration est l'adresse IP publique de l'application, qui est utilisée en interne pour créer des liens. J'ai besoin d'ajouter une entrée dnsmasq pointant cette adresse IP vers 127.0.0.1 à l'intérieur du conteneur, afin qu'elle puisse récupérer les liens de l'application comme si elle n'était pas conteneurisée.

J'essaie donc de définir un ENVdans mon Dockerfile qui transmettrait une variable d'environnement au conteneur.

J'ai essayé quelques trucs.

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`

Tout passe cependant la chaîne "REQUEST_DOMAIN" au lieu de la valeur de la variable d'environnement. Existe-t-il un moyen de transmettre des valeurs de variables d'environnement de la machine hôte au conteneur?

Damien MATHIEU
la source

Réponses:

392

Vous devez utiliser la ARGdirective dans votre Dockerfile qui est destinée à cet effet.

L' ARGinstruction définit une variable que les utilisateurs peuvent transmettre au moment de la construction au générateur avec la commande docker build en utilisant l' --build-arg <varname>=<value>indicateur.

Votre Dockerfile aura donc cette ligne:

ARG request_domain

ou si vous préférez une valeur par défaut:

ARG request_domain=127.0.0.1

Vous pouvez maintenant référencer cette variable dans votre Dockerfile:

ENV request_domain=$request_domain

alors vous construirez votre conteneur comme ceci:

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


Remarque 1: votre image ne sera pas ARGcréée si vous avez référencé un dans votre Dockerfile mais que vous l'avez exclu --build-arg.

Remarque 2: si un utilisateur spécifie un argument de génération qui n'a pas été défini dans le Dockerfile, la génération génère un avertissement:

[Avertissement] Un ou plusieurs arguments de build [foo] n'ont pas été consommés.

Daniel van Flymen
la source
12
ARG est disponible à partir de Docker v1.9.
Synesso
est-il pris en charge pour être construit à distance sur le dépôt Docker?
James Lin
4
Your image will not build if you have referenced an ARG in your Dockerfile but excluded it in --build-argVous avez tort. Vous pouvez créer une image avec des références même sans --build-arg. De plus, vous pouvez définir la valeur par défaut pour l'argument de génération.
ALex_hha
1
À quoi sert la ligne ENV? Pour moi --build-arg + ARG était suffisant.
Phil
3
L'ARG définit une variable à utiliser dans le dockerfile dans les commandes suivantes. L'ENV définit une variable d'environnement qui est transmise au conteneur.
herm
56

Vous pouvez donc faire: cat Dockerfile | envsubst | docker build -t my-target -

Ensuite, ayez un Dockerfile avec quelque chose comme:

ENV MY_ENV_VAR $MY_ENV_VAR

Je suppose qu'il pourrait y avoir un problème avec certains caractères spéciaux, mais cela fonctionne au moins dans la plupart des cas.

jonasfj
la source
13
Cela ne semble pas fonctionner si vous devez AJOUTER des fichiers à partir du répertoire contenant le Dockerfile.
Tom Hennen
2
Très belle solution! Sur un Mac, vous pouvez en faire envsubstpartie brew install gettext. Mais à cause des conflits possibles avec le système de construction BSD, il est "uniquement en fût" et aucun symlnks n'est fait. Cependant, il est prudent d' ln -s /usr/local/Cellar/gettext/*/bin/envsubst /usr/local/bin/ajouter cette commande à votre PATH. (Ce sont vraiment les bibliothèques qui sont la préoccupation.) Ou vous pouvez l'utiliser à son /usr/local/Cellar/gettext/*/bin/envsubstemplacement
Bruno Bronosky
1
Pour clarifier le commentaire de @ TomHennen, diriger le Dockerfile vers docker build -, en particulier, ce qui ne fonctionne pas lorsque vous référencez des chemins relatifs à partir de votre Dockerfile, indépendamment de la substitution env var.
superEb
4
Re @ commentaire de TomHennen, si vous ne voulez utiliser les commandes dépendant du contexte comme copie dans votre Dockerfile vous pouvez toujours rediriger la sortie de envsubst dans un fichier temporaire, puis alimenter que dans la docker buildplace. Exemple:, cat Dockerfile | envsubst > DockerfileWithEnvVarsalors docker build -t my-target -f DockerfileWithEnvVars ., alorsrm DockerfileWithEnvVars
snark
Ou vous pouvez utiliser une éponge du paquet envsubst < Dockerfile | sponge Dockerfile
moreutils
19

Une alternative utilisant envsubstsans perdre la possibilité d'utiliser des commandes comme COPYou ADD, et sans utiliser de fichiers intermédiaires serait d'utiliser la substitution de processus de Bash :

docker build -f <(envsubst < Dockerfile) -t my-target .
L. Alberto Giménez
la source
3
malheureusement cela ne semble pas fonctionner (Docker 17.09), je reçois l'erreurunable to prepare context: the Dockerfile (/dev/fd/63) must be within the build context
Alexander Klimetschek
11

Chargez les variables d'environnement à partir d'un fichier que vous créez lors de l'exécution.

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

... puis dans le Dockerfile

ADD build /build
RUN /build/test.sh

où test.sh charge MYVAR depuis env.sh

#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile
Dan C
la source
4

Si vous souhaitez simplement rechercher et remplacer toutes les variables d'environnement ($ ExampleEnvVar) dans un Dockerfile, puis créez-le, cela fonctionnerait:

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

snassr
la source
La meilleure réponse ici, et sur cette base, a pu faire: envsubst < ./Dockerfile | docker build -squash -t ${DOCKIMG}:${VERSION} . -f -où la FROMligne utilise la variable d'environnement.
mikequentel
-6

ajouter une -eclé pour passer des variables d'environnement au conteneur. exemple:

$ 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
Valentin Kantor
la source
6
Damien cherche à construire une image. -e fonctionne à la place avec la commande run.
Andres Restrepo