Dockerfile if else condição com argumentos externos
Eu tenho dockerfile
então eu construo
e execute-o.
É possível passar argumentos da linha de comando e usá-los com if no Dockerfile? Quero dizer algo como
e construa com este argumento.
— nick_gabpe
Isso provavelmente deve ser tratado a partir de um script de construção.
— Snps de
@ Зелёный isso está incorreto. Veja a resposta abaixo, isso pode ser feito com --build-arg
A resposta aceita não cobre a parte da pergunta "se outra condição". Seria melhor renomeá-lo para "Dockerfile com argumentos externos" se a verificação de condição não pretendesse ser um requisito.
— Ruslan Kabalin
@RuslanKabalin - a resposta aceita contém as cláusulas "then" e "else". A única diferença é o que é testado em "condição se". Para código mostrado em questão: RUN if [ "$arg" == "42" ]; then ENV=TRUE; else ENV=FALSE; fi. Ou se arg estiver faltando: RUN if [ "x$arg" == "x42" ]; then ...
Pode não parecer tão limpo, mas você pode ter seu Dockerfile (condicional) da seguinte maneira:
e construir a imagem como:
— Qasim Sarfraz
Não deveria ser em [ "$arg" = "x" ]vez de [ "x$arg" = "x" ]?
— Quannt
O ternário aqui é verificar se algum argumento é fornecido, em vez de verificar um argumento específico. Pareceria mais óbvio se reescrito como, if [ $arg != "" ] ;mas tenho certeza de que há algum problema com o qual não estou familiarizado
if [[ -n "$arg" ]]verdadeiro se um parâmetro não estiver vazio, if [[ -z "$arg" ]]verdadeiro se um parâmetro estiver vazio
— acumartini
Como escrever uma declaração if multilinha?
— Ashutosh Chamoli
@Quannt - não, consulte Por que scripts de shell ... [ "x$arg" = "x" ] parece que está comparando duas strings entre aspas, mas as aspas são removidas; Isso mantém a sintaxe correta. Depois de extracção Citação: Bom: if x = x ... Bad: if = . NO ENTANTO, HÁ maneiras melhores de verificar a existência de um parâmetro: Verifique a existência de argumentos de entrada .
Por algum motivo, a maioria das respostas aqui não me ajudou (talvez esteja relacionado à minha imagem FROM no Dockerfile)
Então, eu preferi criar um bash scriptem meu espaço de trabalho combinado com a --build-argfim de manipular a instrução if enquanto o Docker constrói verificando se o argumento está vazio ou não
Observação: Isso irá para o else (false) no script bash
Observação: Isso irá para o if (true)
Depois de várias tentativas eu encontrei o seguinte artigo e este um que me ajudou a entender 2 coisas:
1) ARG antes de FROM estar fora da construção
2) O shell padrão é / bin / sh, o que significa que if else está funcionando um pouco diferente na construção do docker. por exemplo, você precisa apenas de um "=" em vez de "==" para comparar strings.
Então você pode fazer isso dentro do Dockerfile
e no docker build:
De acordo com o doc para o docker buildcomando , existe um parâmetro chamado --build-arg.
IMO é o que você precisa :)
— barat
Há uma alternativa interessante para as soluções propostas, que funciona com um único Dockerfile , requer apenas uma única chamada para docker build por compilação condicional e evita bash .
O seguinte Dockerfileresolve esse problema. Copie e cole e experimente você mesmo.
Explicação do Dockerfile:
Primeiro pegamos uma baseimagem ( centos:7no seu caso) e a colocamos em seu próprio palco. O basepalco deve conter coisas que você deseja fazer antes da condição. Depois disso, temos mais duas etapas, representando os ramos da nossa condição: branch-version-1e branch-version-2. Nós construímos os dois. O finalestágio então escolhe um desses estágios, com base em my_arg. Dockerfile condicional. Ai está.
Saída durante a execução:
(Eu abreviei um pouco isso ...)
my_var==1
Obrigado ao Tõnis por esta ideia incrível!
— User12547645
Até agora, a melhor abordagem.
— Felipe Desiderati
Também pensei assim, é por isso que o postei aqui. Espalhe a notícia @FelipeDesiderati
Esta é a melhor solução de todas apresentadas aqui, porque você não precisa usar soluções alternativas com scripts / bash, mas use uma forma que envolva apenas conhecimento do Dockerfile. Ótima resposta.
O que "ARG ENV" faz? você pode lançar alguma luz sobre isso? Obrigado.
@Max obrigado por apontar isso. Não é necessário
Basta usar o binário "teste" diretamente para fazer isso. Você também deve usar o comando noop ":" se não quiser especificar uma condição "else", para que o docker não pare com um erro de valor de retorno diferente de zero.
— benjhess
O mesmo que RUN [ -z "$YOURVAR" ] && ... || :, eu acredito
Para a instrução a seguir, se var estiver definido, ambos os ecos serão executados. RUN test -z "$YOURVAR" || echo "var is set" && echo "var is not set"
— Harshad Vyawahare
De fato. Lembre-se de que esses não são blocos condicionais ramificados, eles são executados em série, colocados &&na frente de ||:test ! -z "$YOURVAR" && echo "var is set" || echo "var is not set"
Exatamente como outros disseram, o script de shell ajudaria.
Apenas um caso adicional, IMHO vale a pena mencionar (para alguém que tropeçar aqui, procurando um caso mais fácil), que é Substituição de ambiente .
Variáveis ​​de ambiente (declaradas com oENV instrução) também podem ser usadas em certas instruções como variáveis ​​a serem interpretadas pelo Dockerfile.
A ${variable_name}sintaxe também suporta alguns dos modificadores bash padrão, conforme especificado abaixo:
${variable:-word}indica que se variableestiver definido, o resultado será esse valor. Se variablenão for definido, então wordserá o resultado.
${variable:+word}indica que se variablefor definido, então wordserá o resultado, caso contrário, o resultado é a string vazia.
— Jing Li
A resposta aceita pode resolver a questão, mas se quiser ifcondições de várias linhas no dockerfile, você pode fazer isso colocando \no final de cada linha (semelhante a como faria em um script de shell) e terminando cada comando com ;. Você pode até definir algo set -euxcomo o primeiro comando.