Como posso usar uma variável dentro de um CMD Dockerfile?

102

Dentro do meu Dockerfile:

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

Erro:

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

Qual é a solução mais rápida aqui? O Docker tem algum plano para "consertar" ou introduzir essa funcionalidade em versões posteriores do Docker?

NOTA: Se eu remover a linha CMD do arquivo Docker e, em seguida, executar o contêiner do Docker, poderei executar manualmente o Django-admin startproject $ PROJECTNAME de dentro do contêiner e ele criará o projeto ...

david
fonte
1
Como e quando você está definindo $PROJECTNAME?
Piotr Wittchen
No início do meu Dockerfile usando ENV. Também esqueci de mencionar que se eu remover a linha CMD do Dockerfile e depois executar o contêiner, de dentro do contêiner eu posso executar este comando e ele criará o projeto (o que significa que a variável ENV é válida).
David
Que tipo de variável você quer dizer: variável dockerfile ou variável ambiental (como no tempo de execução do sistema)?
emix

Respostas:

160

Quando você usa uma lista de execução, como em ...

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

... então o Docker executará o comando fornecido diretamente , sem envolver um shell. Como não há shell envolvido, isso significa:

  • Sem expansão variável
  • Sem expansão curinga
  • Não i / o redirecionamento com >, <, |, etc
  • Sem comandos múltiplos via command1; command2
  • E assim por diante.

Se você deseja CMDexpandir as variáveis, é necessário providenciar um shell. Você pode fazer isso assim:

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

Ou você pode usar uma string simples em vez de uma lista de execução, o que fornece um resultado praticamente idêntico ao do exemplo anterior:

CMD django-admin startproject $PROJECTNAME
larsks
fonte
2
Um pouco mais de leitura no rastreador de problemas do Docker: github.com/docker/docker/issues/5509
jannis
@larsks uma string simples é INCRÍVEL
abdoutelb
Você salvou meu dia!
Supratim Roy
18

Se você deseja usar o valor no tempo de execução, defina o ENVvalor no Dockerfile. Se você quiser usá-lo em tempo de construção, você deve usar ARG.

Exemplo:

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

Passe o valor no comando build:

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

Digamos que você queira iniciar um processo java dentro de um contêiner:

Exemplo de trecho do Dockerfile:

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

Exemplo de trecho 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
fonte
0

Inspirado acima, fiz o seguinte:

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