Wert der Umgebungsvariablen in Dockerfile abrufen

254

Ich baue einen Container für eine Ruby-App. Die Konfiguration meiner App ist in Umgebungsvariablen enthalten (mit dotenv in die App geladen ).

Eine dieser Konfigurationsvariablen ist die öffentliche IP-Adresse der App, die intern zum Erstellen von Links verwendet wird. Ich muss einen dnsmasq-Eintrag hinzufügen, der diese IP auf 127.0.0.1 im Container verweist, damit die Links der App abgerufen werden können, als wäre sie nicht containerisiert.

Ich versuche daher, ENVin meiner Docker-Datei eine festzulegen, die eine Umgebungsvariable an den Container übergibt.

Ich habe ein paar Dinge ausprobiert.

ENV REQUEST_DOMAIN $REQUEST_DOMAIN
ENV REQUEST_DOMAIN `REQUEST_DOMAIN`

Alles übergibt jedoch die Zeichenfolge "REQUEST_DOMAIN" anstelle des Werts der Umgebungsvariablen. Gibt es eine Möglichkeit, Umgebungsvariablenwerte vom Hostcomputer an den Container zu übergeben?

Damien MATHIEU
quelle

Antworten:

392

Sie sollten die ARGDirektive in Ihrer Docker-Datei verwenden, die für diesen Zweck bestimmt ist.

Die ARGAnweisung definiert eine Variable, die Benutzer beim Erstellen mit dem Befehl docker build mithilfe des --build-arg <varname>=<value>Flags an den Builder übergeben können .

Ihre Docker-Datei hat also folgende Zeile:

ARG request_domain

oder wenn Sie einen Standardwert bevorzugen:

ARG request_domain=127.0.0.1

Jetzt können Sie diese Variable in Ihrer Docker-Datei referenzieren:

ENV request_domain=$request_domain

dann bauen Sie Ihren Container so:

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


Hinweis 1: Ihr Image wird nicht erstellt, wenn Sie ARGin Ihrer Docker-Datei auf eine verwiesen haben, diese jedoch in ausgeschlossen haben --build-arg.

Hinweis 2: Wenn ein Benutzer ein Build-Argument angibt, das nicht in der Docker-Datei definiert wurde, gibt der Build eine Warnung aus:

[Warnung] Ein oder mehrere Build-Argumente [foo] wurden nicht verbraucht.

Daniel van Flymen
quelle
12
ARG ist ab Docker v1.9 verfügbar.
Synesso
Wird dies unterstützt, um remote auf Docker Repo erstellt zu werden?
James Lin
4
Your image will not build if you have referenced an ARG in your Dockerfile but excluded it in --build-argSie liegen falsch. Sie können ein Image mit Referenzen auch ohne --build-arg erstellen. Darüber hinaus können Sie den Standardwert für das Build-Argument festlegen.
ALex_hha
1
Was ist der Zweck der ENV-Leitung? Für mich war --build-arg + ARG genug.
Phil
3
Das ARG definiert eine Variable, die in der Docker-Datei in nachfolgenden Befehlen verwendet werden soll. Die ENV definiert eine Umgebungsvariable, die an den Container übergeben wird.
Herm
56

So können Sie tun: cat Dockerfile | envsubst | docker build -t my-target -

Dann haben Sie eine Docker-Datei mit so etwas wie:

ENV MY_ENV_VAR $MY_ENV_VAR

Ich denke, es könnte ein Problem mit einigen Sonderzeichen geben, aber dies funktioniert zumindest in den meisten Fällen.

jonasfj
quelle
13
Dies scheint nicht zu funktionieren, wenn Sie Dateien aus dem Verzeichnis hinzufügen müssen, das die Docker-Datei enthält.
Tom Hennen
2
Sehr schöne Lösung! Auf einem Mac können Sie envsubstals Teil von bekommen brew install gettext. Aufgrund möglicher Konflikte mit dem BSD-Build-System handelt es sich jedoch nur um "Keg-only", und es werden keine Symlnks erstellt. Es ist jedoch sicher, diesen ln -s /usr/local/Cellar/gettext/*/bin/envsubst /usr/local/bin/einen Befehl zu Ihrem PATH hinzuzufügen. (Es sind wirklich die Bibliotheken, die das /usr/local/Cellar/gettext/*/bin/envsubst
Problem
1
Um den Kommentar von @ TomHennen zu verdeutlichen, funktioniert das Weiterleiten der Docker-Datei docker build -insbesondere nicht, wenn Sie auf relative Pfade aus Ihrer Docker-Datei verweisen, unabhängig von der Ersetzung von env var.
SuperEb
4
Re @ TomHennen Kommentar, wenn Sie es wollen kontextabhängige Befehle wie COPY verwenden in Ihrem Dockerfile man konnte immer die Ausgabe von envsubst in eine temporäre Datei umleiten und dann speisen die in docker buildstatt. Beispiel cat Dockerfile | envsubst > DockerfileWithEnvVarsdocker build -t my-target -f DockerfileWithEnvVars .rm DockerfileWithEnvVars
:,
Oder Sie können Schwamm aus moreutils Paket verwendenenvsubst < Dockerfile | sponge Dockerfile
ALex_hha
19

Eine Alternative, envsubstohne die Fähigkeit zu verlieren, Befehle wie COPYoder zu verwenden ADD, und ohne Zwischendateien zu verwenden, wäre die Verwendung von Bashs Prozessersetzung :

docker build -f <(envsubst < Dockerfile) -t my-target .
L. Alberto Giménez
quelle
3
Leider scheint das nicht zu funktionieren (Docker 17.09), ich bekomme den Fehlerunable to prepare context: the Dockerfile (/dev/fd/63) must be within the build context
Alexander Klimetschek
11

Laden Sie Umgebungsvariablen aus einer Datei, die Sie zur Laufzeit erstellen.

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

... dann in der Docker-Datei

ADD build /build
RUN /build/test.sh

Dabei testet test.sh MYVAR aus env.sh.

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

Wenn Sie nur alle Umgebungsvariablen ($ ExampleEnvVar) in einer Docker-Datei suchen und ersetzen möchten, erstellen Sie diese:

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

snassr
quelle
Die beste Antwort hier und basierend darauf war möglich: envsubst < ./Dockerfile | docker build -squash -t ${DOCKIMG}:${VERSION} . -f -Wo die FROMZeile die Umgebungsvariable verwendet.
Mikequentel
-6

-eSchlüssel zum Übergeben von Umgebungsvariablen an den Container hinzufügen . Beispiel:

$ 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
quelle
6
Damien will ein Image aufbauen. -e arbeitet stattdessen mit dem Befehl run.
Andres Restrepo