Obtener el valor de la variable de entorno en Dockerfile

254

Estoy construyendo un contenedor para una aplicación de rubí. La configuración de mi aplicación está contenida en variables de entorno (cargadas dentro de la aplicación con dotenv ).

Una de esas variables de configuración es la ip pública de la aplicación, que se usa internamente para crear enlaces. Necesito agregar una entrada dnsmasq que apunte esta ip a 127.0.0.1 dentro del contenedor, para que pueda obtener los enlaces de la aplicación como si no estuviera en contenedor.

Por lo tanto, estoy tratando de establecer un ENVarchivo en mi Docker que pasaría una variable de entorno al contenedor.

Intenté algunas cosas.

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`

Sin embargo, todo pasa la cadena "REQUEST_DOMAIN" en lugar del valor de la variable de entorno. ¿Hay alguna manera de pasar valores de variables de entorno de la máquina host al contenedor?

Damien MATHIEU
fuente

Respuestas:

392

Debería usar la ARGdirectiva en su Dockerfile que está destinada para este propósito.

La ARGinstrucción define una variable que los usuarios pueden pasar en el momento de la compilación al constructor con el comando de compilación de la ventana acoplable utilizando el --build-arg <varname>=<value>indicador.

Entonces su Dockerfile tendrá esta línea:

ARG request_domain

o si prefiere un valor predeterminado:

ARG request_domain=127.0.0.1

Ahora puede hacer referencia a esta variable dentro de su Dockerfile:

ENV request_domain=$request_domain

entonces construirás tu contenedor así:

$ docker build --build-arg request_domain=mydomain Dockerfile


Nota 1: su imagen no se compilará si ha hecho referencia a un ARGarchivo en Dockerf pero lo ha excluido --build-arg.

Nota 2: si un usuario especifica un argumento de compilación que no se definió en el Dockerfile, la compilación genera una advertencia:

[Advertencia] Uno o más build-args [foo] no fueron consumidos.

Daniel van Flymen
fuente
12
ARG está disponible desde docker v1.9 en adelante.
Synesso
¿Se admite esto para que se cree de forma remota en el repositorio de Docker?
James Lin el
44
Your image will not build if you have referenced an ARG in your Dockerfile but excluded it in --build-argEstá usted equivocado. Puede crear imágenes con referencias incluso sin --build-arg. Además, puede establecer el valor predeterminado para la construcción arg.
ALex_hha
1
¿Cuál es el propósito de la línea ENV? Para mí --build-arg + ARG fue suficiente.
Phil
3
El ARG define una variable para ser utilizada dentro del dockerfile en comandos posteriores. El ENV define una variable de entorno que se pasa al contenedor.
herm
56

Entonces puedes hacer: cat Dockerfile | envsubst | docker build -t my-target -

Luego tenga un Dockerfile con algo como:

ENV MY_ENV_VAR $MY_ENV_VAR

Supongo que podría haber un problema con algunos caracteres especiales, pero esto funciona para la mayoría de los casos al menos.

jonasfj
fuente
13
Esto no parece funcionar si necesita AGREGAR archivos desde el directorio que contiene el Dockerfile.
Tom Hennen
2
Muy buena solución! En una Mac puedes obtener envsubstcomo parte de brew install gettext. Pero debido a posibles conflictos con el sistema de compilación BSD, es "solo de barril" y no se crean symlnks. Sin embargo, es seguro hacer eso ln -s /usr/local/Cellar/gettext/*/bin/envsubst /usr/local/bin/para agregar ese comando a su RUTA. (Realmente son las libs lo que preocupa.) O puede usarlo en su /usr/local/Cellar/gettext/*/bin/envsubstubicación
Bruno Bronosky
1
Para aclarar el comentario de @ TomHennen, canalizar el Dockerfile docker build -es, específicamente, lo que no funciona cuando hace referencia a rutas relativas desde su Dockerfile, independientemente de la sustitución de var.
superEb
44
Re @ comentario de TomHennen, si usted no desea utilizar comandos dependientes del contexto como copia en su Dockerfile puede redirigir siempre la salida de envsubst en un archivo temporal y luego alimentar a eso en docker buildsu lugar. Ejemplo: cat Dockerfile | envsubst > DockerfileWithEnvVarsentonces docker build -t my-target -f DockerfileWithEnvVars ., entoncesrm DockerfileWithEnvVars
snark
O puede usar una esponja del paquete envsubst < Dockerfile | sponge Dockerfile
moreutils
19

Una alternativa para usar envsubstsin perder la capacidad de usar comandos como COPYo ADD, y sin usar archivos intermedios sería usar la sustitución de proceso de Bash :

docker build -f <(envsubst < Dockerfile) -t my-target .
L. Alberto Giménez
fuente
3
desafortunadamente eso no parece funcionar (Docker 17.09), recibo el errorunable to prepare context: the Dockerfile (/dev/fd/63) must be within the build context
Alexander Klimetschek
11

Cargue variables de entorno de un archivo que cree en tiempo de ejecución.

export MYVAR="my_var_outside"
cat > build/env.sh <<EOF
MYVAR=${MYVAR}
EOF

... luego en el Dockerfile

ADD build /build
RUN /build/test.sh

donde test.sh carga MYVAR desde env.sh

#!/bin/bash
. /build/env.sh
echo $MYVAR > /tmp/testfile
Dan C
fuente
4

Si solo desea buscar y reemplazar todas las variables de entorno ($ ExampleEnvVar) en un Dockerfile, compílelo, esto funcionaría:

envsubst < /path/to/Dockerfile | docker build -t myDockerImage . -f -

snassr
fuente
La mejor respuesta aquí, y en base a eso, fue capaz de hacer: envsubst < ./Dockerfile | docker build -squash -t ${DOCKIMG}:${VERSION} . -f -dónde la FROMlínea usa la variable de entorno.
mikequentel
-6

agregue -eclave para pasar variables de entorno al contenedor. ejemplo:

$ MYSQLHOSTIP=$(sudo docker inspect -format="{{ .NetworkSettings.IPAddress }}" $MYSQL_CONRAINER_ID)
$ sudo docker run -e DBIP=$MYSQLHOSTIP -i -t myimage /bin/bash

root@87f235949a13:/# echo $DBIP
172.17.0.2
Valentin Kantor
fuente
66
Damien está buscando construir una imagen. -e trabaja con el comando ejecutar en su lugar.
Andres Restrepo