Comment puis-je utiliser une variable dans un CMD Dockerfile?

104

Dans mon Dockerfile:

ENV PROJECTNAME mytestwebsite
CMD ["django-admin", "startproject", "$PROJECTNAME"]

Erreur:

CommandError: '$PROJECTNAME' is not a valid project name

Quelle est la solution de contournement la plus rapide ici? Docker a-t-il prévu de «réparer» ou d'introduire cette fonctionnalité dans les versions ultérieures de Docker?

REMARQUE: Si je supprime la ligne CMD du fichier Docker puis exécute le conteneur Docker, je suis en mesure d'exécuter manuellement Django-admin startproject $ PROJECTNAME depuis l'intérieur du conteneur et il créera le projet ...

David
la source
1
Comment et quand définissez-vous $PROJECTNAME?
Piotr Wittchen
Au début de mon Dockerfile en utilisant ENV. J'ai également oublié de mentionner que si je supprime la ligne CMD du Dockerfile puis exécute le conteneur, depuis l'intérieur du conteneur, je peux exécuter cette commande et cela créera le projet (ce qui signifie que la variable ENV est valide).
david
Quel type de variable voulez-vous dire: variable dockerfile ou variable d'environnement (comme dans votre système d'exécution)?
emix

Réponses:

163

Lorsque vous utilisez une liste d'exécution, comme dans ...

CMD ["django-admin", "startproject", "$PROJECTNAME"]

... alors Docker exécutera la commande donnée directement , sans impliquer un shell. Puisqu'il n'y a pas de shell impliqué, cela signifie:

  • Pas d'expansion variable
  • Aucune extension générique
  • Non i / o redirection avec >, <, |, etc.
  • Pas de commandes multiples via command1; command2
  • Et ainsi de suite.

Si vous voulez que vous CMDdéveloppiez des variables, vous devez organiser un shell. Vous pouvez le faire comme ceci:

CMD ["sh", "-c", "django-admin startproject $PROJECTNAME"]

Ou vous pouvez utiliser une simple chaîne au lieu d'une liste d'exécution, ce qui vous donne un résultat largement identique à l'exemple précédent:

CMD django-admin startproject $PROJECTNAME
larsks
la source
2
Quelques lectures supplémentaires dans le suivi des problèmes de Docker: github.com/docker/docker/issues/5509
jannis
@larsks une chaîne simple est incroyable
abdoutelb
Vous avez sauvé ma journée!
Supratim Roy
18

Si vous souhaitez utiliser la valeur au moment de l'exécution, définissez la ENVvaleur dans le Dockerfile. Si vous souhaitez l'utiliser au moment de la construction, vous devez utiliser ARG.

Exemple :

ARG value
ENV envValue=$value
CMD ["sh", "-c", "java -jar ${envValue}.jar"]

Passez la valeur dans la commande build:

docker build -t tagName --build-arg value="jarName"
rex roy
la source
10

Disons que vous souhaitez démarrer un processus java dans un conteneur:

Exemple d'extrait Dockerfile:

ENV JAVA_OPTS -XX +UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm 
... 
ENTRYPOINT ["/sbin/tini", "--", "entrypoint.sh"] 
CMD ["java", "${JAVA_OPTS}", "-myargument=true"]

Exemple d'extrait entrypoint.sh:

#!/bin/sh 
... 
echo "*** Startup $0 suceeded now starting service using eval to expand CMD variables ***"
exec su-exec mytechuser $(eval echo "$@")
Flavio Aiello
la source
0

Inspiré ci-dessus, j'ai fait ceci:

#snapshot by default. 1 is release.
ENV isTagAndRelease=0

CMD     echo is_tag: ${isTagAndRelease} && \
        if [ ${isTagAndRelease} -eq 1 ]; then echo "release build"; mvn -B release:clean release:prepare release:perform; fi && \
        if [ ${isTagAndRelease} -ne 1 ]; then echo "snapshot build"; mvn clean install; fi && \ 
       .....
csomakk
la source