É possível definir uma variável docker ENV para o resultado de um comando? Gostar:
ENV MY_VAR whoami
eu quero que MY_VAR obtenha o valor "root" ou o que quer que whoami retorne
Respostas:
Como um complemento à resposta DarkSideF.
Você deve estar ciente de que cada linha / comando no Dockerfile é executado em outro contêiner.
Você pode fazer algo assim:
RUN export bleah=$(hostname -f);echo $bleah;
Isso é executado em um único contêiner.
$bleah
está disponível em nenhum lugar fora deste comando RUN, nem mesmo na próxima linha no mesmo dockerfile, muito menos em outra imagem em que se baseia. Recurso ausente realmente óbvio do docker aqui, parece que escrever e ler de um arquivo é a única maneira de realmente armazenar variáveis (dinâmicas) em imagens e passá-las entre imagens, o que parece super hacky.
Eu tive o mesmo problema e encontrei uma maneira de definir a variável de ambiente como resultado da função usando o comando RUN no dockerfile.
Por exemplo, eu preciso definir SECRET_KEY_BASE para o aplicativo Rails apenas uma vez, sem alterar como faria quando eu executo:
docker run -e SECRET_KEY_BASE="$(openssl rand -hex 64)"
Em vez disso, escrevo na string do Dockerfile como:
RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'
e minha variável env disponível a partir do root, mesmo após o login do bash. ou talvez
RUN /bin/bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" > /etc/profile.d/docker_init.sh'
então ele variável disponível nos comandos CMD e ENTRYPOINT
O Docker armazena em cache como camada e muda apenas se você alterar algumas strings antes dele.
Você também pode tentar maneiras diferentes de definir a variável de ambiente.
*.sh
arquivo dentro /etc/profile.d/
é usado para
Neste momento, um resultado de comando pode ser usado com RUN export
, mas não pode ser atribuído a uma ENV
variável.
Problema conhecido: https://github.com/docker/docker/issues/29110
Esta resposta é uma resposta a @DarkSideF ,
O método que ele está propondo é o seguinte, em Dockerfile
:
RUN bash -l -c 'echo export SECRET_KEY_BASE="$(openssl rand -hex 64)" >> /etc/bash.bashrc'
( adicionando uma exportação no/etc/bash.bashrc
)
É bom, mas a variável de ambiente só estará disponível para o processo /bin/bash
, e se você tentar executar seu aplicativo docker, por exemplo, um aplicativo Node.js, /etc/bash.bashrc
será completamente ignorado e seu aplicativo não terá uma única pista do que SECRET_KEY_BASE
está ao tentar para acessar process.env.SECRET_KEY_BASE
.
Essa é a razão pela qual ENV
palavra-chave é o que todos estão tentando usar com um comando dinâmico, porque toda vez que você executa seu contêiner ou usa um exec
comando, o Docker verifica ENV
e canaliza cada valor no processo executado atualmente (semelhante a -e
).
Uma solução é usar um wrapper (crédito para @duglin neste problema do github ). Tenha um arquivo wrapper (por exemplo envwrapper
) na raiz do projeto contendo:
#!/bin/bash
export SECRET_KEY_BASE="$(openssl rand -hex 64)"
export ANOTHER_ENV "hello world"
$*
e então em seu Dockerfile
:
...
COPY . .
RUN mv envwrapper /bin/.
RUN chmod 755 /bin/envwrapper
CMD envwrapper myapp
Além da resposta de @ DarkSideF, se quiser reutilizar o resultado de um comando anterior Dockerfile
durante o processo de compilação , você pode usar a seguinte solução alternativa:
Por exemplo :
RUN echo "bla" > ./result
RUN echo $(cat ./result)
Para algo mais limpo, você também pode usar a seguinte essência, que fornece uma pequena CLI chamada envstore.py
:
RUN envstore.py set MY_VAR bla
RUN echo $(envstore.py get MY_VAR)
Ou você pode usar a biblioteca python-dotenv que possui uma CLI semelhante.
Não tenho certeza se é isso que você estava procurando, mas para injetar ENV vars ou ARGS em seu .Dockerfile, esse padrão funciona.
em seu 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 .
para obter um ARG em seu .Dockerfile, o snippet pode ter a seguinte aparência:
FROM scratch
ARG ARTIFACT_TAG
FROM my_artifact_home_url/bucketname:${ARTIFACT_TAG}
como alternativa, para obter um ENV em seu .Dockerfile, o snippet pode ter a seguinte aparência:
FROM someimage:latest
ARG ARTIFACT_TAG
ENV ARTIFACT_TAG=${ARTIFACT_TAG}
a ideia é que você execute o script de shell e isso chama o .Dockerfile com os args passados como opções na construção.