¿Cómo puedo usar una variable dentro de una CMD de Dockerfile?

104

Dentro de mi Dockerfile:

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

Error:

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

¿Cuál es la solución más rápida aquí? ¿Tiene Docker algún plan para "arreglar" o introducir esta funcionalidad en versiones posteriores de Docker?

NOTA: Si elimino la línea CMD del archivo Docker y luego ejecuto el contenedor Docker, puedo ejecutar manualmente Django-admin startproject $ PROJECTNAME desde el interior del contenedor y creará el proyecto ...

david
fuente
1
¿Cómo y cuándo estás definiendo $PROJECTNAME?
Piotr Wittchen
Al comienzo de mi Dockerfile usando ENV. También olvidé mencionar que si elimino la línea CMD del Dockerfile y luego ejecuto el contenedor, desde dentro del contenedor puedo ejecutar este comando y creará el proyecto (lo que significa que la variable ENV es válida).
David
¿A qué tipo de variable se refiere: variable dockerfile o variable de entorno (como en el tiempo de ejecución de su sistema)?
emix

Respuestas:

164

Cuando usa una lista de ejecución, como en ...

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

... entonces Docker ejecutará el comando dado directamente , sin involucrar un shell. Dado que no hay shell involucrado, eso significa:

  • Sin expansión variable
  • Sin expansión con comodines
  • Sin i / o redirección con >, <,| , etc.
  • No hay varios comandos a través de command1; command2
  • Etcétera.

Si desea CMDexpandir las variables, debe organizar un shell. Puedes hacerlo así:

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

O puede usar una cadena simple en lugar de una lista de ejecución, lo que le da un resultado en gran parte idéntico al ejemplo anterior:

CMD django-admin startproject $PROJECTNAME
larsks
fuente
2
Más lectura en el rastreador de problemas de Docker: github.com/docker/docker/issues/5509
jannis
@larsks una cadena simple es INCREÍBLE
abdoutelb
¡Me has salvado el día!
Supratim Roy
18

Si desea utilizar el valor en tiempo de ejecución, establezca el ENVvalor en Dockerfile. Si desea usarlo en el momento de la compilación, debe usarARG .

Ejemplo:

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

Pase el valor en el comando de compilación:

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

Digamos que desea iniciar un proceso de Java dentro de un contenedor:

Ejemplo de extracto de Dockerfile:

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

Ejemplo de extracto de 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
fuente
0

Inspirado en lo anterior, hice esto:

#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
fuente