Ist es möglich, eine Docker-ENV-Variable auf das Ergebnis eines Befehls zu setzen? Mögen:
ENV MY_VAR whoami
Ich möchte, dass MY_VAR den Wert "root" erhält oder was auch immer whoami zurückgibt
Antworten:
Als Ergänzung zur DarkSideF-Antwort.
Sie sollten sich bewusst sein, dass jede Zeile / jeder Befehl in Dockerfile in einem anderen Container ausgeführt wird.
Sie können so etwas tun:
RUN export bleah=$(hostname -f);echo $bleah;
Dies wird in einem einzigen Container ausgeführt.
$bleah
ist nicht überall verfügbar außerhalb dieses RUN - Befehls, nicht einmal in der nächsten Zeile in der gleichen dockerfile, geschweige denn in einem anderen Bild ist es basiert. Wirklich offensichtliche fehlende Funktion von Docker hier, es sieht so aus, als ob das Schreiben und Lesen aus einer Datei die einzige Möglichkeit ist, (dynamische) Variablen in Bildern zu speichern und zwischen Bildern zu übertragen, was sehr hackig erscheint.
Ich hatte das gleiche Problem und fand einen Weg, die Umgebungsvariable als Ergebnis der Funktion mithilfe des RUN-Befehls in der Docker-Datei festzulegen.
Zum Beispiel muss ich die App SECRET_KEY_BASE für Rails nur einmal festlegen, ohne sie zu ändern, wie dies beim Ausführen der Fall wäre:
docker run -e SECRET_KEY_BASE="$(openssl rand -hex 64)"
Stattdessen schreibe ich in Dockerfile String wie:
RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'
und meine env-Variable, die auch nach dem Bash-Login über root verfügbar ist. oder vielleicht
RUN /bin/bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" > /etc/profile.d/docker_init.sh'
dann ist die Variable in den Befehlen CMD und ENTRYPOINT verfügbar
Docker speichert es als Ebene zwischen und ändert es nur, wenn Sie einige Zeichenfolgen davor ändern.
Sie können auch verschiedene Möglichkeiten ausprobieren , um Umgebungsvariablen festzulegen.
*.sh
Datei im Inneren /etc/profile.d/
wird verwendet, um die Umgebung zu
Zu diesem Zeitpunkt kann ein Befehlsergebnis mit verwendet RUN export
, aber keiner ENV
Variablen zugewiesen werden.
Bekanntes Problem: https://github.com/docker/docker/issues/29110
Diese Antwort ist eine Antwort auf @DarkSideF ,
Die Methode, die er vorschlägt, ist die folgende in Dockerfile
:
RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'
( Hinzufügen eines Exports in der/etc/bash.bashrc
)
Es ist gut, aber die Umgebungsvariable ist nur für den Prozess verfügbar. /bin/bash
Wenn Sie versuchen, Ihre Docker-Anwendung auszuführen, z. B. eine Node.js-Anwendung, /etc/bash.bashrc
wird sie vollständig ignoriert und Ihre Anwendung hat keine einzige Ahnung, was SECRET_KEY_BASE
beim Versuch der Fall ist zuzugreifen process.env.SECRET_KEY_BASE
.
Dies ist der Grund, warum ENV
jeder versucht, ein Schlüsselwort mit einem dynamischen Befehl zu verwenden, da exec
Docker jedes Mal, wenn Sie Ihren Container ausführen oder einen Befehl verwenden, ENV
jeden Wert im aktuell ausgeführten Prozess überprüft und weiterleitet (ähnlich wie -e
).
Eine Lösung besteht darin, einen Wrapper zu verwenden (Gutschrift an @duglin in diesem Github-Problem ). Haben Sie eine Wrapper-Datei (z. B. envwrapper
) in Ihrem Projektstamm, die Folgendes enthält:
#!/bin/bash
export SECRET_KEY_BASE="$(openssl rand -hex 64)"
export ANOTHER_ENV "hello world"
$*
und dann in Ihrem Dockerfile
:
...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp
Als Ergänzung zur Antwort von @ DarkSideF können Sie die folgende Problemumgehung verwenden, wenn Sie das Ergebnis eines vorherigen Befehls in Ihrem Dockerfile
während des Erstellungsprozesses wiederverwenden möchten :
Zum Beispiel :
RUN echo "bla" > ./result
RUN echo $(cat ./result)
Für etwas Saubereres können Sie auch den folgenden Kern verwenden, der eine kleine CLI mit dem Namen bereitstellt envstore.py
:
RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)
Oder Sie können die Python-Dotenv- Bibliothek verwenden, die eine ähnliche CLI hat.
Sie sind sich nicht sicher, ob Sie danach gesucht haben, aber um ENV-Variablen oder ARGS in Ihren .Dockerfile-Build einzufügen, funktioniert dieses Muster.
in deiner my_build.sh:
echo getting version of osbase image to build from
OSBASE=$(grep "osbase_version" .version | sed 's/^.*: //')
echo building docker
docker build -f \
--build-arg ARTIFACT_TAG=$OSBASE \
PATH_TO_MY.Dockerfile \
-t my_artifact_home_url/bucketname:$TAG .
Um ein ARG in Ihre .Docker-Datei zu bekommen, könnte das Snippet folgendermaßen aussehen:
FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}
Alternativ könnte das Snippet folgendermaßen aussehen, um eine ENV in Ihre .Docker-Datei zu bekommen:
FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}
Die Idee ist, dass Sie das Shell-Skript ausführen und das .Dockerfile mit den Argumenten aufruft, die als Optionen für den Build übergeben wurden.