(Estou criando um novo problema para isso, pois o antigo acumulou muita bagagem.)
Deve ser possível passar variáveis de ambiente para o valor de qualquer * entrada de configuração em docker-compose.yml
. Muitas pessoas querem fazer isso, é bom para a portabilidade e estou satisfeito que não vai causar o caos.
Eu tenho algumas estimativas.
É útil poder especificar que uma variável que _deve_ estar presente no ambiente, ou seja, que o Compose se recusará a ser executado se não estiver. No entanto, isso será uma dor quando você tiver muitos deles, então deve ser algo que você habilite explicitamente ou deve ser possível especificar um valor padrão.
A implementação do MVP não precisa ter nenhum dos recursos, mas deve haver um caminho claro para a implementação de ambos de maneira compatível com versões anteriores.
Há um forte caso para implementar um padrão estabelecido, desde que não seja pesado - nossos requisitos de funcionalidade são mínimos.
${VARIABLE}
- gera uma string vazia se VARIABLE
não estiver definido${VARIABLE-default}
- gera default
se VARIABLE
não estiver definido${VARIABLE?}
- erros se VARIABLE
não estiver definidohttps://github.com/docker/compose/pull/845 implementou uma sintaxe ${VARIABLE:default}
estilo Bash, que é semelhante à expansão do parâmetro POSIX, mas um pouco diferente.
A função os.path.expandvars
do Python implementa o caso mais básico de expansão do parâmetro POSIX:
>>> from os.path import expandvars
>>> expandvars('${HOME}')
'/Users/aanand'
No entanto, tem pelo menos 2 problemas:
`` `
expandvars ('$ {UNSET}')
'$ {UNSET}'
`` `
- A sintaxe malformada não apresenta erros - em vez disso, também resulta em nenhuma expansão:
`` `
expandvars ('$ {HOME')
'$ {HOME'
`` `
Até agora, https://github.com/docker/compose/pull/845 é o mais próximo que temos, mas estou fundamentalmente desconfiado de uma implementação que depende de expressões regulares. A modelagem não é uma tarefa trivial, e as pessoas vão colocar todos os tipos de coisas quebradas, então precisamos de algo que seja robusto, rígido e com mensagens úteis. Dois requisitos importantes:
Pode muito bem haver boas implementações de Python de interpolação de variável semelhante ao Bash por aí - se não, criar algo autônomo seria muito preferível a aumentar a base de código do Compose.
* Na verdade, há alguma chave de configuração para a qual _não devemos_ permitir a interpolação?
Até onde você deseja ir com esses padrões UNIX estabelecidos? (FWIW, não é um padrão de fato, é um padrão real.)
Como alguém que ocasionalmente tenta acidentalmente usar expansões de parâmetro POSIX em Dockerfiles, se elas fossem suportadas em docker-compose.yml isso me faria um campista feliz.
@kojiromike Hmm, então a expansão do parâmetro POSIX é realmente o que eu estava
Edit: Eu atualizei meus pensamentos sobre a sintaxe na descrição.
Tenho seguido o tópico antigo e queríamos ter esse recurso com urgência. Finalmente a dor foi muito grande e criamos um script bahs pré-processador yaml para substituir variáveis no estilo POSIX. funcionou bem, mas eventualmente paramos de usá-lo porque tinha um problema. Você deve executar o pré-processador primeiro e definir todos os parâmetros antes de obter a solução final. Agora estamos usando o recurso docker yaml extends. Porque nos permite verificar a configuração real e apenas executá-la no destino. Sabemos melhor o que vai acontecer.
Embora eu fosse um defensor da passagem de variáveis docker-compose, agora não tenho tanta certeza.
Como uma solução ideal, eu preferiria ver o docker extends bem feito. Em certo sentido, essa seria uma solução adequada para ambos. Então, o que está quebrado no docker estende? É basicamente o fato de que você deve gravar todas as entradas no arquivo herdado. Não é uma fusão em que você insere apenas o que deseja substituir.
Veja nosso exemplo real e como ele é detalhado. Existem apenas duas linhas que importam.
#Common
elasticsearch:
image: zinvoice/elasticsearch
hostname: elasticsearch
restart: always
dns: 172.17.42.1
ports:
- "9200:9200"
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
- /data/elasticsearch:/opt/elasticsearch/data/elasticsearch
logstash:
image: zinvoice/logstash
hostname: logstash
dns: 172.17.42.1
restart: always
ports:
- "5000:5000"
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
kibana:
image: zinvoice/kibana
hostname: kibana
dns: 172.17.42.1
restart: always
ports:
- "5601:5601"
volumes:
- /etc/localtime:/etc/localtime:ro
- /etc/timezone:/etc/timezone:ro
logspout:
image: zinvoice/logspout
hostname: logspout
command: logstash://logstash.docker:5000
restart: always
dns: 172.17.42.1
ports:
- "8003:8000"
volumes:
- /var/run/docker.sock:/tmp/docker.sock
doorman:
image: zinvoice/doorman
hostname: doorman
restart: always
dns: 172.17.42.1
ports:
- "8085:8085"
# inherited
elasticsearch:
extends:
file: ../common.yml
service: elasticsearch
logstash:
extends:
file: ../common.yml
service: logstash
kibana:
extends:
file: ../common.yml
service: kibana
logspout:
extends:
file: ../common.yml
service: logspout
doorman:
environment:
- DOORMAN_GITHUB_APPID=xxxxxxxx
- DOORMAN_GITHUB_APPSECRET=xxxxxx
links:
- nginxtrusted
extends:
file: ../common.yml
service: doorman
Portanto, meu docker de correção de recomendação estende e torna menos prolixo. Você nem mesmo precisa escrever tantos códigos, já que YAML fornece todas as funcionalidades de que você precisa. Se você seguir o YAML padrão, o arquivo poderá ser analisado ou criado por outras ferramentas e IUs.
Dê uma olhada em "âncoras de nó" YAML e "mesclagem de arquivos" YAML. Pode ser a solução perfeita.
Para sua informação: esta discussão continua agora no # 1380
@ Vad1mo Concordo que extends
fica aquém no seu caso. Há muitas coisas que podemos fazer para melhorar essa experiência - você poderia abrir uma edição separada para isso, para que não sejamos desviados aqui?
Claro! Queria apenas destacar que esta pode ser uma alternativa fácil e elegante.
Se compose extends leva você a meio caminho de passagem de variável, então um compose-extends aprimorado tornará a passagem de variável obsoleta. Ter menos conceitos para entender torna mais fácil para o usuário.
Meu caso de uso é permitir $PWD
em volumes
, para que cada desenvolvedor da equipe possa clonar um repositório para qualquer lugar e os caminhos ainda sejam montados corretamente.
elasticsearch:
image: zinvoice/elasticsearch
volumes:
- $PWD:/app
@mattes , acredito que já seja suportado, acho que .:/app
é suportado
@aanand Como um PoC, fiz um hackup sujo do POSIX PE em Python . Para os sábados.
@kojiromike Parece ótimo. Deixe-me saber se você pretende continuar com isso.
@aanand eu pretendo, mas definitivamente tem alguns bugs (e eu acho que pode ter sido uma má ideia usar shlex
). Relatórios de bugs e PRs são bem-vindos, é claro.
@dnephin que tal $HOME
/ ~
?
@nafg Ambos são suportados para o caminho do host de um volume
@dnephin interessante, b / c de alguma forma acabei com um diretório chamado '$ HOME' ...
@aanand Como a proposta "$ { VARIABLE: default }", com global_extends (ou "import") isso se tornaria bastante poderoso.
P: Isso permitiria especificar o número da porta que é exposta ao host? como - "$ {WEB_ PORT: 80 }: 80"?
O caso de uso é ser capaz de ativar facilmente várias instâncias de um aplicativo na mesma máquina / cluster, geralmente escutando portas diferentes ou atribuídas a diferentes nomes de domínio locais.
Sim, você seria capaz de fazer isso.
Eu gostaria de usar vars em volumes junto com docker-compose scale my_app=3
. Eu tenho este docker-compose.yml
server:
image: alexanderilyin/docker-teamcity-server
ports:
- "8111:8111"
volumes:
- .TeamCity:/root/.BuildServer
links:
- mysql
mysql:
image: alexanderilyin/docker-mysql
volumes:
- .MySQL:/var/lib/mysql
environment:
MYSQL_DATABASE: teamcity
MYSQL_USER: teamcity
MYSQL_PASSWORD: teamcity
MYSQL_ALLOW_EMPTY_PASSWORD: yes
agent:
image: alexanderilyin/docker-teamcity-agent
links:
- server
E eu quero poder usar scale
para agentes e usar volumes dinâmicos para eles manterem os dados entre os lançamentos, por exemplo:
agent:
image: alexanderilyin/docker-teamcity-agent
volumes:
- .agent_{$AGENT_INSTANCE_ID}:/opt/buildAgent
links:
- server
Espero que seja possível interpolar variáveis como parte do nome da imagem também
Estamos usando https://github.com/openshift/source-to-image para construir um contêiner local em CI para cada branch e, em seguida, executar testes nele usando docker-compose.
A execução de testes com imagem dinâmica é bastante complicada com docker-compose e requer a renderização manual do modelo ..: -1:
Mas você pode definir COMPOSE_PROJECT_NAME
para controlar o prefixo por execução para poder fazer isso certo? Em caso afirmativo, não há necessidade de lógica complexa e arquivos yml ilegíveis em torno dos nomes.
@andrerom não segue. De acordo com a documentação que controla o seguinte Sets the project name, which is prepended to the name of every container started by Compose
enquanto tentamos definir uma propriedade de imagem:
web:
image: <I_AM_DYNAMIC>
ah, erro meu.
Pensei que você quisesse dizer
<I_AM_DYNAMIC>:
image: nginx
A referência dinâmica de imagem (e construção) realmente faria muito sentido. Por exemplo, alternar entre contêineres base de depuração e não depuração para sua linguagem de programação, por exemplo, seria um bom caso de uso para isso.
Caso de uso adicional _ (que pode ser o que @ Maxim-Filimonov tem em mente) _: Ser capaz de sobrescrever qual tag usar de uma imagem, então você pode usar: mais recente por padrão, mas mudar para testar facilmente outra coisa sem alterar yml arquivo _ (necessário para casos de uso de CI basicamente) _.
@andrerom esse é exatamente nosso caso de uso: +1:
Isso também funcionará para coisas como ??
web:
environment:
- FOO=${whoami}
@ k0377 Eu não acho que eles vão, porque isso é realmente algo que é tratado pelo shell, mas você pode adicionar o resultado em uma variável de ambiente e usar isso.
Neste caso particular, a variável de ambiente $USER
provavelmente fornecerá o mesmo.
@aanand Por que não usar qualquer um dos mecanismos de modelo existentes que já estão presentes? Jinja2 está lá e funciona bem.
Como mencionado antes - implementar nosso próprio template não é uma tarefa trivial (e regexps não são tão legais), então devemos usar um já existente, que provou ser sólido.
Como alternativa, podemos usar ancors e referências YAML https://gist.github.com/bowsersenior/979804
Mas então estamos limitados no uso de variáveis (injete o nome da variável no meio do conteúdo).
1 para Jinja2: certamente se encaixaria no molde e a ansible o usa para
exatamente esse caso de uso (modelagem em arquivos yml)
Na terça-feira, 26 de maio de 2015 às 13h25, tonnzor [email protected] escreveu:
@aanand https://github.com/aanand Por que não usar qualquer um dos modelos existentes
motores que já estão presentes? Jinja2 está lá e funciona bem.Como mencionado antes - implementar nossos próprios modelos não é uma tarefa trivial
(e regexps não são tão legais), então devemos usar um já existente,
que provou ser sólido.-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105493447.
Jinja2 faz _muito_ mais do que precisamos:
Não estamos adicionando nada disso ao Compose. Se Jinja2 puder ser configurado para apenas interpolar variáveis, então ele pode ser um candidato.
Na verdade, fazer um loop pode ser interessante.
Suponha que você tenha uma lista de clientes para os quais deseja iniciar contêineres
onde você coloca algumas variáveis específicas do cliente no ambiente.
Extensão / Herança pode ser interessante para melhorar o atual
mecanismo de extensão rudimentar.
Filtros podem ser ótimos para fazer algo com variáveis existentes.
Na terça-feira, 26 de maio de 2015 às 13h56, Aanand Prasad [email protected]
escrevi:
Jinja2 faz _muito_ mais do que precisamos:
- condicionais
- looping
- extensão / herança
- comentários
- filtros
Não estamos adicionando nada disso ao Compose. Se Jinja2 pode ser configurado
para apenas interpolar variáveis, então pode ser um candidato.-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105498909.
Eles _podem_ ser recursos interessantes, mas vêm com muito mais complexidade do que me sinto confortável em apresentar o Compose e o formato de arquivo, e estaríamos vinculando ambos a uma linguagem de modelo específica com (até onde eu sei) uma única implementação e nenhuma especificação. Simplesmente não é viável.
@aanand Algumas notas aqui:
from jinja2 import Template
template = Template ('Olá {{name}}!')
template.render (name = "Aanand")
Hello Aanand!
Se você quiser mais segurança, pode usar o sandbox imutável:
from jinja2.sandbox import ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Olá {{nome}}!')
template.render (name = "Aanand")
Hello Aanand!
No nosso caso seria:
importar os
from jinja2.sandbox import ImmutableSandboxedEnvironment
env = ImmutableSandboxedEnvironment ()
template = env.from_string ('Olá {{nome}}!')
template.render (** os.environ)
- Não queremos filtros? Com o filtro, você pode definir o valor padrão facilmente ({{value | default ("default")}})
- Precisamos realmente nos preocupar com os usuários que usam recursos estendidos do Jinja para danificar o arquivo YAML? Da mesma maneira, o usuário pode produzir um arquivo YAML inválido manualmente. Acho que devemos mantê-lo simples - tente processar determinado modelo Jinja e retornar o erro se houver um erro ou se o YAML produzido for inválido (o mesmo que você faz agora).
- Se você não vê Jinja2 como solução - seria ótimo, pelo menos, usar {{variable}} como sintaxe.
- Django usa regexp para analisar e gerar template. É de qualidade de produção por um longo tempo e vive bem com ele.
importar os
importar re
template = "Olá {{name}}!"
re.sub ("{{\ s _ ([a-zA-Z0-9 _] +?) \ s_}}", lambda m: os.environ.get (m.group (1), ''), modelo)
Em qualquer caso - precisamos ter esse recurso funcionando, seja qual for a solução que escolhermos.
Estou com +1 sobre como usar uma solução de modelo genérico se os modelos forem considerados. Por exemplo, http://mustache.github.io , que está disponível em vários idiomas. Este é apenas um exemplo, outros motores de modelos podem ser considerados igualmente
@aanand eu entendo totalmente seu ponto. Eu também gosto da simplicidade e
sucinto do dsl composto.
Talvez isso deva ser feito como um projeto externo, digamos, meta-compositor. isto
pega um compose.tpl.yml e um variables.yml, cria um docker-compose.yml
e lá vamos nós.
Como @tonnzor mostrou, isso poderia ser feito com um pequeno pedaço de código python.
Isso proporcionaria modelos poderosos para aqueles que precisam sem
introduzindo complexidade para tarefas simples.
Na terça-feira, 26 de maio de 2015 às 16:52, Sebastiaan van Stijn <
notificaçõ[email protected]> escreveu:
Estou com +1 em usar uma solução de modelo _generic_ se os modelos
considerado. Por exemplo, http://mustache.github.io , que está disponível em muitos
línguas. Este é apenas um exemplo, outros motores de modelos podem ser
considerado igualmente-
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.
Hmm ... Então é a proposta agora de usar uma linguagem de modelos dentro de compose.yml (que é uma linguagem descritiva para compor containers Docker), para coisas como command
e entrypoint
, que já aceitam ambos exec
e sh -c
valores de estilo? Isso pode ser confuso, já que após a renderização do modelo, o comando shell resultante ainda seria interpretado, portanto, se uma variável se expandisse para *
ela seria posteriormente expandida. Escapar sequências em um idioma ou outro torna-se complicado quando você tem tantas camadas de interpretação incompleta.
@kojiromike Não tenho certeza se um motor de template é desejado, mas se for para ser usado! melhor usar algo bem conhecido. A questão básica é; deve docker-compose escrever a substituição do zero ou usar algo existente.
Em Ter, 26 de maio de 2015, 11:02 Christoph Witzany [email protected]
escrevi:
@aanand eu entendo totalmente seu ponto. Eu também gosto da simplicidade e
sucinto do dsl composto.
Talvez isso deva ser feito como um projeto externo, digamos, meta-compositor. isto
pega um compose.tpl.yml e um variables.yml, cria um docker-compose.yml
e lá vamos nós.
Você pode fazer isso hoje, sem nenhum novo projeto. Tenho certeza que jinja pode ser
invocado da linha de comando de alguma forma. Pessoalmente, eu só uso o envsubst
comando.
O que seria realmente útil é se o compose pudesse ler o arquivo de stdin.
Isso eliminaria a necessidade de um arquivo intermediário.
Como @tonnzor mostrou, isso poderia ser feito com um pequeno pedaço de código python.
Isso proporcionaria modelos poderosos para aqueles que precisam sem
introduzindo complexidade para tarefas simples.
Na terça-feira, 26 de maio de 2015 às 16:52, Sebastiaan van Stijn <
notificaçõ[email protected]> escreveu:
Estou com +1 em usar uma solução de modelo _generic_ se os modelos
considerado. Por exemplo, http://mustache.github.io , que está disponível em muitos
línguas. Este é apenas um exemplo, outros motores de modelos podem ser
considerado igualmenteResponda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105551631.
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/compose/issues/1377#issuecomment -105554730. src = "
https://ci6.googleusercontent.com/proxy/iSBXyl7D8PwFM4p1mGPHCR7bQctunieGbhyGkvo0QIMIjmAYE3I0Mt96yl1fGrqcuOzxV4APP8ZRIw-5_qd6nzps9Mpr6jTAydCC4xs8JDgqm93aIbWvN1eMlxykrz7iwYooyAQdqL4RFJokeEbnBkZm5mhgKg=s0-d-e1-ft#https://github.com/notifications/beacon/AAGAUO8xqz29B2SUoG7QFPUy848_JJW9ks5oNIJlgaJpZM4EMysO.gif
">
1 para ler o arquivo de stdin. Não tenho nenhum problema em usar uma solução de modelo externo, mas não ter arquivos intermediários por perto seria bom.
Isso parece um ótimo primeiro passo e uma característica comum de muitas ferramentas CLI. Vamos fazer isso
: +1:
Então por exemplo
envsubst compose.tmpl.yml | docker-compose -f - up -d
wfm. : +1:
Acabei de notar que docker / distribution lida com valores de substituição no arquivo yml por meio de variáveis de ambiente, mas usando uma abordagem diferente https://github.com/docker/distribution/blob/master/docs/configuration.md#override -configuration-options
^^ @aanand
@thaJeztah isso funcionaria para nós também. Podemos usar variáveis de ambiente para substituir comandos, então
DOCKER_COMPOSE_IMAGE_NAME='my_image:is_dynamic'
Abordagem interessante, mas não sou um fã - nomes de variáveis de ambiente detalhados, muita duplicação se você quiser usar um valor em vários lugares, tudo está implícito, sem interpolação dentro de strings.
@aanand também não
Acabei de tropeçar em https://github.com/kelseyhightower/confd que pode ser do seu interesse. Ele usa http://golang.org/pkg/text/template/#pkg -overview
@olalonde infelizmente, docker-compose é escrito em Python, então Go-templates não funcionam.
@aanand eu sou +20 em sua proposta original, com o ajuste que mesmo imagens e especialmente tags devem ser possíveis de injetar. Simplesmente vá em frente, economizaria muitos invólucros e manipulação desnecessária de configurações;)
Eu escrevi um pequeno pacote python que me ajuda com isso. O plano é fazer um túnel de todos os comandos para o docker compose para que você possa usá-lo de forma equivalente.
Confira em https://github.com/webcrofting/meta-compose/
meta-composição parece muito bom. Deve ser integrado ao docker-compose!
Grande +1 aqui - não estou entusiasmado com o pré-processamento de modelos, mas puxar variáveis de ambiente de uma forma ou de outra seria ótimo. A expansão POSIX é provavelmente mais limpa do que Jinja2, mas de qualquer forma é bom.
Grande +1 daqui também. Meu caso de uso é mais para adicionar suporte de ID de publicidade dinâmica para contêiner kafka, que é vital para produtores de dados (que podem ser outros contêineres).
Também estou animado com esse recurso.
A expansão POSIX é provavelmente mais limpa do que Jinja2, mas de qualquer forma é bom.
Acho que outro argumento a favor da expansão POSIX é que ela não tem lógica. O Jinja2 suporta algum grau de lógica condicional / de loop (como a maioria dos motores de modelos fazem, mesmo aqueles que afirmam ser "sem lógica"). Misturar lógica de modelos e YAML é muito estranho na minha experiência. Alguém pode pensar em um caso de uso para tal lógica? Caso contrário, pode ser melhor evitar especificamente o suporte por enquanto.
Seria bom ter uma resposta clara dos desenvolvedores sobre esse recurso. Lendo várias questões e RP, não fica claro se você realmente deseja implementá-lo ou não.
Se sim, com que tipo de mecanismo? Caso contrário, as pessoas podem começar a construir algumas ferramentas de terceiros para gerenciar o recurso.
Obrigado !
Ok, acabei de ver https://github.com/docker/compose/pull/76. Acho que a resposta está aí ...
Percorreu alguns ciclos sobre as questões / RPs vinculadas.
AFAIK, a comunidade nginx se recusou a adotar qualquer mecanismo de modelo para arquivos de configuração, mesmo para uma substituição de variável simples. Por quê? Talvez eles ainda estejam escolhendo um mecanismo de template ideal: smile :
@hadim
Lendo várias questões e RP, não fica claro se você realmente deseja implementá-lo ou não.
Esse problema deveria fornecer a resposta definitiva para essa pergunta, então, sinto muito não ter sido claro: sim, queremos implementá-lo e com uma sintaxe no estilo POSIX.
obrigado @aanand !
Obrigado, @aanand.
1 para mim. Preciso passar --dns = (endereço da ponte docker0) e preciso que funcione se isso mudar em versões futuras do docker, portanto, uma variável de ambiente e / ou shell é perfeita. meta-compose não funciona para mim, pois deve suportar DOCKER_HOST remoto e, por exemplo, via docker-swarm, não apenas localmente.
: +1: Isso seria muito bom. Atualmente, ou acabo gerando o arquivo .yml por meio de outro script ou simplesmente não estou usando docker-compose completamente e - vinculando dockers manualmente.
:afirmativo:
Acho que a interpolação básica de variáveis de ambiente seria muito útil para coisas simples.
Alguns casos de uso simples:
Ferramentas como o Ansible já fazem modelos muito bem, então não tenho certeza se um mecanismo de modelo completo é necessário. Mas não poder ter nenhum conteúdo dinâmico no arquivo comose.yml é muito limitante.
Com relação ao PR # 1488 mesclado, estou particularmente interessado em enviar um arquivo de configuração para docker-compose
. Não consigo entender por que docker-compose
não pode pegar de um processo de nó.
var spawn = require('child_process').spawn;
var compose = spawn('docker-compose', ['--file' + '-' + 'up']);
compose.stdin.setEncoding = 'utf-8';
compose.stdout.on('data', function (data) {
console.log('"docker-compose --file - up" stdout: "%s".', data);
});
compose.stderr.on('data', function (data) {
console.log('"docker-compose --file - up" returned an error: "%s".', data);
});
compose.on('close', function (code) {
if (code !== 0) {
console.log('"docker-compose --file - up" existed with an erroneous code: "%s".', code);
} else {
console.log('"docker-compose --file - up" existed with code: "%s". SUCCESS!', code);
}
});
compose.stdin.write("redis: {\"image\": \"redis\"}\n");
compose.stdin.end();
Algum exemplo de como canalizar dados do Node.js?
Outra coisa que descobri é que docker-compose
1.4.0-RC1 está enviando algumas mensagens aparentemente normais como Starting...
ou Attaching...
para stderr
vez de stdout
.
@kadishmal Você poderia abrir edições separadas para eles, por favor?
Outra sugestão de sintaxe / implementação: o modelo de string do Python, conforme especificado no PEP 0292 e implementado no string.Template .
É muito semelhante à expansão do parâmetro POSIX:
$foo
expande para o valor de foo
${foo}
expande para o valor de foo
$
, ${
, $}
, ${}
, ${foo
, $ {foo}
, ${ foo}
, ${foo }
são errosDesvantagens:
$$
vez de \$
.Isso pode realmente ser uma bênção disfarçada: YAML não gosta de \$
e requer que você escape duas vezes. Eu não acho que dizer às pessoas para digitar \\$
apenas para obter um cifrão vai funcionar.
Eu detectei uma implementação em # 1765.
+1
Não tenho certeza se este é o lugar certo para isso, ou se devo fazer uma nova edição.
Acho que a precedência de env deve ser o contrário, ou seja, uma variável do shell que invoca docker-compose deve substituir qualquer variável dentro de docker-compose.yml, que por sua vez deve substituir qualquer variável definida pelo contêiner.
Aqui está o que acontece atualmente quando eu tento:
docker-compose.yml:
test:
image: ubuntu
environment:
- FOO="from compose"
e então execute-o com o comando env
:
docker-compose run test env | grep FOO
dá FOO="from compose"
, como esperado. Mas então:
FOO="from shell" docker-compose run test env | grep FOO
também dá FOO="from compose"
, mas aqui eu esperava FOO="from shell"
.
Algumas pessoas ainda podem precisar de interpolação de variável para outros casos de uso, mas alterá-la satisfaria o caso "padrão" - efetivamente a environment:
definição / valor em docker-compose.yml é o padrão e pode ser substituído em tempo de execução, se necessário, sem a necessidade de qualquer sintaxe YAML extra.
@fazy você não levou em conta que o comando env
foi executado no contêiner test
isolado no qual o FOO
é from compose
(apenas como deveria ser e como foi configurado em um arquivo docker-compose
). Mas fora desse contêiner se docker-compose
processo tivesse algum tipo de função de impressão para a variável de ambiente que você configurou antes do comando, ele teria impresso 'do shell' porque é o valor para o host (bem como para o processo docker-compose
) em que você está executando. Talvez você estivesse esperando que o FOO
fosse from shell
neste caso, mas pessoalmente eu ficaria muito surpreso se fosse. (Espero que, apesar do meu inglês, você compreenda meu ponto).
@smileart obrigado, acho que entendo o que você está dizendo.
No entanto, o contêiner test
não está completamente isolado, ele obtém seu ambiente de docker-compose
(ou pelo menos, docker-compose é capaz de definir variáveis de ambiente no contêiner iniciado) e docker-compose em si pode ver a variável de ambiente "externa".
Você pode ver com este docker-compose.yml:
test:
image: ubuntu
environment:
- FOO
Então o comando:
FOO="from shell" docker-compose run test env | grep FOO
realmente dá o resultado "do shell".
Portanto, minha pergunta é sobre precedência. Especificando apenas o nome da variável aqui, - FOO
, posso injetar a variável de fora. Mas se eu especificar - FOO=something
_and_ injetar uma variável de fora, qual deve ter precedência? IMHO a variável especificada na linha de comando deve ter precedência sobre o arquivo de configuração.
@fazy Oh, desculpe, eu não tentei FOO="from shell" docker-compose run test env | grep FOO
sem especificar seu valor em docker-compose.yml
e eu não sabia que isso nos dá o FOO
do host. Então não seria apenas estranho para mim: smiley: Eu pensei que configurar uma variável de ambiente antes de docker-compose
influenciaria em docker-compose
e docker-compose
SOMENTE sem jogá-la no recipiente. Agora eu vejo o que você quis dizer.
Acabei de descobrir a desvantagem de escapar de $
mencionado em https://github.com/docker/compose/issues/1377#issuecomment -124571722. Primeiro eu fiz apenas FOO=ba$e
depois FOO='ba$e'
(esquecendo que é considerado "puro"), depois FOO=ba\$e
, depois FOO=ba\\$e
, desisti e fui para os documentos, apenas para ficar surpreso ao descobrir que " $
é o caractere de escape para $
". Para mim, isso não foi particularmente "menos surpresa".
Porém, não sei qual seria a boa solução.
@ ct-clearhaus Compose não é o único programa que usa $
para escapar $
. Você também encontrará isso em makefiles. Portanto, para algumas pessoas, esse idioma é bastante familiar.
Eu amo a implementação de substituição de variável existente. No entanto, eu realmente poderia usar a capacidade de definir um padrão, de acordo com a proposta original de
${ENV-default}
Meu uso específico é poder especificar a porta do host em que o serviço é executado:
PORT=8123 docker-compose up
Adicionando isso ao meu docker-compose.yml
:
web:
ports:
- "${PORT-8000}:5000"
Este recurso ainda está planejado e em desenvolvimento?
Tentei resolver meu problema com extensões , mas ficou muito confuso. Não apenas tive que duplicar quase todas as minhas docker-compose.yml
apenas para alterar uma configuração, também não há como _alterar_ uma configuração de porta exposta, você pode apenas add to
a lista de portas expostas, que não é ideal para mim.
Por que docker-compose não falha quando as variáveis de ambiente não estão definidas? Ele apenas registra um aviso e continua. Não seria apenas retornar e errar uma abordagem melhor ...
WARNING: The FOO variable is not set. Defaulting to a blank string.
1 para sintaxe POSIX para declarar valores padrão
Talvez esteja faltando algo óbvio, mas gostaria de poder usar variáveis de ambiente de um env_file para definir o valor de uma variável de ambiente, por exemplo:
docker-compose.env:
DB_PASSWORD=test
docker-compose.yaml:
...
service:
database:
env_file:
- ./docker-compose.env
environment:
- MYSQL_PASSWORD=${DB_PASSWORD}
webserver:
env_file:
- ./docker-compose.env
environment:
- WORDPRESS_DB_PASSWORD=${DB_PASSWORD}
Isso poderia ser realizado de alguma outra maneira? Não quero ter um arquivo de modelo yaml que precise ser canalizado por meio de envsubst.
Por que não colocar esse valor diretamente em env_file
do jeito que você quiser?
Isso significaria ter uma variável que deve ter o mesmo valor em dois lugares, torna mais fácil se você só precisar alterar um. # 2636 parece promissor.
Precisamos desesperadamente de um mecanismo para suportar variáveis padrão agora, pois as limitações existentes nos forçam a usar scripts de wrapper para ajudar docker-compose. Preciso de coisas como NODE_ENV=${NODE_ENV:-dev}
para funcionar e, por conveniência, seria bom ter SOME_NUMBER=$((96*60))
para funcionar. Isso estava programado para uma versão futura?
+1 para valores padrão
+1 para valores padrão. isso está se tornando crítico para nós.
Concordo @ darkn3rd - preciso obter o ID do usuário e o ID do grupo de usuários para configurá-los no contêiner. A única maneira que encontrei é forçar minha equipe a exportar 2 vars ... ou usar um makefile que fiz para exportá-los.
Se eu pudesse fazer:
user: $((id -u)):$((id -g))
isso vai resolver todos os meus problemas
@mgor Parece que você poderia simplesmente passar por envsubst
?
env $(cat docker-compose.env | xargs) envsubst < docker-compose.tmpl > docker-compose.yml
deve fazê-lo (sem poluir o ambiente persistente), eu acho.
@OJFord @mgor Sem intenção de roubar o thread, mas desenvolvi algumas ferramentas CLI para ter um fluxo de trabalho mais limpo; envset e slv .
envset development -- slv docker-compose.tpl > docker-compose.yml
envset carregará variáveis de um arquivo env na sessão shell atual, slv substitui o modelo usando variáveis ambientais.
Eu concordo com @OJFord mas não é disso que preciso ...
Deixe-me ser mais preciso: somos uma equipe de 40 desenvolvedores que usa uma pilha docker-compose diferente. Estamos usando git para obter o código.
Se eu pedir a eles para modificar docker-compose.yml que é entregue por nosso git, então tenho certeza que alguém enviará um arquivo docker-compose.yml modificado ... Confie em mim, esse será o caso.
Posso "gerar um arquivo base composer" que é ignorado por git e estendido por docker-compose.yml, mas para gerá-lo vou precisar dar a eles um Makefile ou um bashscript ... Chegará o dia em que " a mudança do arquivo docker "será necessária e a equipe não saberá que será necessário executar novamente a geração.
O mesmo para um arquivo "env", que é muito bom, mas não funciona com "build" e preciso pedir à minha equipe para gerar este arquivo.
Realmente, se docker-compose puder obter valores de bash (ou qualquer outra solução que retorne algo que uma var ENV) no arquivo yaml resolverá muitas necessidades.
Meu exemplo em meu comando anterior é perfeito: eu preciso obter a id do usuário e gid e esses valores não são definidos por ENV vars. Portanto, preciso pedir à minha equipe que escreva suas identidades em um arquivo .env ... Simples para mim e para você, não para todos.
Para ser mais preciso: preciso fornecer um arquivo docker-compose que não deve ser alterado pela equipe, porque está em um repositório git.
Este pull-request é um exemplo simples que funciona para mim. Talvez você possa me ajudar a fazer melhor.
Tentei com as diretivas de ambiente e de usuário do arquivo docker-compose.yml. Funciona bem por enquanto.
O valor padrão deve estar lá ... Muito útil ... Desenvolvedores e OPS estão usando os logs do docker ou syslog ... Então, eles geralmente precisam criar o LOG_FORMAT padrão mostrado abaixo ... Poderíamos apenas ter o valor padrão e só usá-lo ao mudar para o syslog ...
default:
extends:
file: base.yml
service: base-${LOG_FORMAT:docker}
labels:
- "net.company.npmjs.datacenter=${DATA_CENTER}"
- "net.company.npmjs.env=${ENV}"
- "net.company.npmjs.hostname=${HOSTNAME}"
- "net.company.npmjs.role=${NPMO_ROLE}"
- "net.company.npmjs.log=${LOG_FORMAT}"
base-syslog:
log_driver: syslog
log_opt:
tag: "{{.ImageName}}/{{.Name}}/{{.ID}}"
base-docker:
log_driver: json-file
log_opt:
max-size: "128m"
max-file: "4"
Quando isso estará disponível? Estou no Compose 1.7.0 e ainda não está lá :(
Por favor, forneça os valores padrão!
@marcellodesales : Talvez você possa tirar vantagem de usar um arquivo docker-compose.override.yml
alguma forma. Verifique esse recurso.
Também +1 em env vars. É nosso maior problema com docker-compose hoje em dia.
Eu insistiria em meu PR # 3367 para poder obter certos valores do host. :)
@pataquets Acho que não quero criar outro arquivo de substituição ... nosso arquivo base.yml
, como mostrado acima, mostra todas as coisas suportadas em termos de driver de logger, etc ... Eu só quero mudar e têm valores padrão. Eu acho que precisaríamos manter ainda mais arquivos yml. Mas vou manter isso em mente para o caso.
+1
+1
+1
+1
Qualquer aviso sobre o uso de variáveis de ambiente em docker-compose?
+1
+1
FYI: Vars de ambiente para docker-compose funciona a partir de 1.7.0. Você também pode definir variáveis padrão docker-compose em .env
no mesmo diretório do arquivo raiz docker-compose.yml
. Isso não deve ser confundido com os envfiles do docker, já que é uma coisa diferente.
Existe uma maneira de definir o nome do serviço como uma variável?
Em vez de escrever isso
services:
site_db:
image: mysql:5.7
Poderíamos escrever
services:
${CONTAINER_NAME}:
image: mysql:5.7
Meu objetivo é manter o mesmo docker-compose.yml
em vários sites e apenas alterar o arquivo .env
. No momento, ainda preciso modificar o nome do contêiner porque estou executando vários aplicativos no mesmo host. E gostaria que cada serviço tivesse seu próprio nome para maior clareza.
@LouWii você pode usar
services:
site_db:
container_name: "${CONTAINER_NAME}"
image: mysql:5.7
ou (formato de arquivo de composição 2.1 e superior)
services:
site_db:
container_name: "${CONTAINER_NAME:-defaultname}"
image: mysql:5.7
Mas por que não definir o nome do projeto? O nome do projeto é _intendido_ para isso, uma vez que ele prefixa / coloca nomes de contêineres que são criados para evitar conflito com outros projetos no mesmo host. Consulte https://docs.docker.com/compose/reference/envvars/#/composeprojectname
@thaJeztah Obrigado! Ainda estou aprendendo como o Docker e a composição do docker funcionam. Definir o nome do projeto parece ser a melhor opção, faz todo o sentido no meu uso.
Existe alguma maneira de fazer o script dentro das chaves interpoladas? Por exemplo ${HOST_PORT + 1}
.
Você pode canalizar o arquivo através do Jinja ou algo assim ...
Em Ter, 24 de janeiro de 2017, 5:36 AM Sam A. Horvath-Hunt [email protected]
escrevi:
Existe alguma maneira de fazer o script dentro das chaves interpoladas? Por exemplo $ {HOST_PORT
- 1}
-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/compose/issues/1377#issuecomment-274767368 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/AAGAUN5ZrU39dnVVVASwIHr5mGqJFxh3ks5rVdRIgaJpZM4EMysO
.
Consigo escapar de $
?
environment:
PATH: "$PATH:/home/appuser/.bundler/bin"
Atualmente, isso resulta na variável PATH do host sendo interpolada e não no contêiner
é um arquivo docker-compose.yml encontrado apenas um?
como posso adicionar ou modificar?
desde já, obrigado
@logicminds embora eu não conseguisse encontrar documentado em lugar nenhum, encontrei $$
interpola para um $
com escape.
environment:
PATH: "$$PATH:/home/appuser/.bundler/bin"
@elquimista tem uma solução que achei útil https://github.com/mhart/alpine-node/issues/48#issuecomment -430902787
Comentários muito úteis
Meu caso de uso é permitir
$PWD
emvolumes
, para que cada desenvolvedor da equipe possa clonar um repositório para qualquer lugar e os caminhos ainda sejam montados corretamente.