Dockerfile if else condición con argumentos externos


Tengo dockerfile

FROM centos:7
ENV foo=42

Entonces lo construyo

docker build -t my_docker .

Y ejecutarlo.

docker run -it -d  my_docker

¿Es posible pasar argumentos desde la línea de comandos y usarlo con if else en Dockerfile? Quiero decir algo como

FROM centos:7
if (my_arg==42)
     {ENV=TRUE}
else:
     {ENV=FALSE}

Y construir con este argumento.

 docker build -t my_docker . --my_arg=42
Author: nick_gabpe, 2017-04-27

5 answers

Puede que no parezca tan limpio, pero puede tener su Dockerfile (condicional) de la siguiente manera:

FROM centos:7
ARG arg
RUN if [ "x$arg" = "x" ] ; then echo Argument not provided ; else echo Argument is $arg ; fi

Y luego construir la imagen como:

docker build -t my_docker . --build-arg arg=45

O

docker build -t my_docker .

 69
Author: Qasim Sarfraz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-27 11:35:59

De acuerdo con la documentación de build command , hay un parámetro llamado --build-arg

Https://docs.docker.com/engine/reference/commandline/build/#set-build-time-variables-build-arg

Ejemplo de uso
docker build --build-arg HTTP_PROXY=http://10.20.30.2:1234 .

IMO es lo que necesitas:)

 18
Author: barat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-18 06:08:58

Simplemente use el binario "test" directamente para hacer esto. También debe usar el comando noop": "si no desea especificar una condición" else", para que docker no se detenga con un error de valor de retorno distinto de cero.

RUN test -z "$YOURVAR" || echo "var is set" && echo "var is not set"
RUN test -z "$YOURVAR" && echo "var is not set" || :
RUN test -z "$YOURVAR" || echo "var is set" && :
 3
Author: benjhess,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-18 13:26:11

Por alguna razón la mayoría de las respuestas aquí no me ayudaron (tal vez esté relacionada con mi imagen de FROM en el Dockerfile)

Así que preferí crear un bash script en mi espacio de trabajo combinado con --build-arg para manejar la instrucción if mientras se construye Docker comprobando si el argumento está vacío o no

Guión Bash:

#!/bin/bash -x

if test -z $1 ; then 
    echo "The arg is empty"
    ....do something....
else 
    echo "The arg is not empty: $1"
    ....do something else....
fi

Dockerfile:

FROM ...
....
ARG arg
COPY bash.sh /tmp/  
RUN chmod u+x /tmp/bash.sh && /tmp/bash.sh $arg
....

Compilación de Docker:

docker build --pull -f "Dockerfile" -t $SERVICE_NAME --build-arg arg="yes" .

Observación: Esto irá al otro (falso) en el bash script

docker build --pull -f "Dockerfile" -t $SERVICE_NAME .

Observación: Esto irá a la if (true)

Editar 1:

Después de varios intentos he encontrado el siguiente artículo y este uno lo que me ayudó a entender 2 cosas:

1) ARG antes de está fuera de la construcción

2) El shell predeterminado es /bin/sh, lo que significa que si else está trabajando un poco diferente en la compilación de docker. por ejemplo, solo necesita un "=" en lugar de "==" para comparar cadena.

Así que puedes hacer esto dentro del Dockerfile

ARG argname=false   #default argument when not provided in the --build-arg
RUN if [ "$argname" = "false" ] ; then echo 'false'; else echo 'true'; fi

Y en el docker build:

docker build --pull -f "Dockerfile" --label "service_name=${SERVICE_NAME}" -t $SERVICE_NAME --build-arg argname=true .
 2
Author: dsaydon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-26 14:55:02

Si lo que desea es construir dinámicamente imágenes, probablemente debería hacerlo con un script de compilación.

Docker ya proporciona SDK para muchos lenguajes que generalmente incluyen una llamada de compilación que le permite suministrar una cadena arbitraria o un archivo Dockerfile desde el que compilar.

Por ejemplo, con Ruby:

require 'docker'

val = my_arg == 42 ? "TRUE" : "FALSE"

# Create an Image from a Dockerfile as a String.
Docker::Image.build("FROM centos:7\nENV MY_ENV=" + val)
 0
Author: Snps,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-27 11:59:01