Dockerfile - Setzen Sie ENV auf das Ergebnis des Befehls

92

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

Sultanen
quelle

Antworten:

22

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.

Dimitrie Mititelu
quelle
14
Nur um zu klären - $bleahist 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.
Davnicwil
17

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.

DarkSideF
quelle
Ist /etc/profile.d/docker_init.sh immer noch eine Sache? Diese Antwort ist die einzige Erwähnung, die ich bei Google finden kann, und sie funktioniert bei mir nicht. War es vielleicht Teil einer Docker-Ausführungs-Engine im Jahr 2016, die nicht mehr aktuell ist?
SigmaX
1
@ SigmaX Es ist keine Docker-Sache, es ist eher eine Linux- Sache. Jede *.shDatei im Inneren /etc/profile.d/wird verwendet, um die Umgebung zu
füllen
7

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/bashWenn Sie versuchen, Ihre Docker-Anwendung auszuführen, z. B. eine Node.js-Anwendung, /etc/bash.bashrcwird sie vollständig ignoriert und Ihre Anwendung hat keine einzige Ahnung, was SECRET_KEY_BASEbeim Versuch der Fall ist zuzugreifen process.env.SECRET_KEY_BASE.

Dies ist der Grund, warum ENVjeder versucht, ein Schlüsselwort mit einem dynamischen Befehl zu verwenden, da execDocker jedes Mal, wenn Sie Ihren Container ausführen oder einen Befehl verwenden, ENVjeden 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
vdegenne
quelle
3

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 :

  1. Führen Sie einen Befehl aus und speichern Sie das Ergebnis in einer Datei
  2. Verwenden Sie die Befehlssubstitution, um das vorherige Ergebnis aus dieser Datei in einen anderen Befehl zu übertragen

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.

sebpiq
quelle
2

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.

kat
quelle