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

90

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

ENV MY_VAR whoami

je veux que MY_VAR obtienne la valeur "root" ou tout ce que whoami renvoie

Sultanen
la source

Réponses:

23

En complément de la réponse DarkSideF.

Vous devez être conscient que chaque ligne / commande dans Dockerfile est exécutée dans un autre conteneur.

Vous pouvez faire quelque chose comme ceci:

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

Ceci est exécuté dans un seul conteneur.

Dimitrie Mititelu
la source
14
Juste pour préciser - $bleahest pas disponible partout en dehors de cette commande RUN, même pas sur la ligne suivante dans la même dockerfile, et encore moins dans une autre image , il est basé au large. Fonctionnalité manquante vraiment évidente de docker ici, il semble que l'écriture et la lecture d'un fichier soient le seul moyen de stocker des variables (dynamiques) dans des images et de les passer entre les images, ce qui semble super hacky.
davnicwil
17

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

Par exemple, je dois définir SECRET_KEY_BASE pour l'application Rails une seule fois sans changer comme le ferait lorsque je lance:

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 d'environnement 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'

puis 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 lui.

Vous pouvez également essayer différentes méthodes pour définir la variable d'environnement.

DarkSideF
la source
/Etc/profile.d/docker_init.sh est-il toujours une chose? Cette réponse est la seule mention que je puisse trouver avec Google, et cela ne fonctionne pas pour moi. Faisait-il peut-être partie d'un moteur d'exécution Docker en 2016 qui n'est plus actuel?
SigmaX
1
@SigmaX Ce n'est pas un truc de docker, c'est plus un truc Linux . Tout *.shfichier à l'intérieur /etc/profile.d/est utilisé pour peupler l'environnement
Madacol
7

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

La méthode qu'il propose est la suivante, en 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 docker, par exemple une application Node.js, /etc/bash.bashrcsera complètement ignorée et votre application n'aura pas un seul indice de ce SECRET_KEY_BASEque vous essayez pour accéder process.env.SECRET_KEY_BASE.

C'est la raison pour laquelle le ENVmot clé est ce que tout le monde essaie d'utiliser avec une commande dynamique, car chaque fois que vous exécutez votre conteneur ou utilisez unexec commande, Docker vérifiera ENVet canalisera chaque valeur du processus en cours d'exécution (similaire à -e).

Une solution consiste à utiliser un wrapper (crédit à @duglin dans ce problème github ). Avoir un fichier wrapper (par exempleenvwrapper ) dans la racine de votre 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
vdegenne
la source
2

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

  1. exécuter une commande, stocker le résultat dans un fichier
  2. utiliser 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 également utiliser l' essentiel 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 la bibliothèque python-dotenv qui a une CLI similaire.

sebpiq
la source
2

Je ne sais pas si c'est ce que vous recherchiez, mais pour injecter des variables ENV ou ARGS dans votre .Dockerfile, construisez ce modèle fonctionne.

dans votre my_build.sh:

echo getting version of osbase image to build from
OSBASE=$(grep "osbase_version" .version | sed 's/^.*: //')

echo building docker
docker build -f \
--build-arg ARTIFACT_TAG=$OSBASE \
PATH_TO_MY.Dockerfile \
-t my_artifact_home_url/bucketname:$TAG .

pour obtenir un ARG dans votre .Dockerfile, l'extrait de code pourrait ressembler à ceci:

FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}

ou pour obtenir un ENV dans votre fichier .Docker, l'extrait de code pourrait ressembler à ceci:

FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}

l'idée est que vous exécutez le script shell et qui appelle le .Dockerfile avec les arguments passés en tant qu'options sur la construction.

kat
la source