Dockerfile - ustaw ENV na wynik polecenia

Odpowiedzi:

23

Jako dodatek do odpowiedzi DarkSideF.

Należy pamiętać, że każda linia / polecenie w pliku Dockerfile jest uruchamiane w innym kontenerze.

Możesz zrobić coś takiego:

RUN export bleah=$(hostname -f);echo $bleah;

Jest to uruchamiane w jednym kontenerze.

Dimitrie Mititelu
źródło
14
Dla wyjaśnienia - nie$bleah jest dostępne nigdzie poza tym poleceniem RUN, nawet w następnej linii w tym samym pliku dockerfile, nie mówiąc już o innym obrazie, na którym jest oparty. Naprawdę oczywista brakująca funkcja z dockera tutaj, wygląda na to, że zapisywanie i odczytywanie z pliku jest jedynym sposobem na faktyczne przechowywanie (dynamicznych) zmiennych w obrazach i przekazywanie ich między obrazami, co wydaje się super hackerskie.
davnicwil
17

Miałem ten sam problem i znalazłem sposób na ustawienie zmiennej środowiskowej w wyniku funkcji za pomocą polecenia RUN w pliku dockerfile.

Na przykład muszę ustawić SECRET_KEY_BASE dla aplikacji Rails tylko raz, bez zmiany, jak przy uruchomieniu:

docker run  -e SECRET_KEY_BASE="$(openssl rand -hex 64)"

Zamiast tego piszę do ciągu Dockerfile, takiego jak:

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'

a moja zmienna env dostępna z poziomu roota, nawet po zalogowaniu bash. albo może

RUN /bin/bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" > /etc/profile.d/docker_init.sh'

to zmienna dostępna w poleceniach CMD i ENTRYPOINT

Docker buforuje go jako warstwę i zmienia tylko wtedy, gdy zmienisz kilka ciągów przed nią.

Możesz także wypróbować różne sposoby ustawiania zmiennej środowiskowej.

DarkSideF
źródło
Czy /etc/profile.d/docker_init.sh nadal jest rzeczą? Ta odpowiedź jest jedyną wzmianką o tym, jaką mogę znaleźć w Google, i nie działa dla mnie. Czy to może część silnika wykonawczego Dockera w 2016 roku, który nie jest już aktualny?
SigmaX
1
@SigmaX To nie jest kwestia dokera, to bardziej kwestia Linuksa . Każdy *.shplik wewnątrz /etc/profile.d/jest używany do zapełniania środowiska
Madacol
7

Ta odpowiedź jest odpowiedzią na @DarkSideF ,

Metoda, którą proponuje, jest następująca, w Dockerfile:

RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'

( dodanie eksportu w/etc/bash.bashrc )

To dobrze, ale zmienna środowiskowa będzie dostępna tylko dla procesu /bin/bash, a jeśli spróbujesz uruchomić swoją aplikację docker, na przykład aplikację Node.js, /etc/bash.bashrczostanie całkowicie zignorowana, a Twoja aplikacja nie będzie miała pojęcia, co SECRET_KEY_BASEjest podczas próby aby uzyskać dostęp process.env.SECRET_KEY_BASE.

To jest powód, dla którego ENVsłowo kluczowe jest tym, czego wszyscy próbują użyć z poleceniem dynamicznym, ponieważ za każdym razem, gdy uruchamiasz kontener lub używasz execpolecenia, Docker sprawdzi ENVi potokuje każdą wartość w aktualnie uruchomionym procesie (podobnie jak -e).

Jednym z rozwiązań jest użycie wrappera (autorstwo @duglin w tym wydaniu na githubie ). Miej plik opakowania (np. envwrapper) W katalogu głównym projektu zawierający:

#!/bin/bash
export SECRET_KEY_BASE="$(openssl rand -hex 64)"
export ANOTHER_ENV "hello world"
$*

a potem w Dockerfile:

...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp
vdegenne
źródło
2

Jako dodatek do odpowiedzi @ DarkSideF, jeśli chcesz ponownie użyć wyniku poprzedniego polecenia w Dockerfile trakcie procesu kompilacji , możesz zastosować następujące obejście:

  1. uruchom polecenie, zapisz wynik w pliku
  2. użyj podstawiania poleceń, aby pobrać poprzedni wynik z tego pliku do innego polecenia

Na przykład :

RUN echo "bla" > ./result
RUN echo $(cat ./result)

Aby uzyskać coś czystszego, możesz również użyć następującego streszczenia, które zapewnia mały CLI o nazwie envstore.py:

RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)

Lub możesz użyć biblioteki python-dotenv, która ma podobny interfejs CLI.

sebpiq
źródło
2

Nie jestem pewien, czy tego właśnie szukałeś, ale aby wstrzyknąć zmienne ENV lub ARGS do twojego pliku .Dockerfile, ten wzorzec działa.

w twoim 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 .

aby uzyskać ARG w pliku .Dockerfile, fragment może wyglądać następująco:

FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}

alternatywnie, aby uzyskać ENV w pliku .Dockerfile, fragment może wyglądać następująco:

FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}

pomysł polega na tym, że uruchamiasz skrypt powłoki i wywołuje on plik .Dockerfile z argumentami przekazanymi jako opcje podczas kompilacji.

kat
źródło