web-dev-qa-db-fra.com

Dockerfile - définit ENV sur le résultat de la commande

Est-il possible de définir une variable ENV de docker sur le résultat d'une commande? Comme:

ENV MY_VAR whoami

je veux que MY_VAR obtienne la valeur "root" ou quoi que ce soit qui retourne

41
Sultanen

En complément de DarkSideF answer.

Vous devez savoir que chaque ligne/commande de Dockerfile est exécutée dans un autre conteneur.

Vous pouvez faire quelque chose comme ça:

RUN export bleah=$(hostname -f);echo $bleah;

Ceci est exécuté dans un seul conteneur.

12
Dimitrie Mititelu

J'ai eu le même problème et j'ai trouvé le moyen de définir la variable d'environnement comme résultat de la fonction en utilisant la commande RUN dans dockerfile.

Par exemple, je dois définir l'application SECRET_KEY_BASE pour Rails une seule fois sans changer, comme cela aurait été le cas lors de l'exécution:

docker run  -e SECRET_KEY_BASE="$(openssl Rand -hex 64)"

Au lieu de cela, j'écris dans la chaîne Dockerfile comme:

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl Rand -hex 64)" >> /etc/bash.bashrc'

et ma variable env disponible à partir de la racine, même après la connexion bash ..__ ou peut-être

RUN /bin/bash -l -c 'echo export SECRET_KEY_BASE="$(openssl Rand -hex 64)" > /etc/profile.d/docker_init.sh'

alors variable disponible dans les commandes CMD et ENTRYPOINT

Docker le cache en tant que couche et ne change que si vous modifiez certaines chaînes avant.

Vous pouvez également essayer différentes manières pour définir la variable d'environnement.

9
DarkSideF

À ce stade, un résultat de commande peut être utilisé avec RUN export, mais ne peut pas être affecté à une variable ENV

Problème connu: https://github.com/docker/docker/issues/29110

7
Kur00Hazama

Cette réponse est une réponse à @DarkSideF,

La méthode proposée est la suivante, dans Dockerfile:

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl Rand -hex 64)" >> /etc/bash.bashrc'

(ajout d'une exportation dans le /etc/bash.bashrc)

C'est bien, mais la variable d'environnement ne sera disponible que pour le processus /bin/bash, et si vous essayez d'exécuter votre application de menu fixe, par exemple une application Node.js, /etc/bash.bashrc sera complètement ignoré et votre application n'aura pas la moindre idée de ce que SECRET_KEY_BASE est en essayant d'accéder à process.env.SECRET_KEY_BASE.

C’est la raison pour laquelle le mot clé ENV correspond à ce que tout le monde essaie d’utiliser avec une commande dynamique car chaque fois que vous exécutez votre conteneur ou utilisez une commande exec, Docker vérifie ENV et redirige toutes les valeurs du processus en cours d’exécution (similaire à -e).

Une solution consiste à utiliser un wrapper (crédit de @ duglin dans ce problème github ) . Avoir un fichier wrapper (par exemple envwrapper) dans la racine du projet contenant:

#!/bin/bash
export SECRET_KEY_BASE="$(openssl Rand -hex 64)"
export ANOTHER_ENV "hello world"
$*

puis dans votre Dockerfile:

...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp
3
vdegenne

En complément de la réponse de @ DarkSideF, si vous souhaitez réutiliser le résultat d'une commande précédente dans votre Dockerfilependant le processus de construction, vous pouvez utiliser la solution de contournement suivante:

  1. lancer une commande, stocker le résultat dans un fichier
  2. utilisez la substitution de commande pour obtenir le résultat précédent de ce fichier dans une autre commande

Par exemple :

RUN echo "bla" > ./result
RUN echo $(cat ./result)

Pour quelque chose de plus propre, vous pouvez aussi utiliser le Gist suivant qui fournit une petite CLI appelée envstore.py:

RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)

Ou vous pouvez utiliser python-dotenv library qui a une CLI similaire.

0
sebpiq