Czy można ustawić zmienną Docker ENV na wynik polecenia? Lubić:
ENV MY_VAR whoami
chcę, aby MY_VAR otrzymywał wartość „root” lub cokolwiek zwraca whoami
Odpowiedzi:
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.
$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.
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.
*.sh
plik wewnątrz /etc/profile.d/
jest używany do zapełniania środowiska
W tej chwili wyniku polecenia można używać z RUN export
, ale nie można go przypisać do ENV
zmiennej.
Znany problem: https://github.com/docker/docker/issues/29110
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.bashrc
zostanie całkowicie zignorowana, a Twoja aplikacja nie będzie miała pojęcia, co SECRET_KEY_BASE
jest podczas próby aby uzyskać dostęp process.env.SECRET_KEY_BASE
.
To jest powód, dla którego ENV
słowo kluczowe jest tym, czego wszyscy próbują użyć z poleceniem dynamicznym, ponieważ za każdym razem, gdy uruchamiasz kontener lub używasz exec
polecenia, Docker sprawdzi ENV
i 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
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:
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.
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.