Compose: Passe variáveis ​​dentro de fig.yml em tempo de execução

Criado em 24 set. 2014  ·  106Comentários  ·  Fonte: docker/compose

É possível configurar um fig.yml de forma que você possa passar variáveis ​​de tempo de execução ao invés de hard-wiring dentro do fig.yml?

Acho que uma injeção de variável genérica durante a execução seria bastante útil para vários casos de uso.

por exemplo:

 Jenkins:
 imagem: aespinosa / jenkins: mais recente
 portas:
 - "8080"
 nome do host: $ {HOSTNAME}

HOSTNAME = ci fig up

Isso poderia injetar a variável HOSTNAME dentro do fig.yml durante a execução e executar uma execução do docker com o nome do host ci .

ps. Isso é diferente de passar variáveis ​​de ambiente dentro do docker, que já é suportado (http://www.fig.sh/yml.html#environment)

kinenhancement

Comentários muito úteis

O Github precisa implementar um recurso de upvote / importância para problemas.

Todos 106 comentários

Boa ideia - também achei muito útil ao passar env. variável como um parâmetro na execução de teste automatizado: smile:
Mas o seu exemplo implica passar todas as variáveis ​​da sessão de shell dos usuários atuais? Eu prefiro ver isso como no docker

fig up -d -e HOSTNAME:ci

Outra coisa é: qual contêiner deve definir essa variável passada inline? Primeiro, segundo, ambos?

o formato fig up -d -e HOSTNAME:ci soa bem para mim.

quanto a qual container, eu diria torná-lo global para todo o arquivo. Se o autor de fig.yml não quiser que haja conflitos entre os contêineres, ele usará diferentes variáveis ​​para diferentes contêineres ou pode compartilhar a mesma variável com ambos, se necessário.

Isso é ótimo: +1:

Existem duas opções possíveis agora:

  • Depois de fig up -d -e HOSTNAME:ci passamos a variável para todos os contêineres, e digamos que podemos usar nomes de variáveis ​​para detectar, qual contêiner deve usar a variável, por exemplo:
    Tendo web e db container, podemos simplesmente executar:
fig up -d -e WEBS_ENDPOINT=192.168.0.40 -e DBS_ENDPOINT=192.168.0.50

De forma que além do fato de que cada container possui dois endpoints definidos, ainda pode usar este definido por ele.

  • Também podemos usar nomes de contêiner como na abordagem scale=? , mas com a sintaxe:
    fig up -d -e <container_name>:<VARIABLE_NAME>:<VARIABLE> , mas parece bom:
    fig up -d -e web:HOSTNAME:ci ??
    Talvez algo como:
    fig up -d -c web -e HOSTNAME:web -e ROLE:ci -c db -e PASS:pass
    onde web e db são nomes de contêineres definidos em fig.yml

Mas a primeira ideia definitivamente parece melhor para mim

você pode me mostrar uma maquete de um arquivo fig.yml e o respectivo comando CLI
para entender melhor a primeira opção?

os nomes das variáveis ​​são arbitrários ou devem corresponder ao nome do contêiner?

30/09/2014 11h47 GMT + 02: 00 mieciu [email protected] :

Mas a primeira ideia definitivamente parece melhor para mim

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/fig/issues/495#issuecomment -57290241.

Bem, eu pensei em apenas nomes de variáveis ​​arbitrários, mas combiná-los com o nome do contêiner também será bom (como a FIG usa 'nativamente' http://www.fig.sh/env.html). Então, talvez esta seja a maneira correta: +1:

Eu também não considero modificar fig.yml como necessário, passando-os apenas em linha, como em

fig up -d -e HOSTNAME:ci

é 100% bom para mim.

Então vamos dizer que:

fig up -d -e WEB_HOSTNAME:ci

irá passar variáveis ​​para todos os recipientes da web, e se nenhum prefixo for detectado (como HOSTNAME:ci ), as variáveis ​​serão passadas para todos os recipientes

ok, então provavelmente estamos falando sobre coisas diferentes.

Eu entendo o que você propõe como passar variáveis ​​_dentro_ do contêiner,
mas durante a criação do comando docker não faça nada com eles. Minha inicial
proposta é passar variáveis ​​dentro de _fig.yml_ antes de analisá-lo.

No meu caso de uso, eu preciso ser capaz de definir o nome do host não como variável dentro do
container, mas como parte do comando docker:

por exemplo docker -h '$HOSTNAME' jenkins

que no formato fig.yml traduz:

 Jenkins:
 imagem: aespinosa / jenkins: mais recente
 hostname: ci

mas que ci eu gostaria de defini-lo em tempo de execução. Se eu passar minha vriable como você
diga WEB_HOSTNAME:ci então o contêiner _ precisa_ para saber o que fazer com ele.

o que você propõe já está feito com
http://www.fig.sh/yml.html#environment mas
apenas a lista branca de coisas que são definidas no fig.yml quanto possível
entradas variáveis, o que parece suficiente (o autor de fig.yml deve
explicar quais entradas podem ser analisadas no contêiner)

Variáveis ​​de ambiente com apenas uma chave são resolvidas para seus valores na máquina em que a Fig está rodando, o que pode ser útil para valores secretos ou específicos do host
(tirado do site da fig)

Eu também adoraria ter algum tipo de expansão variável no fig.yml. A partir de agora, tenho que usar um modelo fig.yml e criar o fig.yml real com algum script de wrapper.

Meu caso de uso atual: Ter um teste funcional executado em um contêiner do docker, mas ser capaz de especificar a tag da imagem em teste.

+1 neste pedido!

Também estou procurando este suporte para que eu possa deixar um contêiner saber o endereço IP do host para que ele possa se conectar a ele.

+1

+1

Isso é realmente útil, se você armazenar fig.yml no VCS. Por exemplo, nossa equipe usa a opção volumes :, mas todos mapeiam a pasta dos containers para caminhos diferentes na máquina host. Portanto, precisamos modificar alguns parâmetros antes da execução de 'fig up', sem alterar o próprio fig.yml.

Estes são fragmentos de arquivo para esclarecer:

# run.sh
export DIST_FOLDER=~/work/project/dist
fig up
# fig.yml
tomcat:
  image: internal/tomcat
  volumes:
    - "$DIST_FOLDER:/dist:ro"

Este é exatamente o mesmo caso de uso que eu tenho e por que o propus: have fig.yml
no VCS e evite alterações no arquivo para personalizar as execuções.

Na quarta-feira, 26 de novembro de 2014, 14h34, Dzmitry Paulenka [email protected]
escrevi:

Isso é realmente útil, se você armazenar fig.yml no VCS. Por exemplo, nossa equipe
usa a opção _volumes: _, mas todos mapeiam a pasta dos contêineres para
caminho diferente na máquina host. Portanto, precisamos de uma maneira de modificar alguns
parâmetros antes da execução de 'fig up', sem alterar o próprio fig.yml.

Estes são fragmentos de arquivo para esclarecer:

run.shexport DIST_FOLDER = ~ / work / project / dist

fig up

fig.ymltomcat:

imagem: interno / tomcat
volumes:
- "$ DIST_FOLDER: / dist: ro "

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/fig/issues/495#issuecomment -64604460.

Meu caso de uso é semelhante: tenho um fig.yml definindo a configuração de um conjunto de testes funcionais. Agora quero poder executar esses testes em diferentes versões.

# fig.yml
app:
  image: mickey/theapp:${APP_VERSION:latest}
test:
  image: mickey/tests
  links:
   - app
# run
APP_VERSION=1.3 fig up

+1

+1

+1

+1

+1

+1

Existem planos para implementar esse recurso?

Acho que esse recurso já está parcialmente implementado. Muitos campos já oferecem suporte a variáveis ​​de ambiente.

O único exemplo que vejo aqui que ainda não foi implementado é o suporte a variáveis ​​de ambiente para tags de imagem. Isso deve ser uma pequena mudança, PRs bem-vindos :)

Acredito que tudo o que precisa é de os.environ() em fig/service.py:_get_image_name()

Sim, desculpe, eu não estava claro. Eu estava me referindo à resolução do ambiente dentro do próprio Fig.

+1

+: 100:

+1

+1

+1 - Isso pode ser útil para a nossa imagem postgres. Caso contrário, não podemos compartilhar a mesma configuração.

db:
  image: postgres:9.3
  volumes:
    - /$APP_NAME/postgresql/:/var/lib/postgresql/data/
  environment:
    - POSTGRES_USER=$CURRENT_USER
    - POSTGRES_PASSWORD=
  ports:
    - "5432:5432"

+1

+1

: +1:

Tenho algumas sugestões sobre como implementar essa mudança:

  • A Fig deve oferecer suporte a dois métodos separados para acessar esses dados:

    • Variáveis ​​de ambiente, namespaces com FIG_VARIABLE_X

    • Exemplo: Se você está procurando por HOSTNAME em fig.yml, a variável de ambiente deve ser armazenada como FIG_VARIABLE_HOSTNAME

    • Um arquivo YAML separado

    • Por padrão, pesquisaríamos o arquivo variables.yml da pasta raiz

    • O usuário pode especificar a localização deste arquivo como uma variável de ambiente em FIG_VARIABLES_YML

    • O usuário também pode passar este arquivo por meio da linha de comando para qualquer comando como --fig-variables = / foo / bar / variables.yml

  • Crie uma classe chamada FigConfig que envolve todos os acessos aos dados de configuração de fig.yml

    • Esta classe de configuração deve ter todas as APIs disponíveis a partir do valor de retorno de yaml.safe_load para minimizar as alterações nas interações em toda a biblioteca

    • Esta classe de configuração deve incluir ganchos para interpolação de valores primeiro de templates.yaml, substituíveis por valores definidos como variáveis ​​de ambiente

  • Substitua todas as chamadas existentes para yaml.safe_load instanciando uma nova instância de FigConfig com o nome de arquivo fornecido.

Se todos se sentirem bem com esta proposta, ficarei feliz em começar a trabalhar nela e divulgar um relatório.

+1
Mal posso esperar!

Já oferecemos suporte a variáveis ​​de ambiente em alguns campos sem esse nome mutilado. ${HOSTNAME} seria usado diretamente. Acho que isso é muito mais intuitivo do que ter que atribuir um nome a eles.

Como os valores neste arquivo yaml seriam representados? Faria mais sentido como um arquivo com apenas um key=value por linha? Já que isso é mais um "bom ter", eu provavelmente esperaria por isso.

FigConfig

Gosto da ideia de uma aula em vez de um dicionário. Isso torna a validação mais fácil. Você pode centralizar toda a validação de configuração nessa classe (ou antes de criá-la), em vez de espalhar a validação por toda parte. Eu não tentaria emular a interface dict . Acho que você perde muito dos benefícios de usar uma classe se fizer isso.

Outra solicitação relacionada é ser capaz de fornecer valores padrão para as coisas. Algo como: ${HOSTNAME:localhost} é usado em outros arquivos (pelo menos tox.ini, possivelmente outros), para fornecer padrões.

Uma mudança para suportar variáveis ​​de ambiente na maioria dos campos pode ser um bom momento para apresentar esse recurso.

Como um primeiro passado, eu sugeriria apenas adicionar suporte extra para variáveis ​​de ambiente em muitos campos usando os.environ() é provavelmente a maneira mais fácil de oferecer suporte com alterações mínimas de código.

1 sobre como evitar namespacing, uma vez que já é fornecido como tal em muitos
Campos.
+1 também sobre o fornecimento de valores padrão, isso é realmente muito legal,
caso contrário, ao colocar variáveis ​​sem padrões, você perde a fantasia de
fig up

Na quarta-feira, 7 de janeiro de 2015 às 21h20min47s Daniel Nephin [email protected]
escrevi:

Já oferecemos suporte a variáveis ​​de ambiente em alguns campos sem este nome
mutilando. $ {HOSTNAME} seria usado diretamente. Eu acho que isso é muito mais
intuitivo do que ter de nomeá-los.

Como os valores neste arquivo yaml seriam representados? Faria mais
sentido como um arquivo com apenas uma chave = valor por linha? Uma vez que este é mais um
"bom ter", eu provavelmente esperaria por isso.

FigConfig

Gosto da ideia de uma aula em vez de um dicionário. Isso torna a validação mais fácil.
Você pode centralizar toda a validação de configuração nessa classe (ou antes de criar
it), em vez de espalhar a validação por toda parte. Eu não tentaria emular
a interface dict. Eu acho que você perde muitos benefícios de usar um
classe se você fizer isso.

Outra solicitação relacionada é ser capaz de fornecer valores padrão para
coisas. Algo como: $ { HOSTNAME: localhost } é usado em outros arquivos
(tox.ini pelo menos, possivelmente outros), para fornecer padrões.

Uma mudança para suportar variáveis ​​de ambiente na maioria dos campos pode ser uma boa
hora de apresentar esse recurso.

Como um primeiro passado, eu sugeriria apenas adicionar suporte extra para o ambiente
variáveis ​​em muitos campos usando os.environ () é provavelmente a maneira mais fácil
para oferecer suporte a isso com alterações mínimas de código.

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/fig/issues/495#issuecomment -69085278.

Sobre o namespace, acho que é apenas o caso de querer evitar interações ou dependências entre outros sistemas na máquina de alguém. Estou feliz em tornar as variáveis ​​de ambiente de namespacing uma discussão totalmente separada, especialmente porque parece que já existe suporte para algumas variáveis ​​de ambiente básicas.

Acho que você está certo de que um formato simples no estilo INI faz mais sentido aqui. Inicialmente, eu queria evitar a introdução de "outra" forma de gerenciamento de configuração nesta proposta.

Então, talvez a proposta deva ser algo mais como:

  • Adicione acesso a os.environ () para todos os campos fig.yml
  • Apresente uma classe FigConfig responsável por empacotar o acesso aos dados de fig.yml
  • A classe FigConfig deve ter ganchos que podem acessar dados do ambiente (desde o formato $ {}). O valor padrão deve ser fornecido com um ponto-e-vírgula para a string fornecida.

Podemos diminuir o escopo do arquivo de modelo por enquanto, uma vez que os usuários podem criar um arquivo separado com suas variáveis ​​de ambiente de origem por enquanto.

Fico feliz em tentar pegar esse pedaço de trabalho, seja em uma ou duas relações públicas. Estou inclinado a fazer isso em um único PR, já que realmente queremos tirar os.environ () de todos os campos atualmente expostos e ter esse acesso diretamente na classe Config.

+1

+1

+1

+1, especialmente o ponto de @relwell de ter um arquivo YAML separado

+1

+1

Especialmente como este:

# fig.yml
app:
  image: django:${DJANGO_VERSION:latest}
  environment:
    - SECRET_KEY=${SECRET_KEY:ONLYFORTESTING}

+1

as variáveis ​​de ambiente da fyi podem ser referenciadas quando declaradas sem um valor como o estado docs

Variáveis ​​de ambiente com apenas uma chave são resolvidas para seus valores na máquina em que a Fig está sendo executada, o que pode ser útil para valores secretos ou específicos do host.

Para o resto, tente envsubst que pode substituir as referências de variáveis ​​usando a sintaxe $var ou ${var}

envsubst < "fig.tpl" > "fig.yml"
fig up

+1 e eu não acredito que env vars deva ter namespace. Eu quero escrever meu código normalmente e espero que env vars estejam disponíveis como normalmente estariam em um determinado host.

Eu concordo com @thomasdavis .

@NoumanSaleem dá um bom conselho, mas como o envsubst não está disponível no OS X sem instalar gettext do homebrew, por exemplo, que aparentemente pode causar alguns problemas, juntei um equivalente do Go: https://github.com/ilkka/substenv

Concordado com @thomasdavis

+1 para ENV passou no tempo de execução

Eu odeio o +1, mas este é o recurso mais solicitado e discutido aqui.

Podemos resumir a discussão aqui?

  1. Quais variáveis ​​já são suportadas no RC2 e onde estão documentadas?
  2. Qual é o status atual?
  3. Esta solicitação de recurso é aceita e quando se pode esperar uma solução?

Concordado com @ Vad1mo , +1

Este é um script simples que pode ser usado antes de docker-compose

https://gist.github.com/Vad1mo/9ab63f28239515d4dafd

aqui está o liner para instalar:
sudo curl https://gist.githubusercontent.com/Vad1mo/9ab63f28239515d4dafd/raw/aa54b91f4c3671097789a54a9f42ba679b89dbaf/replace-var -o /usr/local/bin/replace-var && sudo chmod 755 /usr/local/bin/replace-var

+1

Eu odeio marcar isto com +1 - mas este realmente é o recurso mais solicitado no github agora ...

definitivamente +1
Qual é o status atual? Este recurso está sendo trabalhado?

+1

+1

+1

+1, meu caso de uso para isso é ter 3 ambientes (um monte de máquinas) que são basicamente duplicados, mas quero portas diferentes para cada um. Em vez de ter um arquivo fig diferente para manter, prefiro um arquivo .sh, posso adicionar um parâmetro como 2000, e isso geraria um ambiente que usa portas como 2001, 2002, 2003. Posso fazer a lógica de adição no script bash, mas vou precisar de algo para passar para a fig.

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

+1

deixe-me resumir o progresso até agora:
image

adicionar comentários '+ 1' e imagens maliciosas certamente não ajudam em um debate.

Eu gostaria de ter o direito de excluí-los. :-P

Na minha opinião, o mantenedor tem tempo e energia limitados e ele precisa escolher onde investi-los. '+1' é a maneira mais simples para um usuário mostrar qual recurso \ bug é mais importante para ele. Existem diferentes tipos de níveis de participação do usuário em projetos OSS. '+1' no bug \ feature diz em uma única bandeira o que eles pensam. E eu gostaria que você tivesse apenas um botão '+1' com um contador.

+1

já não é possível usando env_file ?
por exemplo:

echo 'VAR=test' > env && docker-compose up -d

Pode não ser, porque "As variáveis ​​de ambiente especificadas no ambiente substituem esses valores.", O que eu acho um pouco estranho, porque env_file se destina a permitir parâmetros personalizados (por instalação) IMHO

O arquivo Compose.yml não define apenas variáveis ​​env. Então isso não funcionaria
para definir dinamicamente o nome do host ou o número da porta exposta etc.

Na quarta-feira, 15 de abril de 2015, 9h39 Florian Klein [email protected]
escrevi:

ainda não é possível usando o env_file
https://docs.docker.com/compose/yml/#env_file ?
por exemplo:

echo 'VAR = test'> env && docker-compose up -d

Pode não ser, porque "Variáveis ​​de ambiente especificadas no ambiente
substituir esses valores. "

-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/compose/issues/495#issuecomment -93242626.

+1

Quais são as implicações de segurança disso? Ou seja, um usuário sem privilégios pode definir HOSTNAME ou outras variáveis ​​de ambiente referenciadas no YAML para algo nefasto, que levaria à execução de código não intencional ... por meio de análise YAML com falha ou por meio de seu uso após a análise?

Bem, boa pergunta, suponho que se alguém tem privilégios para executar um arquivo compose.yml definido pelo usuário, você deve assumir que ele 'possui' a máquina, já que ele pode ativar o modo --privileged em um contêiner de sua escolha.

Se o arquivo compose.yml não for definido pelo usuário, o nome do host só poderá ser definido se o autor do arquivo compose.yml permitir que ele seja definido por variável. Nesse caso, a substituição do nome do host não deve executar nenhum comando de shell arbitrário para ser resolvido, caso contrário, a injeção de comando pode ser possível por usuários sem privilégios.

+1

+1

: +1:

Qual é, até o Symfony 2 tem suporte a variáveis ​​em YML!

Ou precisamos de algo além do docker-compose.

+1

+1

+1

Cada vez que você escreve seu +1 , 73 pessoas recebem e-mails inúteis. Isso não faz sentido. Aposto que os mantenedores já entenderam seu ponto de vista.

stop

Desculpe por este spam adicional, mas até que o Github apóie votos de outra forma, você verá muito feio, ocupando espaço e sem utilidade +1 ... Você tem um bom carro btw: p

Fyi, ontem eu solicitei censura automática para conteúdo de spam '+ 1'- no github

se você quer algo implementado, faça uma oferta de patrocínio!

ESTÁ BEM! Sinceros agradecimentos aos + 1s, é realmente útil saber quantas pessoas desejam esse recurso. Criei um novo problema em https://github.com/docker/compose/issues/1377 para rastreá-lo. Vá até lá com seus pensamentos.

Caso alguém não saiba, você pode cancelar a assinatura das notificações por meio do botão Cancelar assinatura à direita. / meta

Eu queria compartilhar uma solução temporária bastante simples que tinha para a expansão variável:

#!/bin/bash
apply_shell_expansion() {
    declare file="$1"
    declare data=$(< "$file")
    declare delimiter="__apply_shell_expansion_delimiter__"
    declare command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter"
    eval "$command"
}
#in case you want to store the variables in a local file
source ./local.env
if ! [ -n "$DOCKER_DATA_PATH" ] ; then
    echo "DOCKER_DATA_PATH not set, using default value"
fi
DOCKER_DATA_PATH=${DOCKER_DATA_PATH:=//c/projects/dockerdata}

apply_shell_expansion docker-compose.tpl.yml > docker-compose.yml

Então seu docker-compose.tpl.yml pode ser confirmado, cada pessoa pode ter local.env que é originado no script, e ele apenas usa a própria expansão de variável do bash, rápida e fácil.

Pode colocar valores padrão para todos os vars no script ou apenas usar a sintaxe da variável padrão diretamente dentro do tpl.yml

Editar: na verdade, esse script parece ser apenas bash, já que boot2docker só tem sh, sh seria:

#!/bin/sh
apply_shell_expansion() {
    local file="$1"
    local data=$(cat "$file")
    local delimiter="__apply_shell_expansion_delimiter__"
    local command="cat <<$delimiter"$'\n'"$data"$'\n'"$delimiter"$'\n'""
    eval "$command"
}
#in case you want to store the variables in a local file
source ./local.env
if ! [ -n "$DOCKER_DATA_PATH" ] ; then
    echo "DOCKER_DATA_PATH not set, using default value"
fi
DOCKER_DATA_PATH=${DOCKER_DATA_PATH:=//c/projects/dockerdata}

apply_shell_expansion docker-compose.tpl.yml > docker-compose.yml

Para um pequeno número de variáveis ​​('tokens'), eu uso um script de shell simples junto com uma versão de modelo do meu arquivo YAML. Aqui está um exemplo real:

arquivos:

docker-compose-template.yml
docker-compose.yml
compose_replace.sh

corre:

sh compose_replace.sh

roteiro:

#!/bin/sh

# variables
base_url_token="{{ base_url }}" # find all these...
base_url="api.foo.com" # replace with url of public rest api
host_ip_token="{{ host_ip }}" # find all these...
host_ip=$(docker-machine ip $(docker-machine active)) # replace with ip of host running NGINX

# output
echo ${base_url_token} = ${base_url}
echo ${host_ip_token} = ${host_ip}

# find and replace
sed -e "s/${base_url_token}/${base_url}/g" \
    -e "s/${host_ip_token}/${host_ip}/g" \
    < docker-compose-template.yml \
    > docker-compose.yml

isso em docker-compose-template.yml :

  extra_hosts:
   - "{{ base_url }}:{{ host_ip }}"

torna-se isso em docker-compose.yml :

  extra_hosts:
   - "api.acme.com:192.168.99.100"

O Github precisa implementar um recurso de upvote / importância para problemas.

@apobbati +1

(A interpolação de variáveis ​​de ambiente foi implementada e mesclada em https://github.com/docker/compose/pull/1765, se é isso que você quer chegar.)

Eu admito que há espaço para interpretações erradas, então atualize seus conhecimentos sobre as estratégias bolcheviques!

+1

Esta página foi útil?
0 / 5 - 0 avaliações