Moby: Adiciona suporte para o recurso `extends` no Compose v3 / docker stack deploy

Criado em 16 fev. 2017  ·  165Comentários  ·  Fonte: moby/moby

Como pode ser visto em https://github.com/docker/compose/issues/4315 , o recurso extends que existe em docker-compose parece ser popular entre os usuários, apesar de suas falhas. No entanto, até agora não foi adicionado na implementação do Engine do formato Compose. Até agora, aconselhamos os usuários a simplesmente nivelar a estrutura de arquivos do Compose ao usar a v3, mas essa é a solução de longo prazo que queremos? Como podemos fornecer um caminho de atualização claro para os usuários que passaram a contar com esse recurso?

cc @dnephin @vdemeester

arestack kinfeature

Comentários muito úteis

Não apenas isso, mas o changelog diz "isto foi removido, veja 'como atualizar' para detalhes". Eu vejo "como atualizar" para, você sabe, detalhes sobre como atualizar, e o que isso diz é "ver 'extensão de serviços' para detalhes". Eu vou para "estendendo serviços" imaginando que finalmente verei uma maneira de estender meus arquivos, apenas para ver "isso foi removido, consulte o changelog para detalhes".

Nesse ponto, parece uma piada cruel que o redator da documentação está pregando.

Todos 165 comentários

Eu adicionei algumas notas https://github.com/docker/compose/issues/4315#issuecomment -280617251 para mim trazer de volta extends como ele existe até docker compose file versão 2.1 não é uma boa ideia, mas o principal recurso. miss é ser capaz de declarar serviços abstratos (que nunca devem ser executados, mas podem ser usados ​​para agrupar propriedades comuns de serviços por conveniência).

Concordou nos comentários do docker / compose # 4315 que a maneira extends funcionava era um pouco espartana.

Não vou recomendar uma solução, mas FWIW, para mostrar a extensão do abuso, aqui estão as convenções que adornam o topo do nosso arquivo de composição:

#
# Docker Compose configuration
#
# Due to lack of "expressivity" in Compose, we define our own couple of service
# "pseudo-types":
#
#   - image-only services (name: *-image)
#
#     The only goal of these is to build images. No other services build images.
#
#     These have entrypoint overridden to exit immediately.
#
#   - base services (name: *-base)
#
#     These contain common configuration and are intended to be extended.
#
#     Their command (not entrypoint, to keep the original one) is overridden to
#     exit immediately. Service must support a command to exit immediately.
#
#   - task services (name: *-task)
#
#     These are intended for running one-off commands.
#
#     Their default command is overridden to exit immediately. Service must
#     support a command to exit immediately.
#
#   - "real" services
#
#     These are actual services that stay up and running.
#
version: '2'
services:
  ...

Eu acho que estende como na v2.1 é uma boa escolha. Extends é realmente simples e compreensível, esta é uma boa prática para cada ambiente ter uma pequena transformação legível entre dev, prod e env.

Na verdade, eu tenho

  • um arquivo docker-compose comum que apresenta as regras básicas
  • um dev docker, estendendo-o e com recursos para o desenvolvedor
  • um docker de encenação composto de extensão comum também e com facilidades para este ambiente
  • uma docker de produção extensível também comum e com facilidades para este ambiente, especialmente replicação de container, regras de reinicialização, etc ...

Isso funciona, e não entendo por que devemos buscar neste ticket uma reescrita completa, mas mais para manter uma característica interessante. Extends é uma boa parte com casos de uso especiais que outras técnicas não podem resolver facilmente. Estou feliz com amplia possibilidades.

Nos impedindo de atualizar para o formato v3.x também.

Mantemos nossas definições de contêiner do docker em um layout de pasta por instância, onde cada pasta contém um docker-compose.yml que define as especificações do env para a instância do contêiner em questão. Para fatorar o material comum (DRY), usamos definições de serviço básicas em uma pasta pai e usamos extend .

Então, quando eu preciso gerenciar uma instância de contêiner específica, eu só preciso cd na pasta certa e posso, então, executar diretamente os comandos docker-compose sem configuração adicional (nenhum sinalizador -f exigia que os membros da equipe precisa pesquisar ou saber, funciona conforme o esperado fora da caixa).

Estou impedido de usar arquivos de composição da versão 3.

Eu uso services.yml para definir o layout base dos meus serviços e, em seguida, estendo-o com dev.services.yml para o meu ambiente de desenvolvimento (principalmente adicionando volumes), mas eu gosto da reutilização (SECA) de extensões quando era adicionado. Não é um problema, mas me impediria de mudar para a versão 3, a menos que haja um recurso obrigatório.

Não sou contra o aprimoramento da solução v2.1 'extends' com algo mais apropriado. Algo como serviços abstratos pode ser mais seguro de usar e mais poderoso.

Por exemplo (já que é abstrato), eu poderia imaginar o suporte a volumes / pontos de montagem / redes abstratos, onde o serviço de base abstrato define um ponto de montagem local ou uma rede necessária para um serviço, sem definir a parte do host - o que significa que um serviço derivado poderia então definir / mapeie a parte do host das montagens / volumes e redes para o que for apropriado em seu ambiente de host / estágio.

Esse é um exemplo de algo que não podemos fazer agora com 'estende', pelo que eu sei, e abriria algumas possibilidades interessantes.

Tirar o recurso de extensões não foi útil em nada. Temos muitos serviços da web iniciados com os mesmos volumes mapeados, variáveis ​​de ambiente e rótulos definidos. Eles também têm as mesmas políticas de verificação de integridade. E sem falar nas portas. Combinar arquivos de composição usando várias opções -f é entediante e sujeito a erros se você estiver lidando com vários projetos no mesmo host.

@ shin- isso será trazido de volta no esquema 3.2?

Eu realmente adoraria colocar extends volta no formato de arquivo. Tenho usado-o para refinar ainda mais os serviços abstratos para vários projetos. Eu entendo que várias opções de -f se enquadram quase no problema, mas nem sempre funciona. Por exemplo, muitas vezes mudo o nome do serviço abstrato para algo que seja mais significativo no contexto do projeto em questão. Isso é algo que a substituição que ocorre com várias opções -f não suporta.

Eu não me importaria de perder o extends exato, contanto que haja alguma outra maneira de "instanciar" um serviço abstrato em um arquivo.

Eu tenho uma configuração com um arquivo de serviço comum e vários serviços estendendo-o, alterando principalmente os volumes, então eu diria que conto com o recurso extends e não vejo outra boa maneira de descrever minha configuração.

--frustrated

+1
Posso ver a lógica por trás da recomendação de simplificar arquivos docker-compose, mas não gosto da ideia de duplicar o código que define nossa topologia de serviço de desenvolvimento em vários projetos. Usaremos a solução alternativa -f por enquanto, com scripts de shell para que os desenvolvedores não tenham que lembrar quais serviços incluir em quais casos.

Espero que uma solução satisfatória possa ser encontrada aqui para permitir uma melhor fatoração das estruturas compostas!

No topo da minha lista de casos de uso está DRYup meu estoque de serviços gerenciado por configuração. Achei que seria capaz de tirar proveito de 'estende' se v3. Não quero voltar para a v2 ... e não quero ter casos especiais em que devo usar a solução alternativa do processo -f.

Ei, alguém começou a trabalhar nisso? Não consigo encontrar um PR para acompanhar. Isso simplificaria muito algumas coisas para nós aqui também (caso de uso muito semelhante a alguns descritos acima).

Uma vez que a versão 3 está congelada e eu precisava de uma forma de compartilhar a configuração comum, hackeei uma pequena solução alternativa, que acho que poderia compartilhar aqui (não tenho certeza se este é o lugar certo, mas sinta-se à vontade para me dizer onde mais posso compartilhe esta informação :))

Não vou entrar em detalhes aqui, já que há um leia-me no repo.
Tenham um bom dia, pessoal ☮️

Editar:

Desculpe, aqui está o link: D

+1

+1

+1

Obrigado pelos + 1s 💃
Nesse ínterim, encontrei outra imagem do docker noop , que é menor por um fator de 10 ^ 3 (devido ao noop real sendo escrito em assembly).

Infelizmente, não há licença nesse repo. Já escrevi uma mensagem para o dono no facebk mas ele ainda não respondeu. Talvez ele adicione uma licença se mais pessoas o questionarem sobre isso :)

Algo que pode ajudar alguns dos casos de uso estendidos (aqueles dentro de um único arquivo) seria o suporte para âncoras YAML: https://learnxinyminutes.com/docs/yaml/

Parece que o esquema JSON pode estar falhando na validação deles service must be a mapping, not a NoneType. .

Ei, @grayside , as âncoras do yaml funcionam, pelo menos para mim. Veja meu comentário acima para saber como eu os uso.

Ok, mas é muito triste usar algum serviço noop, não?

Especialmente para env vars, que tipo de valores esses env vars manipulam? Se for sobre segredos, use o recurso de segredos de enxame (ou qualquer outra solução de segredos). Se for sobre configurações, concordamos que na maioria das vezes as configurações são específicas do aplicativo / serviço, e não se destinam a ser compartilhadas entre os serviços.

Se você precisar compartilhar configurações entre serviços, na maioria das vezes é quando você inicia a mesma imagem de contêiner, mas para diferentes propósitos / tarefas de tempo de execução (consumidor, produtor, trabalhador http, ...).

Se for sobre configurações, concordamos que na maioria das vezes as configurações são específicas do aplicativo / serviço, e não se destinam a ser compartilhadas entre os serviços.

Eu tendo a discordar. No projeto em que estou trabalhando atualmente, eu o uso, por exemplo, para volumes:

# Volume paths
environment:
  - &volume_a        volume-a:/usr/share/my_project/volumes/volume-a
  - &volume_b        volume-b:/usr/share/my_project/volumes/volume-b
  - &volume_c        volume-c:/usr/share/my_project/volumes/volume-c
  - &volume_d        volume-d:/usr/share/my_project/volumes/volume-d

Agora posso especificar esses volumes assim:

volumes:
  - volume-a:
  - volume-b:
  - volume-c:
  - volume-d:

services:
  some-service:
    image: some-image
    volumes:
      - *volume_a
      - *volume_b

  some-other-service:
    image: some-other-image
    volumes:
      - *volume_b
      - *volume_c

  some-third-service:
    image: yet-another-image
    volumes:
      - *volume_a
      - *volume_b
      - *volume_c
      - *volume_d

Isso torna mais fácil navegar por diferentes volumes sem ter que pensar em qual contêiner você está. Imho, essa é uma maneira de tornar sua configuração docker-compose mais consistente e fácil de usar e manter.

Ok sim eu entendo @JanNash mas no seu exemplo abaixo você não tem nenhum serviço noop certo?

Mas as âncoras não são suficientes para muitos casos.

Meu caso envolve suporte a vários ambientes para o mesmo projeto. Você pode ver um andaime para nossos projetos aqui .

Quando você desenvolve, você usa devel.yaml , mas na produção você usa prod.yaml . Também há test.yaml . Todos eles herdam de common.yaml e obtêm algumas variáveis ​​comuns de um arquivo .env .

Cada um tem suas peculiaridades:

  • O ambiente devel visa a velocidade de desenvolvimento, então ele usa argumentos de compilação que produzem compilações mais rápidas, monta volumes com o código do aplicativo do computador do desenvolvedor e adiciona alguns serviços fictícios que isolam o aplicativo do mundo externo.
  • O prod visa a estabilidade, então ele baixa e compila todo o código e o empacota na própria imagem em vez de usar volumes. As compilações são mais lentas, mas mais seguras.
  • teste pretende ser exatamente como prod, mas com isolamento de serviços externos, para evitar poluir o mundo externo.

Essa separação simples permite ter um pipeline DevOps muito ágil e flexível, onde todos usam o mesmo código entre diferentes estágios, com apenas pequenos ajustes dependendo do ambiente em uso.

Eu tentei mudar para compor o formato de arquivo v3, mas não apenas extends não é compatível, mas também .env , então agora seria um pesadelo de manutenção (mais por causa da falta de .env , para ser honesto). Ao decidir entre Swarm e DRY, escolhemos DRY por enquanto, mas algum dia precisaremos do Swarm e espero que ambos os recursos sejam suportados novamente ... ☺️

... ou pelo menos temos uma maneira de gerar um formato válido sem DRY a partir de uma solução DRY-ful. Achei que docker-compose bundle era para isso, mas parece estar condenado à suspensão de uso agora ...

... ou temos uma ferramenta diferente que faz tudo (estou de olho no ansible-container também). Mas certamente esta não é "a solução".

O link em https://github.com/moby/moby/issues/31101#issuecomment -301212524 inclui um README com o exemplo funcional de âncoras YAML. Olhando e tentando novamente hoje, funciona bem. Não tenho certeza do que estou fazendo de diferente.

@JanNash 👍

@Yajo , ouvi você e, como disse, é uma solução alternativa e seria melhor em uma ordem de magnitude se houvesse uma boa solução DRY integrada fornecida por docker / moby / docker-compose (qualquer que seja a referência correta) . Vamos todos torcer para que isso aconteça em breve, porque, além disso, estou muito feliz com o docker compose 👍

~ Para não ter suporte para .env, eu também modifiquei uma solução alternativa (meu projeto ainda não está em produção, então minha palestra é um pouco barata, eu sei :)). Para suportar diferentes conjuntos de env vars (dependências e versões / tags de imagem, por exemplo) em diferentes ambientes (para mim agora, que é local-development e um pequeno dev-server), eu uso dois arquivos, local.env e development.env e em vez de executar meus comandos apenas docker-compose <command> , ou eu crio o respectivo arquivo .env em meu shell antes, ou o executo assim: (. local.env && docker-compose <command>) . Ainda um hack, mas por agora, estou muito feliz com isso. ~

Tenham um bom dia, pessoal 🚶

Talvez até duas ordens de magnitude: D

@JanNash espere! .env não é mais compatível com 3 ?

Na verdade, não sei, acabei de ler em um comentário que não era.
Tenho usado o procedimento local.env e development.env principalmente porque não sabia sobre o autoenv quando o implementei: D
Desculpe pela possível confusão.

Ah, @Yajo mencionou a falta de suporte para .env neste comentário .
Você poderia explicar, @Yajo?

Oh, desculpe, minha culpa. Não é que não esteja funcionando, é apenas que você deve especificá-lo com env_file: .env , em vez de ser detectado automaticamente como antes. Voltemos ao problema original.

A discussão é para deixar extends qualquer lugar? Adoraria lê-lo antes de apresentar nosso caso de uso, porque acho que já se sabe que é um recurso bastante usado.

Olá, tenho uma pergunta - quando? Quando o suporte "estende" estará de volta na v3?

@JanNash você pode ficar bem menor do que isso. Acabei de apresentar um problema no github contra o seu repo, baixei o noop para 1200 bytes de 750k na minha máquina.

Vejo que não posso usar estender no momento em enxame.
alguma ideia de como lançar o mesmo serviço com as mesmas portas de publicação e com um contêiner no serviço que tem 1 variável de ambiente extra?

+1 para estende o suporte em implantação de pilha de enxame

Oi,
Estamos executando um aplicativo de microsserviços que é espalhado em vários repositórios git (cada um com seu arquivo docker-compose).
A implantação é liderada por um arquivo docker-compose "raiz" que estende cada serviço: para nós, esse extends recurso é realmente necessário para implantação de pilha.
Portanto, também +1 para estender o suporte na implantação da pilha de enxame
Obrigado.

Você pode usar a herança simples YAML (consulte &default , <<: *default ) como solução temporária:

version: '3'
services:
  worker: &default
    build: .
    command: bundle exec rake jobs:work
    env_file:
      - .env
    volumes:
      - .:/app
    depends_on:
      - db
      - redis
    links:
      - db:postgres
  web:
    <<: *default
    command: bundle exec puma -C config/puma.rb -p 3000
    ports:
      - "3000:3000"
  spring:
    <<: *default
    command: bundle exec spring server

Claro, o recurso extends é melhor

Que tal quando você estende um arquivo diferente?

Yaml não tem recurso de extensão de arquivo :(

Existe alguma atualização sobre esse recurso de um contribuidor do Docker? Está planejado para ser reintroduzido? Se não, existem planos para algo semelhante? Se não, por que não ..?

@quolpr , temo que seu código de "herança simples YAML" não substitua extends na maioria dos casos, pois o "protótipo" (ou seja, &default ) sempre será interpretado pelo Docker Compose como um serviço denominado worker . Qual serviço a) precisa, portanto, ser bem definido, b) pode ser indesejado.

Enfim, definitivamente um recurso interessante.

@laugimethods você também pode usar referências YAML:

version: '3'
services:
  spring:
    build: ./app
    command: /bin/sh -c "bundle exec spring server"
    volumes: &default_volumes
      - ./app:/app:delegated
      - bundle:/bundle:nocopy
  worker:
    build: ./app
    command: bundle exec sidekiq -v -C config/sidekiq.yml
    volumes: *default_volumes

(preste atenção em &default_volumes e *default_volumes )

Mas eu realmente não consigo entender por que extends recurso foi removido 🤔

Para sua informação, para substituir o recurso "extends" ausente, agora estou usando uma composição / mesclagem de .yaml arquivos:
https://github.com/Logimethods/smart-meter/blob/master/README.md#docker -compose

estende funciona, é simples e maduro, acho que se alguém ver estende como algum antipadrão, então simplesmente não use isso, mas por favor não corte

Posso pedir uma explicação clara da abordagem pretendida sem usar extends ? Eu o uso extensivamente, especialmente ao herdar de arquivos contidos em submódulos Git, permitindo uma definição de um metaprojeto lidando com fiação de rede entre aplicativos, etc. Embora eu esteja bem ciente de que posso especificar vários arquivos docker-compose.yml e tê-los sobrescritos, isso significa que eu precisaria especificar as interconexões na linha de comando, em vez de poder verificá-los no controle de origem usando extends ? Ou perdi algum novo recurso em algum lugar da v3?

Estou usando fortemente extends em vários projetos para herdar um conjunto comum de atributos de serviço para diferentes ambientes e diferentes hosts (leia-se: Eu uso extends para herdar de um arquivo diferente).

Depois de ler em estupor a remoção da palavra-chave extends e tentar encontrar uma substituição que não requeira o encadeamento de -f docker arquivos de composição, estou muito curioso para saber qual é a razão para remover extends .

Eu entendo o problema com links e volume-from mas apenas abster-se de usá-los em arquivos yml base parece a melhor coisa a fazer.

Seria improvável remover a roda de um carro só porque ela _pode_ se acostumar a virar o carro de cabeça para baixo ... certo?

PS: noop e âncoras parecem interessantes, mas adicionam complexidade desnecessária aos projetos mais simples ...

Como um exemplo muito, muito simples:

common/common.yml

services:
  web:
    image: alpine:3.6
    build: .
    environment:
      DOMAIN:
      PREFIX:

dev/docker-compose.yml

services:
  web:
    extends: ../common/common.yml
    service: web
  ports:
    - "8080:8080"

prod/docker-compose.yml

services:
  web:
    extends: ../common/common.yml
    service: web
  image: the-prod-image:latest-release
  ports:
    - "80:80"
    - "80:443"
  environment:
    NEW_RELIC_KEY:

Exatamente como você mantém os princípios DRY sem extends ?

Atualmente, não vejo razão para atualizar da versão 2.1 devido a isso.

@teodorescuserban ,

daisy chaining -f docker compose files

Qual é o problema disso? Você pode criar seus próprios scripts com apelidos curtos para chamar docker-compose.

Use a seguinte estrutura:

common / common.yml

services:
  web:
    image: alpine:3.6
    build: .
    environment:
      DOMAIN:
      PREFIX:

dev / docker-compose.yml

services:
  web:
    ports:
      - "8080:8080"

prod / docker-compose.yml

services:
  web:
    image: the-prod-image:latest-release
    ports:
      - "80:80"
      - "80:443"
    environment:
      NEW_RELIC_KEY:

Comandos

docker-compose -f common/common.yml -f dev/docker-compose.yml -p myproject up --build
docker-compose -f common/common.yml -f prod/docker-compose.yml -p myproject up --build

Eu não conhecia esse recurso. Embora torne sua CLI um 💩, ela pode funcionar.

Eu acho que se essa for a substituição oficial de extends , então deve haver uma maneira de tornar isso mais fácil.

Por exemplo:

docker-compose.yml

version: "3"  # or whatever
extend:
  - ./common/common.yml
  - ./dev/docker-compose.yml
services: # Not required now
  # etc.

Desta forma, você pode apontar para um único arquivo docker-compose.yml que faz tudo o que você precisa.

Uma alternativa útil seria oferecer suporte a vários arquivos de composição no COMPOSE_FILE env var.

@Yajo

Uma alternativa útil seria oferecer suporte a vários arquivos de composição na var de env COMPOSE_FILE.

De https://docs.docker.com/compose/reference/envvars/#compose_file :

Esta variável suporta vários arquivos Compose separados por um separador de caminho (no Linux e macOS, o separador de caminho é : , no Windows é ; ). Por exemplo: COMPOSE_FILE=docker-compose.yml:docker-compose.prod.yml . O separador de caminho também pode ser personalizado usando COMPOSE_PATH_SEPARATOR .

@ dermeister0 Você também pode mesclar permanentemente esses arquivos com ferramentas como https://github.com/ImmobilienScout24/yamlreader :

> yamlreader common/common.yml prod/docker-compose.yml > docker-compose-prod.yml
> docker-compose -f docker-compose-prod.yml -p myproject up --build

> cat docker-compose-prod.yml
services:
    web:
        build: .
        environment:
            DOMAIN: null
            NEW_RELIC_KEY: null
            PREFIX: null
        image: the-prod-image:latest-release
        ports:
        - 80:80
        - 80:443

@ dermeister0 obrigado por sua sugestão, infelizmente, é uma maneira desajeitada de resolver isso. Usando extends elimine a necessidade de realmente saber exatamente como você precisa conectá-los em série. Embora eu possa viver fazendo isso por mim mesmo, nunca poderia aplicar essa solução aos meus queridos desenvolvedores.

No entanto, eu não sabia que a variável COMPOSE_FILE env pode conter vários valores. Obrigado @gsong ! Isso é incrível e pode ser usado (eu o defino no arquivo .env ). Há um único problema aqui: nos arquivos base / comuns, também posso ter alguns serviços de que não preciso.

Tome, por exemplo, um arquivo comum que define o banco de dados e os contêineres da web. No teste, você deseja que todos eles sejam agrupados, mas na produção você deseja hosts separados para db e para web.

Além disso, docker-compose.override.yml é carregado por padrão.

https://docs.docker.com/compose/extends/#understanding -multiple-compose-files

Eu uso essa abordagem com a versão 3.3:

  • coloque opções de configuração e serviços comuns em docker-compose.yml ;
  • use docker-compose.override.yml para configuração de desenvolvimento e serviços específicos (como xdebug por exemplo);
  • use docker-compose.staging.yml para opções de configuração de teste específicas.

Nota: Eu não executo o Docker na produção.

Usando essa abordagem, posso construir facilmente localmente usando docker-compose build e quando implanto na preparação, uso:

docker-compose -f docker-compose.staging.yml -f docker-compose.yml build

Estou usando o Apache e não tenho arquivos de host virtuais separados para desenvolvimento e teste. Gastei um pouco para evitar ter arquivos diferentes. No final, vi que a única abordagem válida é usar <IfDefine> e variáveis ​​de ambiente (que defini na seção de ambiente dos arquivos yml), para incluir a configuração SSL, por exemplo. E eu uso TLD e prefixo de domínio, então posso ter algo como www.example.local http: //www.example.local/ : 8080 e www.staging.example.com http://www.staging.example.com / . Localmente, os sites são executados em http e em teste em https. Com essa abordagem, não preciso manter versões diferentes dos arquivos. Acho que o mesmo poderia ser feito na produção, mas como eu disse, prefiro evitar o Docker na produção, atm.

Os caminhos são todos parentes, portanto, os contêineres funcionarão em qualquer ambiente.

Meus 2 centavos

-Filippo

No meu caso, usei anteriormente algo assim:

  • common.yml
  • devel.yml -> extendendo common.yml
  • prod.yml -> extendendo common.yml
  • docker-compose.yml -> local, git-ignore, link simbólico para o ambiente desejado (devel ou prod).

Graças a https://github.com/moby/moby/issues/31101#issuecomment -329482917 e https://github.com/moby/moby/issues/31101#issuecomment -329512231, que eu não conhecia, agora posso passar para a v3 usando um esquema diferente:

  • docker-compose.yml -> o que antes era common.yml
  • devel.yml -> substituindo docker-compose.yml
  • prod.yml -> substituindo docker-compose.yml
  • docker-compose.override.yml -> local, git-ignore, link simbólico para o ambiente desejado (devel ou prod).

Também posso fazer quaisquer hacks necessários usando a variável env, portanto, no meu caso, o problema foi corrigido. Obrigado! 🎉 (Desculpe, eu deveria ter lido os novos documentos corretamente antes de reclamar).

PS: Mesmo assim, extends seria uma boa coisa de se ter de volta, mas pelo menos temos uma alternativa justa. 😊

@ shin- Primeiro, fiquei muito desapontado ao ver o recurso extends ausente em 3.0 , mas as âncoras YAML (exemplo: https://github.com/JanNash/docker-noop) seriam um substituição mais do que suficiente.

A única coisa é que, como no exemplo acima, você precisa colocar suas âncoras em alguma seção válida de seu arquivo docker-compose.yml .

Poderíamos obter uma propriedade templates (de nível superior) ou chaves ocultas como no GitLab para ser mais flexível na forma de definir as âncoras?

@ schmunk42 dê uma olhada em https://github.com/docker/cli/pull/452

O problema de confiar docker-compose.override.yml é que isso pressupõe que você só tem um tipo de substituição que precisa ser incluído e uma camada de substituições.

No meu caso, quero ter certos comportamentos comuns a todo o desenvolvimento local, mas posso precisar que sejam sutilmente diferentes se o desenvolvedor estiver executando Windows, OSX ou Linux. Para manter isso gerenciável em um contexto docker-compose v3, tenho usuários do Linux operando no mesmo comportamento que o ambiente de teste, o que funciona, mas significa que eles estão um pouco fora de sintonia com outros desenvolvedores.

Eu evito usar -f para desenvolvimento local porque descobri que ele é muito sujeito a erros humanos e confiar nele como um alternador para muitas coisas causa problemas. Selecionar um arquivo parece razoável, selecionar vários é algo que evito impor com cuidado.

FYI, eu acho que uma vez que o hack com x- mencionado acima, e também o encadeamento arquivos Docker-compor usando o COMPOSE_FILE variável no .env arquivo de projeto, adicionando o docker- compose.override.yml deve resolver todos os casos de uso que encontrei até agora.

As âncoras yml também são uma coisa bacana que pretendo usar em um futuro próximo.

Não estou muito feliz com a beleza do hack de x- mas posso viver com isso.

Obrigado pessoal por sua contribuição!

Parece que a remoção de extends está causando muita azia e bloqueando a passagem para a v3 ou recorrendo a hacks. Gosto da capacidade de definir um serviço de "modelo" (ou abstrato) que pode conter algumas coisas comuns (por exemplo, políticas de atualização)

Estou trabalhando em um utilitário de filtro golang simples que pode pré-processar um arquivo de composição do docker com extends e cuspir um arquivo v3 limpo com as extensões resolvidas:
resolver-compor docker stack deploy -c docker-compose.yaml
(ou docker-compose up)

Isso funcionará para pelo menos alguns de seus casos de uso / por que pegadinhas?

@pnickolov Isso seria maravilhoso para mim.

Tenho procurado ansible-container (eu uso o ansible pessoalmente, mas ainda não no trabalho), que parece que faria tudo que eu preciso, mas um script como o seu seria mais preferível (menos rotatividade)

Contanto que ele possa processar recursivamente extends: chaves, eu ficaria feliz!

Ok, parece que encontramos alternativas para extends ... 👍

O que é preocupante é o fato de que o gerenciamento de projetos do Moby não parece considerar a manutenção da compatibilidade como um elemento-chave. A compatibilidade com versões futuras é essencial para uma adoção mais ampla, especialmente para grandes aplicativos implantados na produção. Como podemos promover o Docker Swarm / Docker EE quando não há garantia de que recursos essenciais como extends permanecerão? 👎
Uma boa reputação é difícil de ganhar e fácil de perder ...

Pessoalmente, prefiro contar com recursos nativos de YAML para realizar a tarefa que é tratada por extends na sintaxe v2 , em vez de um script personalizado ou uma solução maior como ansible. Eu estava tendo problemas semelhantes e comecei a escrever meu próprio conversor antes que houvesse uma solução como usar vários arquivos .yml etc. (https://github.com/schmunk42/yii2-yaml-converter-command) - mas não era uma solução viável.

Para mim, também não há problema em descontinuar recursos, se isso for feito junto com uma política de controle de versão; você não pode carregar coisas velhas para sempre, mesmo que isso signifique algum trabalho do nosso lado.

@ schmunk42 Não há problema em descontinuar recursos, mas apenas quando:

  • o recurso removido não é mais usado ou é um verdadeiro bloqueador de evoluções
  • é anunciado com antecedência
  • um caminho de migração é fornecido imediatamente

Infelizmente, nenhum desses requisitos (no meu livro) se aplica à depreciação de extends ...

@laugimethods Qual é o motivo pelo qual você precisa usar v3 ?

@ schmunk42 Por causa do Swarm:

Versão 3.x, a versão mais recente e recomendada, projetada para ser compatível com o Compose e o modo de enxame do Docker Engine. Isso é especificado com uma versão: '3' ou versão: '3.1', etc., entrada na raiz do YAML.

O comando docker stack deploy suporta qualquer arquivo Compose da versão “3.0” ou superior

A propósito, meu comentário não está apenas relacionado a extends , mas a qualquer (dolorosa) depreciação que possa ocorrer no futuro ...

Sim, estamos enfrentando o mesmo problema por causa do modo enxame.

Eu me perguntei em primeiro lugar, por que diabos o docker CLI agora é capaz de usar a entrada --composer-file . Mas, de acordo com o que aprendemos com docker/swarm , parece uma coisa muito complicada executar pilhas em um enxame (autogerenciador) e que há vários bons motivos para isso ter sido movido para o motor.

Apenas para observar algumas das minhas descobertas aqui ... a transição de v2 para v3.4 está longe de ser fácil.

Alguns dos meus problemas:

  • existem outras opções não suportadas, como volumes_from , bastante fáceis de contornar, uma vez que queríamos removê-las de qualquer maneira
  • .env arquivos (como com docker-compose ) não têm efeito com Docker CLI
  • especificar vários arquivos de composição ( docker stack deploy -c docker-compose.yml -c docker-compose.override.yml doro ) parece não funcionar corretamente, não há erro, mas parece que eles também não foram mesclados corretamente - mas também não há comando como docker-compose config para verificar isso
  • não há binário "fácil de instalar" (pré-lançamento) para docker-compose que suporta a sintaxe v3.4 ; como Docker Edge
  • redes externas precisam ser criadas com --scope swarm

CC: @handcode

Usando as compilações mais recentes

  • docker 17.09.0-ce
  • docker-compose 1.17.0dev

Agora estou usando este pipeline de configuração para substituir meu uso de _extend_ e _noop_
Mantém as coisas um pouco mais secas
Espero que isso ajude alguém

base.yml (definições compartilhadas, este é um documento yaml válido, então mesclável usando _docker-compose config_)

version: '3.4'
networks:
  net_back:
    external: true

base-inject.yml (definições de âncora compartilhadas, infelizmente não podem ser adicionadas a base.yml, pois as âncoras não podem ser referenciadas em diferentes arquivos yaml, em vez disso, são injetadas como texto em foo.yml , o que não é uma maneira ideal de fazer isso)

x-logging: &logging
  driver: json-file
  options:
    max-size: "50m"
    max-file: "2"

foo.yml (definição de pilha genérica, objetos de referência de base.yml , âncoras de base-inject.yml e objetos substituídos em foo-dev.yml )

version: '3.4'
[[base-inject]]
services:
  foo:
    image: ${DOCKER_REGISTRY}/foo:${IMAGE_VERSION}
    volumes:
      - type: volume
        source: "volfoo"
        target: "/foo"
    networks:
     - net_back
    logging:
      <<: *logging

foo-dev.yml (por definição de pilha de ambiente)

version: '3.4'
services:
  foo:
    ports:
      - "8080:80"
volumes:
  volfoo:
    name: '{{index .Service.Labels "com.docker.stack.namespace"}}_volfoo_{{.Task.Slot}}'
    driver: local

Em seguida, o comando de implantação:

docker stack rm stack_foo && echo "waiting..." && sleep 3 &&
  cat foo.yml | sed -e '/base-inject/ {' -e 'r base-inject.yml' -e 'd' -e '}' > ./foo-temp1.yml &&
  export $(sed '/^#/d' ./dev.env | xargs) &&
  docker-compose -f base.yml -f ./foo-temp1.yml -f foo-dev.yml config > ./foo-temp2.yml
  docker stack deploy --with-registry-auth --prune --compose-file ./foo-temp2.yml stack_foo
  1. Remover pilha antiga
  2. Espere que a pilha removível se propague
  3. Injetar âncoras na definição genérica, salvar no arquivo tmp
  4. Ler + definir variáveis ​​de arquivo env a partir do arquivo
  5. Use docker-compose para mesclar os três arquivos.
  6. Implantar arquivo mesclado

Para aqueles que desejam extends em compor 3+ arquivos, acabei de colocar minhas mãos em uma ferramenta chamada baclin . baclin lineariza essas diretivas, substituindo recursivamente todas as diretivas extends por seu conteúdo. Este é um software alfa, o código faz parte da minha máquina, pois atualmente estou escrevendo código para oferecer suporte ao modo Swarm e implantação de pilhas. Binários de plataforma de uma versão anterior de baclin estão disponíveis aqui . Por favor, relate qualquer comentário ou problema aqui .

Isso é realmente confuso!
Lendo o documento para a versão mais recente do docker ( v17.09 ) e também o documento de lançamento v17.06 este recurso deve estar disponível.

$ head -n1 docker-compose.yml
version: '3'

Mas compose up rende

ERROR: The Compose file './docker-compose.yml' is invalid because:
Unsupported config option for services.admin_application: 'extends'

ao usar a palavra-chave extends .
Além disso, não consigo encontrar nada sobre a remoção de extends no changelog compose .

Agora o que é ?!
Informações cruciais como essa não devem ser difíceis de encontrar ou escondidas dentro de algum problema obscuro do github.


$ docker --version
Docker version 17.09.0-ce, build afdb6d4

$ docker-compose --version
docker-compose version 1.16.1, build 6d1ac21

@jottr , Veja a documentação :

A palavra-chave extends é suportada em formatos de arquivo Compose anteriores até a versão 2.1 do arquivo Compose (consulte extends em v1 e extends em v2), mas não é suportada em Compose versão 3.x.

Então, se você quiser usar extends você precisa usar version: '2.1' .

Foi mal. Ele ainda deve estar na parte superior do documento com um sinal de aviso de suspensão de uso em vermelho.

Foi mal. Ele ainda deve estar na parte superior do documento com um sinal de aviso de suspensão de uso em vermelho.

@jottr Basta usar o Github para criar um problema separado para isso ou até mesmo criar um PR para isso. Acabei de criar o problema aqui: https://github.com/docker/docker.github.io/issues/5340

No meu caso, tenho docker-compose-override.yml como segue:
yaml version: "3.4" services: common: extra_hosts: - "host1:172.28.5.1" - "host2172.28.5.2" - "host3:172.28.5.3" networks: default: external: name: "common-network"
E eu tenho vários outros docker-compose.yml arquivos que precisam compartilhar a rede e extra_hosts. Como fazer isso sem estender o recurso?

yaml version: "3.4" services: mongo: image: "mongo" container_name: "mongo" hostname: "mongo" volumes: - "/opt/docker/mongo/default.conf:/usr/local/etc/mongo/mongod.conf" - /opt/data/mongo:/data/db" ports: - "27017:27017" command: "mongod --config /usr/local/etc/mongo/mongod.conf" networks: default: ipv4_address: "172.28.5.4"
Seria ótimo se docker-compose suportasse âncora yaml e referências entre arquivos diferentes. Talvez, aplicando âncora e referências após mesclar os arquivos.
Por exemplo:
yaml version: "3.4" services: common: &common extra_hosts: ... networks: ...
yaml version: "3.4" services: mongo: <<: *common image: "mongo" container_name: "mongo" ...
O resultado deve ser:
yaml version: "3.4" services: mongo: image: "mongo" container_name: "mongo" extra_hosts: // EXTRA HOSTS HERE networks: ...

@ sandro-csimas isso é possível com: https://docs.docker.com/compose/compose-file/#extension -fields
@ shin- este tíquete pode ser fechado?

@rdxmb Acho que não. Pelo que posso ver, você não pode estender de outro arquivo docker-compose

Estou certo em pensar que este é um problema para https://github.com/docker/compose/issues ?

Algumas depurações:

# cat docker-compose.yml 
version: "3.4"
services:
  foo-not-bar:
    << : *common
  foo-bar:
    << : *common
    environment:
      - FOO=BAR 

x-common-definitions-for-all-our-services:
  &common
    image: phusion/baseimage
    environment:
      - FOO=NOTBARBYDEFAULT

Isso está trabalhando com
docker stack deploy -c docker-compose.yml test

Ao usar docker-compose:

# docker-compose up 
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
  in "./docker-compose.yml", line 4, column 10

Alterando o arquivo yml para:

version: "3.4"

x-common-definitions-for-all-our-services:
  &common
    image: phusion/baseimage
    environment:
      - FOO=NOTBARBYDEFAULT

services:
  foo-not-bar:
    << : *common
  foo-bar:
    << : *common
    environment:
      - FOO=BAR

também funciona com docker-compose.

Então pensei que isso também deveria funcionar com vários arquivos, o que não é o caso:

# docker-compose -f compose-services.yml -f compose-default.yml config > docker-compose.yml
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
  in "./compose-services.yml", line 5, column 10
t# docker-compose -f compose-default.yml -f compose-services.yml config > docker-compose.yml
ERROR: yaml.composer.ComposerError: found undefined alias 'common'
  in "./compose-services.yml", line 5, column 10
# cat compose-services.yml 
version: "3.4"

services:
  foo-not-bar:
    << : *common
  foo-bar:
    << : *common
    environment:
      - FOO=BAR 

# cat compose-default.yml 
x-common-definitions-for-all-our-services:
  &common
    image: phusion/baseimage
    environment:
      - FOO=NOTBARBYDEFAULT

No entanto, é claro, mesclar isso é possível com um simples uso de cat :

# cat compose-default.yml compose-services.yml > docker-compose.yml && docker-compose up -d
WARNING: The Docker Engine you're using is running in swarm mode.

Compose does not use swarm mode to deploy services to multiple nodes in a swarm. All containers will be scheduled on the current node.

To deploy your application across the swarm, use `docker stack deploy`.

Creating network "test_default" with the default driver
Creating test_foo-bar_1 ... 
Creating test_foo-not-bar_1 ... 
Creating test_foo-bar_1
Creating test_foo-bar_1 ... done

Rodando em xenial com as versões:

# docker --version
Docker version 17.11.0-ce, build 1caf76c
# docker-compose --version
docker-compose version 1.17.0, build ac53b73

@rdxmb , obrigado!
Portanto, devo mesclar os arquivos de composição usando o comando "cat" e executar o arquivo final.

Eu também uso docker-compose config para fazer isso. Um exemplo de configurações específicas do ambiente:

Isso é executado pelo pipeline de CI: docker-compose -f docker-compose.yml -f docker-compose.override.prod.yml config > docker-compose.prod.yml e então eu uso docker stack deploy -c .\docker-compose.prod.yml my-stack

Vote nisso, o extends é muito útil para a v3.

Usei muito com a v2, muito útil mesmo!
+1

Eu adoraria ver o suporte de extends na v3. Isso ajudaria a SECAR meu arquivo docker-compose.yml muito.

Já se passou quase um ano desde que esse problema foi trazido e é realmente óbvio que muitas pessoas precisam desse recurso. Ainda não li uma resposta do Docker dev a esta solicitação, nem uma explicação de por que ele não foi incluído no docker-compose v3 antes do lançamento.

Um estado deplorável do software se não conseguirmos nem mesmo comunicar ou manter recursos para nossos clientes que acreditam em uma nova tecnologia.

Uma possível interpretação (e talvez também um resumo do tópico atual) da situação é assim:

  • Âncoras / referências YAML mais os campos de extensão do 3.4 alcançam quase o mesmo.
  • vários arquivos podem funcionar. Veja o cat simples e a abordagem avançada neste tópico. O comentário de abordagem simples mostra um problema de docker-compose carregando vários arquivos no final (alguém criou um problema para isso?). Se isso fosse corrigido no docker-compose, você nem mesmo precisaria da mesclagem do arquivo. Então, para mim, as pessoas que desejam suporte a vários arquivos devem continuar em docker / compose / issues como @rdxmb proposto.
  • Trazer de volta extends foi considerado (veja os eventos do projeto GitHub , boa transparência aqui da equipe do Docker, obrigado!) E você pode interpretar o resultado como "há um monte de outras coisas que são estrategicamente mais importantes para eles", mas você pode ainda escrever uma solicitação de pull para extends eu acho.

Para mim, esse é um ponto de vista perfeitamente compreensível.

@aCandidMind aprovado .

IMHO, embora as abordagens mencionadas por @aCandidMind funcionem, elas adicionam complexidade ao mecanismo mais simples e limpo fornecido por extends .
Talvez seja eu, mas mover uma configuração de extensão moderadamente complexa para campos de extensão torna-se muito mais difícil de ler e manter.
Depois de ler muitos comentários e postagens, ainda não está claro para mim por que o extends foi descartado e quais são as vantagens dessa regressão em recursos.

É possível com um pouco de magia bash eu colocar um repositório de teste para que você possa tentar por si mesmo.

Apenas estruture seu comando stack deploy assim:

docker stack deploy --compose-file=<(docker-compose -f docker/prod.yml -f docker/dev.yml config) <stackname>

@tylerbuchea - a única desvantagem dessa magia bash é que você pode obter um WARNING: Some services (<service-name(s)>) use the '<key>' key, which will be ignored. Compose does not support '<key>' configuration . Isso pode causar alguma confusão. Mas ei, funciona 👍

@dnmgns você está certo! Obrigado por apontar isso. Como @joaocc disse, nada vai superar o suporte nativo, mas a solução que mencionei acima é a melhor que pude encontrar, já que não há dependências além do bash.

@tylerbuchea Uma maneira suja é redirecionar stderr para / dev / null :)
docker stack deploy --compose-file=<(docker-compose -f docker/prod.yml -f docker/dev.yml config 2> /dev/null) <stackname>

Não tem vergonha nisso 😄

Acho que a documentação deveria ser mais explícita sobre essa confusão em torno de extend .
A descrição de extend redireciona o usuário para a documentação de como atualizar, e a documentação de como atualizar aponta de volta para a descrição de extend para obter mais informações. Isso não é útil o suficiente: como um usuário, eu esperaria alguma ajuda sobre como lidar com todo esse problema, quais opções eu tenho e o que devo considerar. Tenho certeza de que havia uma ideia clara por trás da decisão de remover extend da v3.

Ver:
https://docs.docker.com/compose/extends/#extending -services
https://docs.docker.com/compose/compose-file/compose-versioning/#upgrading

Em relação a @tylerbuchea excelente solução baseada em bash de uma linha,
infelizmente, ele não oferece suporte a alguns recursos avançados de pilha do Docker:

WARNING: Some services (web) use the 'deploy' key, which will be ignored. Compose does not support 'deploy' configuration - use `docker stack deploy` to deploy to a swarm.
WARNING: Some services (web) use the 'configs' key, which will be ignored. Compose does not support 'configs' configuration - use `docker stack deploy` to deploy to a swarm.

Não que, uma vez que https://github.com/docker/cli/pull/569 for mesclado, a partir de 18.03, docker stack deploy oferecerá suporte à mesclagem de vários arquivos de composição em um. Não substitui totalmente a chave extends do formato composefile v2, mas espero que cubra muito mais casos de uso 👼

Minha própria solução alternativa foi usar yq (pode ser combinado em uma linha se estiver usando Bash):

yq merge --overwrite docker-stack.yml docker-stack.preprod.yml > merged-docker-stack.yml
docker stack deploy -c merged-docker-stack.yml preprod

@ Lucas-C eles são apenas avisos de que a saída ainda incluirá suas chaves deploy e config . Você pode verificar isso se executar docker-compose -f docker/prod.yml -f docker/dev.yml config

É para compor arquivos v3.4 e superior. Suporta referências cruzadas yaml (parciais). Terminei com este script zsh alias / perl:

alias regen=$'perl -MFile::Slurp=read_file -MYAML=Load,Dump -MHash::Merge::Simple=merge -E \'
  local $YAML::QuoteNumericStrings = 1;
  $n=read_file("/data/docker-compose.yml");
  $s=Dump(merge(map{Load($n.read_file($_))}@ARGV));
  local $/ = undef;
  $s =~ s/\\bno\\b/"no"/g;
  say $s;
  \' $(find /data -mindepth 2 -maxdepth 4 -name docker-compose.yml) >! /data/x-docker-compose.yml'
regen
export COMPOSE_FILE=/data/x-docker-compose.yml
  1. leia /data/docker-compose.yml com parte comum.
  2. encontre todos os docker compose recursivamente (por exemplo, existem cerca de 40 arquivos containers / docker-compose.yml diferentes neste projeto)
  3. prefixe cada docker-compose.yml com o conteúdo /data/docker-compose.yml
  4. fundir
  5. salvar o resultado em /data/x-docker-compose.yml

Prós : perl é uma ferramenta comum, todos os módulos perl também, a geração é rápida.
Contras : Eu odeio hacks, mas não há outra maneira de DRY. Docker-compose final tem cerca de 900 linhas. Você realmente deseja que eu o suporte como um único arquivo desde o início? É uma pena ter docker binário empacotado com docker-compose python empacotado com hack perl.

Como você pode simplesmente remover um recurso como extends? Esse parece ser um recurso central.

Usar docker-compose config canalizado para a opção de entrada padrão de docker stack deploy -c - resolveu o problema para mim:

docker-compose -f docker-compose.yml \
               -f docker-compose.extended.yml \
               config \
| docker stack deploy -c - my-stack

Eu não tentei isso, mas também notei isso na documentação docker stack deploy :

Se sua configuração for dividida entre vários arquivos Compose, por exemplo, uma configuração básica e substituições específicas do ambiente, você pode fornecer vários sinalizadores --compose-file .

Com este como exemplo:

docker stack deploy --compose-file docker-compose.yml -f docker-compose.prod.yml vossibility

https://docs.docker.com/engine/reference/commandline/stack_deploy/#compose -file

A justificativa para a remoção de extends documentada em algum lugar? Não parece ser explicado nos documentos oficiais, por exemplo, aqui: https://docs.docker.com/compose/extends/#extending -services
Se os usuários pudessem entender o motivo, eles poderiam desenvolver uma ideia melhor de como responder à remoção. Obrigado.

@ shaun-blake acabei usando vários arquivos de composição. Essa parece ser a abordagem que as pessoas usam. Em vez de herança, é mais como uma combinação. Ao compilar ou executar, copio o modelo yaml do ambiente correto para docker-compose.override.yml.

Vários arquivos de composição do docker (por exemplo: base.yml , local.yml , prod.yml ) não permitem que o serviço use âncoras YAML de outros arquivos, portanto, as definições de serviço fatoradas não puderam ser definidas entre vários arquivos yml .
Observe que este problema é o 13º mais comentado : https://github.com/moby/moby/issues?q=is%3Aissue+is%3Aopen+sort%3Acomments-desc e o mais gostado .

Se os usuários pudessem entender o motivo, eles poderiam desenvolver uma ideia melhor de como responder à remoção. Obrigado.

+1 na documentação sobre a justificativa para a remoção de extends em primeiro lugar ...

Ainda não _estende_ depois de quase 1 ano e meio depois. Vamos, devs, vc não remova o sth sem dar uma alternativa.

Eles fizeram, eles oferecem uma alternativa chamada composição. Por favor, leia minha resposta no tópico.

-Filippo

Em 30 de julho de 2018, às 09:41, Xiaohui Liu [email protected] escreveu:

Ainda não se estende depois de quase 1 ano e meio depois. Vamos, devs, vc não remova o sth sem dar uma alternativa.

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub https://github.com/moby/moby/issues/31101#issuecomment-408790200 ou desative o thread https://github.com/notifications/unsubscribe-auth/AAS_0AOynjpfVnVo4ZqciLsqlsnvBmkpZ4MgaLs5NgaLs5NgaLs5NgaLs5NgaLs .

@dedalozzo , "no tópico" ==?

Por favor, veja meu comentário aqui:

https://github.com/moby/moby/issues/31101#issuecomment -329527600 https://github.com/moby/moby/issues/31101#issuecomment-329527600

Basicamente, você deve usar uma cadeia de arquivos .yml para substituir ou alterar a configuração de seus contêineres.

Leia "Especificando vários arquivos de composição"

Você pode fornecer vários arquivos de configuração -f. Quando você fornece vários arquivos, o Compose os combina em uma única configuração. O Compose cria a configuração na ordem em que você fornece os arquivos. Os arquivos subsequentes são substituídos e adicionados aos seus predecessores.

https://docs.docker.com/compose/reference/overview/ https://docs.docker.com/compose/reference/overview/

Essa abordagem usa composição sobre herança para obter, mais ou menos, o mesmo resultado.

Em 30 de julho de 2018, às 15:23, Serban Teodorescu [email protected] escreveu:

@dedalozzo https://github.com/dedalozzo , "no tópico" ==?

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub https://github.com/moby/moby/issues/31101#issuecomment-408880809 ou desative o tópico https://github.com/notifications/unsubscribe-auth/AAS_0FZO30NplqHRid_Id8VBOJW7nk4Mul .

Não seríamos capazes de obter a mesma extensibilidade de volta se combinarmos
campos de extensão yaml (compor 2.1 + / 3.4 +)
em permitir que os campos x- referenciem outros arquivos ?

Portanto, poderíamos permitir uma listagem de raiz include para especificar os arquivos a serem carregados.
eles seriam colocados em x-include e imediatamente utilizáveis ​​por meio de âncoras e mesclagem YAML padrão.



Composição atual v2.1 +
# /docker-compose.yml
version: '2.1'

volumes:
  nginx_file_sockets:
    external: false
    driver: local

services:
  reverse_proxy:
    extends:
      file: reverse_proxy/docker-compose.yml
      service: proxy
    restart: 'always'
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  reverse_proxy_test:
    extends:
      file: reverse_proxy/docker-compose.yml
      service: proxy
    restart: 'always'
    ports:
      - "8080:80"
      - "8443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web:
    extends:
      file: webservice/docker-compose.yml
      service: app
    restart: 'always'
    environment:
      ENVIRONMENT: 'production'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web_staging:
    extends:
      file: webservice/docker-compose.yml
      service: app
    restart: 'no'
    environment:
      ENVIRONMENT: 'staging'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

# /proxy/docker-compose.yml
version: '2.1'
services:
  proxy:
    build: ./
    volumes:
      - /certs:/certs:ro
# /webservice/docker-compose.yml
version: '2.1'
services:
  app:
    build:
      context: ./folder
      args:
        LINUX_VERSION: 20.s
        LINUX_FLAVOR: dash
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - bootstrap.memory_lock=true
    ulimits:
      memlock:
        soft: -1
        hard: -1




Idéia de composição v3.X
# /proxy/docker-compose.yml
version: '3.9'
services:
  proxy:
    &proxy
    build: ./
    volumes:
      - /certs:/certs:ro
# /webservice/docker-compose.yml
version: '3.9'
services:
  app:
    &app
    build:
      context: ./folder
      args:
        LINUX_VERSION: 20.s
        LINUX_FLAVOR: dash
    environment:
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
      - bootstrap.memory_lock=true
    ulimits:
      memlock:
        soft: -1
        hard: -1
# /docker-compose.yml
version: '3.9'
include:
  - /proxy/docker-compose.yml
  - /webservice/docker-compose.yml

volumes:
  nginx_file_sockets:
    external: false
    driver: local

services:
  reverse_proxy:
    << : *proxy
    restart: 'always'
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  reverse_proxy_test:
    restart: 'always'
    << : *proxy
    ports:
      - "8080:80"
      - "8443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web:
    << : *app
    restart: 'always'
    environment:
      ENVIRONMENT: 'production'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web_staging:
    restart: 'no'
    extends:
      file: web1/docker-compose.yml
      service: app
    environment:
      ENVIRONMENT: 'staging'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx




Diff
@@ /proxy/docker-compose.yml @@
-version: '2.1'
+version: '3.9'
 services:
   proxy:
+    &proxy
     build: ./
     volumes:
       - /certs:/certs:ro
 ```

 ```diff
 @@ /webservice/docker-compose.yml @@
-version: '2.1'
+version: '3.9'
 services:
   app:
+    &app
     build:
       context: ./folder
       args:
         LINUX_VERSION: 20.s
         LINUX_FLAVOR: dash
     environment:
       - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
       - bootstrap.memory_lock=true
     ulimits:
       memlock:
         soft: -1
         hard: -1
 ```

 ```diff
 @@ /docker-compose.yml @@
-version: '2.1'
+version: '3.9'
+include:
+  - /proxy/docker-compose.yml
+  - /webservice/docker-compose.yml

 volumes:
   nginx_file_sockets:
     external: false
     driver: local

 services:
   reverse_proxy:
-    extends:
-      file: reverse_proxy/docker-compose.yml
-      service: proxy
+    << : *proxy
     restart: 'always'
     ports:
       - "80:80"
       - "443:443"
     volumes:
       - nginx_file_sockets:/sockets/nginx

   reverse_proxy_test:
-    extends:
-      file: reverse_proxy/docker-compose.yml
-      service: proxy
+    << : *proxy
     restart: 'no'
     ports:
       - "8080:80"
       - "8443:443"
     volumes:
       - nginx_file_sockets:/sockets/nginx

   web:
-    extends:
-      file: webservice/docker-compose.yml
-      service: app
+    << : *app
     restart: 'always'
     environment:
       ENVIRONMENT: 'production'
       DB_USER: ${WEB1_DB_USER}
       DB_PASSWORD: ${WEB1_DB_PASS}
     volumes:
       - nginx_file_sockets:/sockets/nginx

   web_staging:
-    extends:
-      file: webservice/docker-compose.yml
-      service: app
+    << : *app
     restart: 'no'
     environment:
       ENVIRONMENT: 'staging'
       DB_USER: ${WEB1_DB_USER}
       DB_PASSWORD: ${WEB1_DB_PASS}
     volumes:
       - nginx_file_sockets:/sockets/nginx
 ```
<hr>
Resulting in the final version, which should be already yaml parsable:

```yml
# /docker-compose.yml
version: '3.9'
#include:
#  - /proxy/docker-compose.yml
#  - /webservice/docker-compose.yml
x-include:
  /proxy/docker-compose.yml:
    version: '3.9'
    services:
      proxy:
        &proxy
        build: ./
        volumes:
          - /certs:/certs:ro
  /webservice/docker-compose.yml:
    version: '3.9'
    services:
      app:
        &app
        build:
          context: ./folder
          args:
            LINUX_VERSION: 20.s
            LINUX_FLAVOR: dash
        environment:
          - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
          - bootstrap.memory_lock=true
        ulimits:
          memlock:
            soft: -1
            hard: -1

volumes:
  nginx_file_sockets:
    external: false
    driver: local

services:
  reverse_proxy:
    << : *proxy
    restart: 'always'
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  reverse_proxy_test:
    << : *proxy
    restart: 'no'
    ports:
      - "8080:80"
      - "8443:443"
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web:
    << : *app
    restart: 'always'
    environment:
      ENVIRONMENT: 'production'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

  web_staging:
    << : *app
    restart: 'no'
    environment:
      ENVIRONMENT: 'staging'
      DB_USER: ${WEB1_DB_USER}
      DB_PASSWORD: ${WEB1_DB_PASS}
    volumes:
      - nginx_file_sockets:/sockets/nginx

AFAIK é um recurso YAML, integrado na própria especificação do idioma, para evitar a repetição de partes no mesmo arquivo. Ao usar arquivos diferentes, isso é basicamente impossível.

Você deve propor esse recurso para a própria especificação YAML.

Esta discussão se reduz a:

  • Quão docker-compose -f file.yml é muito melhor do que docker-compose -f file.yml -f file_extension.yml ?
  • Ou: fiação no nível de comando _vs_ fiação no nível do arquivo.

Somente ao trabalhar na linha de comando, o inconveniente se torna notável. Temos que reconhecer isso por um segundo. Todo o resto é programável, de qualquer maneira.

Se esse for o argumento real, então docker-compose up service tem uma semântica melhor do que docker-compose -f service.yml up : defina tudo o que é necessário para o desenvolvimento local (também conhecido como linha de comando) em docker-compose.override.yml .

A semântica dada é muito limpa e bem pensada. Adotar service.yml _para o uso da linha de comando_ provavelmente significa diminuir a UX. Há outro argumento para isso: embora seja claro à primeira vista, o que docker-compose.yml é, service.yml pode ser qualquer coisa, realmente qualquer coisa.

Isenção de responsabilidade: uma opinião provocativa. : wink: Não levei em consideração todos os casos de uso possíveis ...

Depois dessa discussão prolongada, não tenho certeza se algum dia vai dar certo. IMHO, extends foi legal e deve ter sido pelo menos cuidadosamente descontinuado e então discutido em vez de simplesmente descartá-lo.

Acho que uma coisa que podemos fazer é melhorar a história da documentação sobre v2 vs. v3. Muitos presumem que a v3 substituiu a v2, mas isso não é totalmente verdade. Ambos recebem novos recursos que se concentram em seus casos de uso. Este problema do GH foi iniciado para que pudéssemos ter uma discussão sobre quais recursos futuros seriam necessários para fazer seu caminho do docker-compose para o Swarm e como melhorar os documentos para usar docker-compose, o formato de arquivo de composição e as pilhas do Swarm juntos. Extends ainda funciona muito bem na v2.4 atualizada. Espero poder ajudar a oferecer informações sobre as soluções que temos hoje:

v2: Apenas para docker-compose cli. Fluxo de trabalho de desenvolvimento focado em uma única máquina e motor. Também é bom para fluxos de trabalho de construção / teste de CI. Este ramo de versão recebeu novos recursos em dezembro de 2017 na v17.12

v3: Ideal para pilhas Swarm / Kube, com conceitos de vários nós e mantém o suporte para a maioria dos recursos docker-compose cli.

Se você não estiver usando as pilhas Swarm ou Docker Enterprise Kubernetes, não há razão para usar a v3 . Fique com a v2.4 e você obterá todos os recursos docker-compose cli, incluindo extends, depends_on, extension fields e até Depends_on com verificações de integridade (para evitar scripts de espera).

A v3 foi criada para tentar mesclar os recursos de um único motor docker-compose cli world com um mundo de cluster de vários nós. Nem todos os recursos da v2 (como depends_on) fazem sentido em um cluster. Outros recursos (como extend) simplesmente não chegaram à v3, provavelmente porque antes da v3 existir, todo o código estava em docker-compose Python, e para v3.0 suportar Swarm, eles tiveram que reescrever isso no docker cli Go, e agora eles estão escrevendo novamente no daemon do motor para, eventualmente, fazer uma API de pilhas Swarm, que ainda não existe.

Para aqueles que são novos neste problema, observe também muito do trabalho que foi feito para resolver vários problemas de configuração, modelos e fluxo de trabalho da equipe desde a versão 3.0:

Os documentos em https://docs.docker.com/compose/extends/#extending -services devem enfatizar em vermelho o fato de que a palavra-chave extends foi removida na v3, pois é mais importante do que apenas uma _notação_.
Eu migrei e folheei os documentos para saber por que não estava mais funcionando, então segui vários problemas fechados antes de terminar aqui, então voltei para os documentos originais e notei o texto.

A palavra-chave extends é suportada em formatos de arquivo Compose anteriores até a versão 2.1 do arquivo Compose (consulte extends em v1 e extends em v2), mas não é suportada em Compose versão 3.x.

Pode ser reformulado como:

A palavra-chave extends foi removida no Compose versão 3.x, mas ainda é suportada em formatos de arquivo Compose anteriores até o arquivo Compose versão 2.1 (consulte estende na v1 e estende na v2).

É uma pequena diferença, mas fácil de ignorar ao folhear documentos.

@krisrp PR começou ^^^

Obrigado @BretFisher

Existem planos de, talvez, renomear v2 para "version: docker-cli" e v3 para "version: swarm / kube"?
Faria mais sentido diferenciá-los assim, considerando como a v3 substitui a v2 na maioria dos outros esquemas de controle de versão. No momento, ambos são mantidos e divergentes, então, a menos que eu esteja enganado, parece que os dois ainda existirão por um tempo.

@krisrp Ao contrário, a razão para incrementar um número de versão principal é sinalizar a divergência de compatibilidade.

@ cpuguy83 Não estava insinuando o contrário. Peço desculpas por não ser mais claro ou explícito.
O IIRC Gnome 2 e 3 também teve essa confusão anos atrás, quando garfos independentes de cada um foram mantidos.

Não quero atrapalhar este tópico para discutir a semântica do versionamento (trocadilho), então vou deixar por isso mesmo. A postagem de @BretFisher na semana passada sobre como melhorar a documentação da v2 vs v3 teria ajudado a mim e provavelmente a outros.

@ shin- @ cpuguy83 Olhando para este problema mais de um ano depois, qual _é_ o motivo para não adicioná-lo de volta na versão 3?

Não consegui descobrir muito sobre isso, a não ser "poderíamos fazer de forma diferente" (mas nenhuma solução melhor oferecida)
Existe uma limitação técnica? Ou apenas uma falta de solicitação de pull?

Afinal, meus arquivos do Compose 2.1 ainda estão funcionando bem.

Não apenas isso, mas o changelog diz "isto foi removido, veja 'como atualizar' para detalhes". Eu vejo "como atualizar" para, você sabe, detalhes sobre como atualizar, e o que isso diz é "ver 'extensão de serviços' para detalhes". Eu vou para "estendendo serviços" imaginando que finalmente verei uma maneira de estender meus arquivos, apenas para ver "isso foi removido, consulte o changelog para detalhes".

Nesse ponto, parece uma piada cruel que o redator da documentação está pregando.

Em última análise, o formato de "pilha" não é controlado aqui e faz parte da Docker CLI.

Eu pessoalmente não sei o motivo pelo qual ele foi excluído da v3 ... Eu também não acho que vi alguém realmente tentar adicioná-lo.
Pode ser melhor trazer isso à tona em docker / cli ... talvez até mesmo apenas um PR com uma alteração de documento de alto nível que age como se o recurso estivesse lá para que possa ser discutido e a implementação possa ser adicionada assim que o design for aprovado .

Basicamente, se alguém quiser, faça um PR. Sugiro a alteração do documento apenas para garantir que você não perca muito tempo caso seja rejeitado ... já que, novamente, não tenho certeza por que foi omitido da v3.

O mesmo que acima. Esperando que isso seja resolvido antes de usar docker-compose novamente.

+1 conserte isso, nós estendemos os arquivos de composição com base e não podemos usar o compose para swarm por causa disso.

+1 para estende o recurso

Alguma novidade sobre isso?

Ainda esperando por isso

Mesmo aqui. Ainda esperando.

Qualquer atualização?

Alguma vez foi dada uma razão para a retirada?

Na segunda-feira, 5 de agosto de 2019, 11h10, Jaykishan, [email protected] escreveu:

Qualquer atualização?

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/31101?email_source=notifications&email_token=ABOE6GA4CXY6ESMZMTDSFGDQC74CZA5CNFSM4DANZGS2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD3RLFLQ#issuecomment-518173358 ,
ou silenciar o tópico
https://github.com/notifications/unsubscribe-auth/ABOE6GCEFFJ3SOLDWRWX2IDQC74CZANCNFSM4DANZGSQ
.

Qualquer atualização?

então .. são quase 3 anos ...
mas ainda tenho esperança de que vá pousar: D

Deve haver algum tipo de alternativa para estender, se ele não voltar. Por que não permitir serviços abstratos? O formato do arquivo seria simples e todas as declarações de serviço estariam em um arquivo. Você poderia usar serviços abstratos em conjunto com a capacidade do yaml de adicionar aliases para um nó (por meio de um & ) reutilizar esses aliases por meio do operador <<: .

Por que 3 anos !! parece que você está trabalhando e se concentrando em coisas com as quais ninguém se preocupa

alguma atualização disso?

Isso é patético. Terraform usa composição - então é factível, por que compor não é capaz de seguir esta boa prática de design ?!
Composição dos Módulos Terraform
Práticas recomendadas do Terraform

"patético", legal.

@ Cristian-Malinescu Vá em frente, implemente por favor.
Este é um software gratuito e de código aberto.

Em vez de reclamar como todos neste chat.
Isso simplesmente não agrega nenhum valor aqui, realmente.
Como disse várias vezes, ninguém queria implementar isso até agora,
então é apenas um problema que outra pessoa deveria consertar, obrigado.

@luckydonald Obrigado por afastar @Cristian-Malinescu com uma resposta fácil / passivo-agressiva, é, como sempre, não estar ajudando. @ Cristian-Malinescu É capaz de fazer como já foi feito antes, mas removido, deve haver (espero) uma razão. Há alguém neste tópico realmente na equipe docker-compose para que possa esclarecer o matéria?

Foi mencionado o tópico e o aproveitamento da funcionalidade YAML suportada.

Achei que esse exemplo pudesse ajudar.

@nomasprime, obrigado por esse achado! Eu estava decidindo entre v2 e v3 para meu projeto, e isso resolveu o grande dilema neste tópico. Surpreso que essas soluções alternativas não são mencionadas nos documentos oficiais para o recurso de extensão de serviços.

Boa, parece uma boa oportunidade de usar o link Request docs changes na barra de navegação direita da página de documentos.

@nomasprime Sim, essa ideia já existia neste tópico antes.

Se isso pudesse ser combinado com um mecanismo de carregamento de arquivo para outros arquivos yml, isso é tudo o que é realmente necessário para ter toda a funcionalidade depends antiga.

Veja acima, por exemplo, https://github.com/moby/moby/issues/31101#issuecomment -413323610

Não seria muito _legível_, mas seria pelo menos _possível_.

@nomasprime, obrigado por esse achado! Eu estava decidindo entre v2 e v3 para meu projeto, e isso resolveu o grande dilema neste tópico.

@arseniybanayev O artigo no meio fala apenas sobre a v3, mas as versões mais recentes da v2 também suportam âncoras e campos de extensão . No meu caso, escolhi a v2 (2.4 mais especificamente) porque uso docker-compose e não swarm (e a v3 não oferece suporte a alguns recursos da v2, como limitar a memória do contêiner )

e v3 não oferece suporte a alguns recursos da v2, como limitar a memória do contêiner

v3 suporta limitação de memória, mas o campo está em deploy -> resources -> limits https://docs.docker.com/compose/compose-file/#resources

@thaJeztah, quero dizer, por docker-compose (porque não estou usando o swarm no projeto a que me referi no meu comentário anterior). O desdobramento do IIRC é apenas para enxame, não é?

Faria sentido criar uma configuração separada para swarm e local? Parece que esses dois estão em conflito um com o outro. Compreensivelmente, o Docker gostaria que o uso do swarm aumentasse, mas muitas pessoas usam o compose apenas para desenvolvimento local.

Eu, pelo menos, nunca usei contêineres de enxame e execução na produção com ECS, k8s ou GAE.

A maioria das opções deve ser traduzível / utilizável para os serviços swarm / kubernetes e para contêineres implantados por meio de composição. Eu teria que verificar por que os limites de memory não seriam aplicáveis ​​para docker-compose

ainda faltando o recurso extends, mas para meu caso de uso principal, mudei para vários arquivos de composição do docker por meio do COMPOSE_FILE env. Eu o uso principalmente para usar a mesma base docker-compose.yml para dev e prod com senhas ou configurações diferentes.

exemplo:

  • no dev: export COMPOSE_FILE= docker-compose.yml` # default
  • na produção: export COMPOSE_FILE= docker-compose. yml: docker-compose.prod.yml `# usa ambos os arquivos yaml

Em docker-compose.prod.yml , acabei de sobrescrever os vars env com as senhas de produção.

Esta configuração é simples e não preciso adicionar sempre vários "-f" ao comando docker-compose . Eu só preciso definir COMPOSE_FILE env var diferente no computador dev e no servidor e git ignorar o arquivo docker-compose.prod.yml.

Ainda esperando :)

Tenho usado isso como uma forma de estender:

docker-compose \
  -f ./docker/base.yml \
  -f ./docker/extended.yml \
  up

Mas estender no arquivo seria melhor, sem a necessidade de um script bash extra.

Também tenho usado isso para estender dinamicamente a partir do script bash:

extended_docker_compose="
  version: '3.5'
  services:
    my-service:
      restart: always
"

echo "$extended_docker_compose" | docker-compose \
  -f ./docker/base.yml \
  -f /dev/stdin \
  up

@ dave-dm, essas são substituições antigas!

Eu acredito que este é um caso de uso válido em potencial para extensões

https://github.com/NerdsvilleCEO/devtools/blob/master/doctl/docker-compose.yml#L10

Eu tenho um docker-compose wrapper que uso para um ambiente de serviços https://github.com/nowakowskir/docker-compose-wrapper

EDIT: Outro caso de uso possível é alguém ter uma pilha LAMP / LEMP e deseja estender esses serviços para uso com um serviço específico, como o wordpress

Ainda estou esperando desde 2017 enquanto explora as alternativas de composição do docker.

@nomasprime Sim, essa ideia já existia neste tópico antes.

Se isso pudesse ser combinado com um mecanismo de carregamento de arquivo para outros arquivos yml, isso é tudo o que é realmente necessário para ter toda a funcionalidade depends antiga.

Veja acima, por exemplo, # 31101 (comentário)

Não seria muito _legível_, mas seria pelo menos _possível_.

@luckydonald, obrigado por apontar. Estranho não haver funcionalidade de inclusão de YAML embutida , certamente resolveria muitos problemas.

Parece que seria muito fácil implementar uma solução de terceiros, embora não tenha certeza de por que isso não foi trazido para a v3 🤷‍♂

Um pequeno lembrete de que muitas pessoas gostariam deste recurso :)

Qual é a razão para não portá-lo para v3 btw?

Eu esqueci, mas há uma razão real para que ele tenha sido levado embora?

Na quarta-feira, 6 de maio de 2020, 23:14, Julien Marechal, [email protected] escreveu:

Um pequeno lembrete de que muitas pessoas gostariam deste recurso :)

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/31101#issuecomment-624919070 ou
Cancelar subscrição
https://github.com/notifications/unsubscribe-auth/ABOE6GGDIVGATP734YJA4UTRQHOLJANCNFSM4DANZGSQ
.

A maneira como as âncoras do yaml lidam com esse caso de uso é um pouco inconveniente em comparação com extend . Seu poder, na minha opinião, veio em grande parte da fusão recursiva de elementos. As âncoras levam você talvez 75% do caminho até lá - elas não fundem yaml recursivamente; toda a sua fusão acontece no nível superior. Fazer referência a um modelo de serviço ancorado e, em seguida, redefinir o bloco environment resultará na substituição do bloco de ambiente do serviço ancorado em vez de mesclá-lo. Você precisará ancorar e fazer referência a cada dicionário em uma árvore recursiva de dicionários para corresponder ao comportamento da palavra-chave extend .

Um exemplo:

# anchors for the service, environment, deploy, and deploy.placement blocks
# you'll need an anchor for every dict that you want to merge into
x-common-app: &common-app
  image: app:1.0
  environment: &common-app-environment
    common_option: a
    overwrite_option: b
  deploy: &common-app-deploy
    max-replicas-per-host: 3
    placement: &common-app-deploy-placement
      constraints:
        - 'node.labels.app_host==true'

services:
  myapp: << *common-app
    environment: << *common-app-environment
      foo: bar
      baz: xyzzy
      overwrite_option: quz
    deploy: << *common-app-deploy
      replicas: 15
      placement: << *common-app-deploy-placement
        preferences:
          - spread: node.labels.region

# The above yields the following:
services:
  myapp:
    image: app:1.0
    environment:
      common_option: a
      overwrite_option: quz
      foo: bar
      baz: xyzzy
    deploy:
      replicas: 15
      max-replicas-per-host: 3
      placement:
        constraints:
          - 'node.labels.app_host==true'
        preferences:
          - spread: node.labels.region

Pode não parecer tão chato neste exemplo, mas fica chato e menos legível se você estiver modelando vários (10+) serviços de um bloco de extensão.

Em minha mente, um cenário ideal é uma combinação da abordagem âncora yaml e a abordagem extend - permitir extend ing apenas de um bloco de campo de extensão prefixado x- nível superior, com as características de mesclagem mais inteligentes.

Em minha organização, encontramos âncoras yaml um pouco sintaticamente desleixadas, então basicamente reimplementamos o recurso extend em um script python externo. Isso funciona para nós, mas é uma maneira idiota de lidar com alguma coisa. Da mesma forma, tivemos que criar nossas próprias ferramentas externas para lidar com a remoção de depends_on para pilhas v3 / Swarm.

Tenho feito muito gitlab CI YAML recentemente. Ele tem exatamente esses recursos, que são muito bons para obter modelos e configurações finais legíveis e gerenciáveis:

  • Você pode incluir outros arquivos YAML (bom para modelos)
  • Você pode estender (mesmo entre projetos / usando recursos remotos por meio de https). A documentação estendida descreve exatamente o que @ a-abella descreve para o formato de composição.
  • Você também pode "se esconder" de ser considerado o verdadeiro. No formato de composição é x- , no gitlab CI é um . .

Este é o conjunto exato de recursos que torna esses arquivos suportáveis.

Cheguei a esse problema a partir dos docs do docker, no meu caso, queria modelar minha configuração de docker-compose e, como uma 'solução alternativa', segui o conselho acima e decidi procurar um programa de modelos existente. Eu não vou receber essas nossas horas de volta, então estou detalhando um pouco do que encontrei aqui, independentemente de qualquer discussão sobre esta solicitação de recurso real, no entanto, pode ser que os envolvidos sintam o uso de um sistema de modelo baseado em YAML para gerar um arquivo de composição em vez de integrar esse recurso em docker-compose si pode ser mais apropriado em termos de encapsulamento e escolha da ferramenta certa para o trabalho.

Para algum contexto, estou usando um proxy reverso básico com Let's Encrypt e vários contêineres de aplicativo (Nextcloud por enquanto, um para mim e alguns separados para amigos) - neste caso, eu queria fazer um modelo dos contêineres Nextcloud, então que evito erros e duplicação com pressionamentos de tecla para configurações muito semelhantes. Os seguintes pacotes foram os que experimentei:

ytt parece muito abrangente e é a única opção para usar YAML nativamente. Parecia poderoso e a ferramenta certa para o trabalho e usa Starlark, um superconjunto do Python, diretamente dentro do arquivo YAML para executar o processamento. No entanto, depois de não muito tempo, o modelo ficou muito confuso, e a confusão de fragmentos de código e fragmentos de YAML, além da mistura de tipos de dados Python como dicionários e matrizes e fragmentos YAML (que parecem ser processados ​​como texto, um pouco como usar um mecanismo de template HTML que gera tags como strings) eventualmente resultou em muitos erros e um arquivo muito confuso. Dhall também parece muito abrangente e usa uma linguagem nativa exclusiva que pode ser impressa em uma variedade de formatos; Parece mais uma linguagem de metaprogramação do que um sistema de template, entretanto, dado que a sintaxe é funcional e é bem rigidamente tipada, ela rapidamente se tornou mais complexa do que valia a pena para um template simples para YAML não estruturado. Como o que parece um pouco com uma mistura de JSON e Haskell, exigiu muito pensamento para trabalhar o que eu precisava fazer na linguagem.

Curiosamente, algo que era difícil com Dhall e ytt era usar nomes de campo parametrizados, ambos teriam funcionado bem de outra forma, mas eu preciso que o nome da minha instância apareça nos nomes dos serviços e nos nomes dos volumes, e em ambos alcançar isso era um tanto feio; usar argumentos para os valores em um hash é fácil, mas usar esses argumentos nos nomes das chaves era complicado ou não consegui descobrir como fazer isso de forma organizada, além disso, Dhall reforça a segurança de tipo e isso simplesmente vai contra esse conceito. Com o Jsonnet, era tão simples quanto colocar a expressão entre colchetes.

O CUE e o Jsonnet são ambos orientados para JSON, no entanto, executá-los por meio de um conversor não é nem um pouco difícil, e parece que, como o Dhall, o CUE tem muitos recursos poderosos e nasceu de deficiências no Jsonnet, embora já esteja no meio da documentação , tornou-se aparente que já era um exagero; talvez com muito mais tempo para aprendê-lo adequadamente, seria a opção superior, mas parece que o CUE é mais orientado para validação e esquemas do que um trabalho de modelo simples, então mudei rapidamente para o Jsonnet e terminei o trabalho bem rápido.

Finalmente, só depois de ter concluído tudo isso é que percebi o tempo todo que estivera comparando essas ferramentas à simplicidade das tags Liquid ou modelos HTML semelhantes, que provavelmente poderia simplesmente ter usado o Liquid em primeiro lugar. Eu só usei no contexto de um site Jekyll, então nunca me ocorreu obter um pacote autônomo, no entanto, com looping e listas básicas e a capacidade de avaliar expressões diretamente em texto no local, isso provavelmente teria foi muito melhor também para o trabalho; Jsonify provavelmente superior para JSON, mas o Liquid poderia operar em YAML puro e assim o arquivo se tornaria mais legível novamente.

+1 docker-compose foi uma inspiração por trás da solução sob medida que implementei no trabalho desde que este tíquete foi criado para dar suporte à migração de um grande número de envs de teste para k8s. Tive muito cuidado para evitar sinos e assobios, mas rapidamente justifiquei um recurso análogo. A discussão filosófica (composição versus herança etc.) me parece uma distração do bom senso (com o benefício em retrospectiva - ainda não resolvida quase 3 anos depois). Evidentemente, é exigido por pessoas que podem continuar a usar docker-compose.

+1: +1:

Eu usei esse recurso muito antes para dev / test / ci ambientes, onde eu poderia estender de um arquivo de composição em caminhos de subdiretório de ./config/{dev,test,ci}/compose.yaml . Eu teria um .env que tivesse COMPOSE_ENV=dev , mas os desenvolvedores poderiam substituir e, obviamente, eu substituiria ci .

Estou chocado em descontinuar o recurso e não substituí-lo por algo que pode fazer algo semelhante. Talvez apenas nos permita usar o jinja2 e fazer o que quisermos. Espero que o Docker-Compose seja menos anti-SECO. : '(

Parece que extends é compatível com docker-compose desde a v1.27 (https://github.com/docker/compose/pull/7588).

Um caso de uso em que uso o recurso intensamente é para criar versões de imagens do docker para código. Meus arquivos docker dev e prod compose se estendem de docker-images.yml, onde apenas o serviço básico é listado e uma versão marcada da imagem do serviço.

Não encontrei uma solução fácil para isso na v3.

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