Moby: Como faço para combinar várias imagens em uma via Dockerfile

Criado em 29 dez. 2013  ·  97Comentários  ·  Fonte: moby/moby

Eu tenho vários Dockerfiles para construir imagens que, por exemplo, configurar um cliente postgresql, configurar um ambiente de aplicativo python genérico

Quero fazer um Dockerfile para meu webapp python que combine ambas as imagens e execute mais alguns comandos

Se entendi os documentos corretamente, se eu usar FROM uma segunda vez, começo a criar uma nova imagem em vez de adicionar a atual?

arebuilder kinfeature

Comentários muito úteis

Eu posso ver como fazer isso, ou seja, genericA --> specificA mas há alguma maneira de fazer algo como:

genericA --
            \
             ---> specificAB
            /
genericB --

?

Todos 97 comentários

você os acorrenta :)

então, por exemplo, se você tiver um Dockerfile que configura seu cliente postgres genérico e env de aplicativo genérico python, você marca o resultado dessa compilação (por exemplo, mygenericenv ) e, em seguida, seus Dockerfiles subsequentes usam FROM mygenericenv .

por exemplo

## Dockerfile.genericwebapp might have FROM ubuntu
cat Dockerfile.genericwebapp | docker build -t genericwebapp -
## Dockerfile.genericpython-web would have FROM genericwebapp
cat Dockerfile.genericpython-web | docker build -t genericpython-web -
## and then this specific app i'm testing might have a docker file that containers FROM genericpython-web
docker build -t thisapp .

Eu posso ver como fazer isso, ou seja, genericA --> specificA mas há alguma maneira de fazer algo como:

genericA --
            \
             ---> specificAB
            /
genericB --

?

Não por qualquer meio oficial, mas algumas pessoas tiveram sorte em modificar manualmente a hierarquia de imagens para conseguir isso (mas se você fizer isso, você o faz por sua própria conta e risco e consegue manter todas as peças).

A razão pela qual isso não será suportado oficialmente é porque imagine que eu queira pegar o "ubuntu" e enxertar "centos" por cima. Haverá muitos conflitos divertidos causando um pesadelo de suporte, então se você quiser fazer coisas assim, você está sozinho.

Ok, entendo por quê. Eu estava procurando por blocos combináveis ​​de funcionalidade, mas talvez este não seja o caso de uso do Docker ... parece que eu deveria usá-lo para configurar os contêineres brutos e executar algo como ansible ou saltstack no topo para configurar o software neles.

A ideia por trás dos contêineres é que a menor unidade de composição real é o contêiner. Ou seja, um container é a menor coisa que você pode produzir de antemão, sem saber com o que mais ele será combinado, e ter fortes garantias de como ele se comportará e como interagirá com os outros componentes.

Portanto, qualquer unidade menor que um contêiner - seja um ruby ​​ou script de shell, uma árvore de origem c ++, um binário por conta própria, um conjunto de arquivos de configuração, um pacote de sistema, etc. - não pode ser composta com segurança, porque se comportará muito diferente dependendo de suas dependências de construção, dependências de tempo de execução e quais outros componentes fazem parte da composição.

Essa realidade pode ser parcialmente mascarada pela força bruta. Essa força bruta pode ser pragmática e "boa o suficiente" (Makefile gigante que detecta tudo automaticamente para uma compilação mais portátil do seu aplicativo) ou excessivamente grandiosa ("vamos modelar com antecedência cada permutação possível de cada dependência e interferência entre componentes e expressar em uma abstração de alto nível! ")

Quando você conta com Ansible, Chef ou qualquer outro gerenciamento de configuração para criar "componentes combináveis", você está contando com uma abstração que vaza: esses componentes não são, de fato, combináveis. De um sistema para o outro, eles produzirão construções que se comportam de maneira diferente em um milhão de maneiras. Toda a abstração extra no final comprará muito pouco para você.

Meu conselho é focar em 2 coisas: 1) o código-fonte e 2) o contêiner executável. Estes são os únicos 2 pontos confiáveis ​​de composição.

No domingo, 29 de dezembro de 2013 às 13h46, anentropic [email protected]
escreveu:

Ok, entendo por quê. Eu estava procurando por blocos combináveis ​​de funcionalidade, mas talvez este não seja o caso de uso do Docker ... parece que eu deveria usá-lo para configurar os contêineres brutos e executar algo como ansible ou saltstack no topo para configurar o software neles.

Responda a este e-mail diretamente ou visualize-o no GitHub:
https://github.com/dotcloud/docker/issues/3378#issuecomment -31326172

Obrigado por dar mais perspectiva.

Então você está dizendo que, para reutilizar partes de Dockerfiles, a única ferramenta disponível é copiar e colar? Vindo de um ponto de vista mais 'dev' do que 'ops', parece um pouco errado.

Talvez seja um erro ter o índice público de imagens, parece que você pode compartilhar blocos de construção reutilizáveis ​​vagamente análogos às receitas do Chef, mas minha experiência até agora não é útil porque:
a) para a maioria das imagens, não há informações sobre o que ele faz e o que está dentro
b) os documentos encorajam o comprometimento do seu trabalho com o índice (para que você possa puxá-lo mais tarde), embora o que você fez provavelmente não seja útil para os outros, estou supondo que a maior parte do que está lá provavelmente não vale a pena compartilhar

Acho que os documentos não orientam você a usar o Docker de maneira sensata no momento

@anentropic A maneira certa de fazer isso com Dockerfiles é criando várias imagens com vários Dockerfiles.
Aqui está um exemplo: Dockerfile 1 constrói uma imagem genérica em cima de uma imagem base do Ubuntu, Dockerfile 2 usa a imagem resultante do Dockerfile 1 para construir uma imagem para servidores de banco de dados, Dockerfile 3 usa a imagem do servidor de banco de dados e a configura para uma função especial .

docker build deve ser muito fácil de executar e complexidade desnecessária não deve ser adicionada.

O índice público de imagens é extremamente útil. As imagens do Docker geralmente são destinadas a executar um serviço ou um grupo de serviços que não podem ser executados em contêineres separados. Normalmente, você pode obter uma imagem, executá-la e colocar algum software útil em funcionamento sem muito esforço.

Entendido ... então, no cenário que descrevi com arte ascii acima, a maneira Docker seria:

  • comece com Dockerfiles para imagens independentes GenericA e GenericB
  • para fazer uma imagem SpecificAB eu copiava e colava o conteúdo do GenericB Dockerfile em um novo Dockerfile que começa com: FROM GenericA

O problema que vejo é que se a 'receita' (para tomar emprestado um termo do Chef) para GenericB for bastante complexa e tiver muitas etapas, não há como compartilhar essas informações, exceto publicando o Dockerfile _to Github_ que outros podem _copiar e colar_ as partes relevantes em seu próprio Dockerfile.

Você já tentou usar o índice público? Por exemplo, fiz uma pesquisa por "postgres" ... como julgo a utilidade de (ou distinguir de alguma forma entre) imagens como estas:

?

Que valor eles fornecem quando a única maneira de ter certeza de que tenho um servidor Postgres configurado da maneira que desejo, em uma imagem de base específica, sem nada suspeito escondido nela, será criá-lo do zero.

Posso ver o valor de algumas imagens de base 'oficialmente abençoadas' em um índice público. Eu posso ver o valor de ter um índice privado de minhas próprias imagens personalizadas prontas para extrair.

Mas parece uma pena que não haja nenhuma maneira (além de copiar e colar) para compartilhar a série de comandos no Dockerfile como uma receita ... como a sugestão de um comando 'incluir' que foi rejeitado aqui https: // github .com / dotcloud / docker / pull / 2108

@anentropic Você pode usar uma imagem confiável e também pode encontrar um Dockerfile postgres para construir a imagem você mesmo.

As imagens geralmente são mais úteis quando você personaliza o Dockerfile para garantir que atendam exatamente às suas necessidades. É por isso que você descobriu que mais usuários carregaram uma imagem do mesmo software para o registro.

Imagens específicas existentes, como as imagens do postgres, podem não atender às suas necessidades particulares, mas também existem imagens de base e podem ser usadas imediatamente para construir algo que seja útil para você.

Imagens de base como ubuntu , centos e algumas imagens de stackbrew/* são imagens que você pode usar para construir o que precisa.

Um exemplo de uma ótima imagem pronta para usar é stackbrew/registry . Esta imagem permite que você experimente um registro privado do Docker assim que docker pull stackbrew/registry e docker run -p stackbrew/registry terminem a execução.

O objetivo do Docker é ajudar na implantação e na preparação do ambiente onde seu software é executado. Isso significa que as compilações são lineares e feitas apenas durante a compilação inicial, mas você executará exatamente o mesmo software todas as vezes.

Os sistemas de gerenciamento de configuração podem permitir que você faça algo mais ou empregar alguns outros truques, mas eles não são tão "imutáveis" e você pode acabar tendo dois hosts com diferenças sutis que não são detectadas pelo software de gerenciamento de configuração.

Odeio necro um tópico antigo, mas queria oferecer algo que IMHO ajude a resolver o problema dos cartazes originais e pode ajudar outras pessoas que procuram uma solução semelhante para este problema aqui.

Vamos supor, para simplificar, que todos eles usam a mesma imagem de base R . Imagine que tenho o serviço A e o serviço B . Eu os quero em imagens separadas do Docker e ambas na mesma imagem do Docker.

Escreva um script para instalar o serviço A e um script separado para instalar o serviço B . Em seguida, tenha um repositório git com o script para A e outro para o script B . Crie repos git para todas as três imagens do Docker que serão construídas. Cada um contém submódulos git com os scripts de instalação que serão usados. Cada Dockerfile irá simplesmente ADD um script de instalação e então RUN o script de instalação e fará isso para um ou ambos os scripts. Se você deseja remover o (s) script (s) da imagem, fixe-o depois de executá-lo.

Dessa forma, há uma cópia de cada script de instalação e todas as imagens do docker que você deseja usá-los. Isso evita a cópia desnecessária de código e mantém a carga de manutenção mínima. A única duplicação de esforço é mover para cima o commit usado pelos submódulos, o que é significativamente melhor do que a alternativa e provavelmente poderia ser automatizado.

Acho que não entendi como isso funciona, então estou respondendo para obter esclarecimentos. Quero usar o Ubuntu 11 com as imagens oficiais do dock do selênio. Eles usam o Ubuntu 15.

https://github.com/SeleniumHQ/docker-selenium/blob/master/Base/Dockerfile

Qual é a maneira correta de fazer isso? Para clonar esse repo e editar todos os arquivos para dizer Ubuntu 11 e não 15? Isso não pode estar certo, pode? Isso significaria que todas as pessoas que discordam de algum aspecto das imagens oficiais não podem fazer uso delas sem duplicar o código delas. Acho que entendi errado, alguém pode explicar? Qual é a maneira certa de usar a imagem oficial de selênio com o Ubuntu 11?

@rjurney sim, é assim que funcionaria; no seu exemplo, todo o Dockerfile é desenvolvido com o ubuntu: 15.04 em mente; esses pacotes estão disponíveis no Ubuntu: 11? Eles trabalham? O selênio roda neles? Provavelmente, modificações precisam ser feitas no Dockerfile para que funcione em outra versão do Ubuntu.

"trocar" a imagem de base de uma imagem existente também não funcionaria, porque o Docker armazena apenas as _diferenças_ entre a imagem de base e a imagem. Usar uma imagem de base diferente, portanto, leva a resultados imprevisíveis (por exemplo, "remover arquivo X", onde "arquivo X" existe na imagem de base original, mas não na imagem de base que você selecionou). Além disso, os pacotes / binários em imagens construídas "sobre" uma imagem base são pacotes construídos para _tela_ versão, esses binários podem não ser compatíveis com uma imagem base diferente.

Isso significaria que todas as pessoas que discordam de algum aspecto das imagens oficiais não podem fazer uso delas sem duplicar o código para elas

sim. As imagens oficiais são apoiadas pelos mantenedores dessas imagens (que, neste caso, são os mantenedores do Selenium). Se você acha que são necessárias alterações nessas imagens, a melhor maneira é abrir uma solicitação de recurso em seu repositório. Se essa solicitação de recurso não for aceita, você provavelmente deve construir sua própria versão.

(Observe também que não há imagem oficial de ubuntu:11 )

No resto do mundo do software, herança única não é vista como
adequado para expressar razoavelmente a semântica necessária. Isso leva a muito código
duplicação, o que seria considerado um bug. Por que isso é visto como
aceitável para docker? Mesmo se você estiver construindo um serviço de cada vez,
a composição é necessária no nível do sistema operacional. Eu não quero bater um
cavalo morto, mas esse limite parece um pouco extremo. Pode ser melhor
expressa como uma prática recomendada? Como resultado do rigor desta
decisão, alguém vai construir uma ferramenta que faz composição ou múltipla
herança e os expressa por meio de herança única e duplicação.
Ter este local fora do docker adequado não servirá para a comunidade docker.

Na quarta-feira, 9 de dezembro de 2015, Sebastiaan van Stijn <
notificaçõ[email protected]> escreveu:

@rjurney https://github.com/rjurney sim, é assim que funcionaria; dentro
no seu exemplo, todo o Dockerfile é desenvolvido com o ubuntu: 15.04 em mente;
esses pacotes estão disponíveis no Ubuntu: 11? Eles trabalham? O selênio corre
neles? Provavelmente, modificações precisam ser feitas no Dockerfile
para fazê-lo funcionar em outra versão do Ubuntu.

"trocar" a imagem base de uma imagem existente também não funcionaria, porque
O Docker armazena apenas as _diferências_ entre a imagem base e o
imagem. Usar uma imagem base diferente, portanto, leva a imprevisíveis
resultados (por exemplo, "remover arquivo X", onde "arquivo X" existe na base original
imagem, mas não na imagem de base que você selecionou). Além disso, os pacotes / binários
em imagens construídas "em cima" de imagens de base, são pacotes que são construídos
para _tessa_ versão, esses binários podem não ser compatíveis com um diferente
imagem de base.

Isso significaria que todos com qualquer desacordo com qualquer aspecto do
imagens oficiais não podem fazer uso deles sem duplicar o código para eles

sim. As imagens oficiais são apoiadas pelos mantenedores dessas imagens
(que neste caso, são os mantenedores do Selenium). Se você acha que muda
são necessários para essas imagens, a melhor maneira é abrir uma solicitação de recurso em
seu repositório. Se essa solicitação de recurso não for aceita, você deve
provavelmente construa sua própria versão.

(Observe também que não há imagem oficial do Ubuntu: 11)

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

A herança múltipla de extremos e incompatibilidades.

12749 foi a última tentativa de adicionar essa funcionalidade - acabou rejeitada porque há outro trabalho a ser feito primeiro.

Há muito trabalho sendo feito no construtor, incluindo a habilitação de compilações orientadas para o cliente, o que pode abrir bastante isso.

Dockerfiles de herança única funciona para a (vasta) maioria dos casos de uso, portanto, não há pressa em aprimorar isso. Precisa ser feito de maneira correta e deliberada.
E com base em seus comentários acima, eu diria que você realmente não precisa de herança múltipla, apenas uma maneira de especificar uma imagem de base na qual o Dockerfile é executado sem duplicar o código existente.

Isso iria satisfazer minhas necessidades, sim. Ser capaz de modificar alguma propriedade do
cadeia de dockerfiles.

Ok, fico feliz em saber que você está por dentro disso. Obrigado pela sua paciência :)

Na quarta-feira, 9 de dezembro de 2015 às 9h59, Brian Goff [email protected] escreveu:

@rjurney https://github.com/rjurney herança múltipla também é
extremamente complexo e não apenas algo que você adiciona sem pensar
para consequências, casos secundários e incompatibilidades.

12749 https://github.com/docker/docker/pull/12749 foi o mais recente

tentativa de adicionar essa funcionalidade - finalmente recusada porque há
outro trabalho a ser feito primeiro.
Há muito trabalho sendo feito no construtor, incluindo habilitar
compilações orientadas para o cliente que podem abrir um pouco isso.

Dockerfiles de herança única funcionam para a (vasta) maioria dos casos de uso,
como tal, não há pressa em aumentar isso. Precisa ser feito corretamente e
deliberadamente.
E com base em seus comentários acima, eu diria que você não precisa de vários
herança, apenas uma maneira de especificar uma imagem de base que o Dockerfile é executado
contra sem duplicar o código existente.

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

@rjurney Onde você consegue suas informações. Que eu saiba, Java nunca teve herança múltipla e nunca terá. Tenho certeza de que o mesmo é verdadeiro para muitos idiomas. Muitos consideram a herança múltipla extremamente prejudicial, pois pode resultar em um código quase impossível de ser previsível. O mesmo seria válido para um contêiner docker.

A meu ver, o que precisamos para docker não é o conceito de herança múltipla, mas o conceito de inclusão ou dependências externas. por exemplo, você pode montar contêineres em tempo de execução. O que é realmente necessário é uma maneira de fazer o equivalente com imagens. Assim, você poderia, por exemplo, ter uma imagem definida para ser baseada no Fedora 22 e montar uma imagem oracle para adicionar funcionalidade de banco de dados.

Isso pode ser feito com bastante sucesso ao executar contêineres, mas simplesmente não há sintaxe para especificá-lo com imagens. Portanto, até o tempo de execução, não há como o docker saber sobre essas dependências ou, de qualquer forma, gerenciá-las para você.

Observe que mencionei herança e composição múltiplas.
Composição é a forma preferida de fazer isso, definitivamente.

Eu concordo com tudo o mais que você disse, então +1.

Na quarta-feira, 9 de dezembro de 2015, Bill C Riemers [email protected]
escreveu:

@rjurney https://github.com/rjurney Onde você obtém suas informações.
Que eu saiba, Java nunca teve herança múltipla e nunca terá.
Tenho certeza de que o mesmo é verdadeiro para muitos idiomas. Muitos consideram múltiplos
herança extremamente prejudicial, pois pode resultar em quase impossível
código previsível. O mesmo seria válido para um contêiner docker.

A meu ver, o que precisamos para o docker não é o conceito de múltiplos
herança, mas o conceito de uma inclusão ou dependências externas. por exemplo
Você pode montar contêineres em tempo de execução. O que é realmente necessário é uma maneira de
o equivalente com imagens. Você poderia, por exemplo, ter uma imagem que
foi definido para ser baseado no Fedora 22, e montar uma imagem oracle para adicionar
funcionalidade de banco de dados.

Isso pode ser feito com bastante sucesso ao executar contêineres, mas há
apenas nenhuma sintaxe para especificá-lo com imagens. Então, até o tempo de execução, não há
maneira que o docker pode saber sobre essas dependências ou de qualquer forma gerenciá-las para
vocês.

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

Vou calar a boca depois disso, mas coloquei esse discurso retórico na solicitação pull mencionada anteriormente em vez deste tíquete, por engano. Então, estou colocando aqui.

Alguém vai construir isso. Não aceitar um pull que adiciona INCLUDE atrasará e externalizará esse recurso. Essa deve ser a base da decisão aqui: deve ser dentro ou fora do docker?

Um exemplo vem à mente. No Apache Pig, a equipe tomou a decisão de não incluir loops, apesar de muitas solicitações para eles, porque foi decidido que o Pig deveria ser ótimo para fluxos de dados DAG e é isso. Em vez disso, foi criada uma integração para criar scripts de pigs, para que você pudesse fazer um loop por meio de scripts de qualquer linguagem JVM. Observe que esta foi uma decisão consciente e que alternativas foram buscadas. Este é o processo modelo na minha opinião.

Outro exemplo do Pig vem à mente ... Pig Macros. Eles não existiam e eram 'um porco' até que alguém (ok, eu) começou um tópico sobre como seu projeto de porco grande era incrivelmente feio e que não havia maneira de corrigir esse problema sem gerar o Pig a partir de uma ferramenta externa, que era indesejável. Muitas pessoas concordaram e a equipe do Pig adicionou macros. As macros possibilitam a limpeza de porcos e a comunidade é beneficiada.

Eu sugiro que você aborde a decisão de frente e tenha uma discussão sobre ela, o que não ocorreu aqui ainda, e para localizabilidade provavelmente pertence aqui. Isso vai existir. A duplicação de scripts em idiomas específicos de domínio é terrível. O povo vai exigir isso. Este recurso estará dentro ou fora do Docker? Como você facilitará esse comportamento fora do docker?

Desculpe, provavelmente estou perdendo muito contexto na lista de e-mails, mas como um novo usuário do Docker ... Eu me sinto muito hesitante em fazer muito com o Docker sem a capacidade de compor dockerfiles a partir de receitas existentes. Eu desci essa estrada com Pig e isso quase me matou. Acho que muitas pessoas vão se sentir assim.

Caso alguém se importe ...

A apresentação parcialmente adotada sobre loops e macros no Pig: http://wiki.apache.org/pig/TuringCompletePig
Pig Macro JIRA: https://issues.apache.org/jira/browse/PIG-1793
Interface API para Pig JIRA: https://issues.apache.org/jira/browse/PIG-1333
Um que foi totalmente rejeitado para respeitar o Apache Hive ... adicione SQL ao Pig: https://issues.apache.org/jira/browse/PIG-824

Por fim, tive uma ideia que pode facilitar essa mudança ... e se os arquivos INCLUÍDOS não puderem ser herdados? ou seja, você evitaria objeções, mantendo as coisas super simples. Lide com o resto mais tarde, à medida que mais for aprendido. Pode haver um Dockerfile simples, por exemplo, que instala os pré-requisitos e binários e configura daemons para MySQL no Ubuntu. Se necessário, isso pode ser versionado por versão do Ubuntu e MySQL. Pessoalmente, vou hackear um utilitário para fazer esses INCLUDEs simples e usá-lo para organizar meus dockerfiles dessa maneira. Mal posso esperar para fazer o pedido e reutilizar meu código.

1 para a ideia INCLUIR. Embora eu acredite que proibir a herança apenas mudará o problema, já que agora você seria capaz de modificar a imagem principal da qual está herdando, mas não as outras imagens que incluir. Basicamente, o que faria sentido seria se você pudesse especificar uma imagem para ser "includable" no sentido de que ela não entrega nenhum material do sistema operacional que possa quebrar o material da imagem base existente. Esse sinalizador teria que ser definido pelo processo de compilação do docker e evitaria que imagens sinalizadas não adequadamente fossem incluídas. E quero dizer, vamos enfrentá-lo. Se você está jogando com Dockerfiles, você provavelmente não é uma pessoa que vê sua máquina no primeiro dia, então eu acredito que, embora faça sentido evitar que o usuário final do docker faça coisas estúpidas, deve haver um pouco mais liberdade para os caras que realmente criam essas imagens. E, falando sério, ser capaz de selecionar uma imagem de base e incluir todas as coisas que eu quero para provisionar meu aplicativo seria incrível.

+1 para INCLUIR. Eu simplesmente preciso das imagens nginx e ssh combinadas em um. Por que isso tem que ser tão difícil?

A ideia de que isso não é necessário é francamente confusa a ponto de ser
insincero. A maioria dos usuários usará isso, se for criado. "Adicionar ssh a
ubuntu "e" adicionar nginx ao ubuntu "são tarefas bastante comuns que todos
não precisa se repetir. O que o docker HQ realmente parece dizer sobre isso é,
"Obviamente necessário, mas achamos que vai ficar muito feio. Então fingimos." Isto
seria melhor se você pudesse realmente ser honesto e aberto sobre isso.
Desculpe se estou mal-humorado.

No sábado, 23 de janeiro de 2016 às 18:22, Vazy [email protected] escreveu:

+1 para INCLUIR. Eu simplesmente preciso das imagens nginx e ssh combinadas em um. Por que
isso tem que ser tão difícil?

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

@rjurney vamos esperar pelo spin-out do build; porque dessa forma, haverá mais de uma maneira de construir imagens (e, portanto, pode aparecer um construtor personalizado que faça isso). Um dos motivos pelos quais os mantenedores do docker (trabalhando ou não para o Docker) são brincalhões com isso, é porque acrescentaria complexidade onde queremos adicionar flexibilidade e simplicidade. Ao extrair o construtor, teremos uma melhor separação de interesses (entre construir imagens e executá-las) e muitos casos de uso serão implementados mais livremente em construtores customizados.

Novamente, você está empurrando isso para fora do projeto? Sons personalizados ... não
a forma padrão incluída. Quando na verdade, inclui é uma necessidade simples que
quase todo mundo tem. Repetir-se é complexidade. Herança apenas é
complexidade. Inclui a correspondência de uma necessidade que todos e têm da maneira mais simples
possível.

No domingo, 24 de janeiro de 2016, Vincent Demeester [email protected]
escreveu:

@rjurney https://github.com/rjurney vamos esperar pelo spin-out do build;
porque desta forma, haverá mais de uma maneira de construir imagens (e assim
pode parecer que um construtor personalizado faz isso). Um dos motivos docker
mantenedores (trabalhando ou não para o Docker) são brincalhões sobre isso, é
porque acrescentaria complexidade onde queremos adicionar flexibilidade e
simplicidade. Ao extrair o construtor, teremos uma melhor separação de
preocupação (entre construir imagens e executá-las) e muitos casos de uso
será implementado mais livremente em construtores personalizados.

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

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

+1, combinar imagens seria extremamente útil. Imagine um (Deus me livre) caso de uso C ++. Eu construo um imagine com boost, outro com Qt, todos com o mesmo compilador, etc. Agora digamos que eu queira construir um aplicativo com boost e Qt, eu só preciso combinar os dois e pronto - um ambiente de desenvolvimento pronto. Isso seria incrivelmente útil.

Pessoalmente, acho que essa é uma questão muito importante para não resolver. Dito isso, precisamos obter um bom entendimento de quais são os problemas e o escopo, independentemente de onde seja implementado.

Então, eu vejo esses problemas apresentados pela fusão.

  1. Tratamento de conflitos de mesclagem.
  2. Resolvendo diferentes bases (Ubuntu e CentOS).

Com o primeiro, acho que a resposta simples é não. Para mim, parece complicado e potencialmente problemático e exigiria um conjunto de ferramentas para resolver e ainda pode ser muito mágico. Portanto, se isso fosse adicionado, os conflitos de mesclagem simplesmente falhariam. Suponho que poderia ser revisitado mais tarde, mas isso parece mais problemático do que vale a pena.

Quanto ao segundo caso, parece que você pode adicionar uma restrição de que eles compartilham algumas camadas de base. Agora a questão é: quantos são suficientes. Acho que a resposta correta ao iniciar seria que as duas imagens sendo mescladas devem ter a mesma imagem FROM . Pode ser necessário haver mais restrições aqui, mas não está claro para mim se esses casos não se enquadrariam no problema 1, que foi resolvido simplesmente por não permitir isso.

Existem outros problemas que estou perdendo aqui?

Acho que não deve haver tentativa de fusão ... Não consigo ver isso acontecendo

Uma abordagem mais realista pode ser um tipo de solução de modelo, ou seja, permitir INCLUDE um Dockerfile _fragment_ (que não tem uma cláusula FROM , apenas uma lista de comandos) em um Dockerfile real ... o fragmentos podem ser compartilhados, reutilizados e incluídos em qualquer Dockerfile de imagem de base compatível

Sou completamente novo no Docker e estou aprendendo com humildade. Mas eu pensei que o ponto principal do Docker era construir aplicativos _reutilizáveis_ muito pequenos para depois combiná-los de todas as maneiras para grandes aplicativos finais como em um aplicativo da web. Se for assim, IMHO uma declaração como INCLUDE é obrigatória.

@jmcejuela em muitos casos, "reutilizar" é criar imagens dedicadas a um serviço específico e combinar essas imagens / contêineres para formar seu aplicativo. Os componentes individuais de seu aplicativo são reutilizáveis ​​(possivelmente, apenas a configuração do contêiner é diferente), mas a maneira como você os combina forma o aplicativo real.

@thaJeztah eu entendo, obrigado.

Mas tornando-o concreto como as pessoas postaram antes, digamos que eu construa um aplicativo da web que executa um aplicativo scala (imagem A ), a seguir crie o servidor da web com nginx (imagem B ), e então tenho ssh (imagem C ), e precisa de um aplicativo python extra (imagem D ). Digamos que criei 4 Dockerfiles para cada um. Como faço para combiná-los com o Docker para criar meu aplicativo da web final (imagem E ?)

Eu só preciso de uma maneira simples de fazer isso. Eu não me importo com disputas de filosofia sobre herança múltipla, incluir ou não, compor ou não, etc. Embora certamente eu não gostaria de copiar e colar como foi proposto antes.

Muito obrigado pelo seu tempo. Ainda estou aprendendo Docker.

@jmcejuela, você não combinaria as _imagens_, mas as executaria como contêineres separados e faria com que cooperassem para formar o aplicativo. Você pode fazer isso usando o Docker Compose, que permite definir sua "pilha". Por exemplo, consulte https://github.com/docker/example-voting-app/blob/master/docker-compose.yml (e o README; https://github.com/docker/example-voting-app/ blob / master / README.md)

Para a parte "ssh", realmente depende para que você deseja usá-lo; no geral, os contêineres são considerados "imutáveis", então você não vai fazer ssh em um contêiner e modificá-lo, mas sim girar um novo contêiner para substituir o antigo; os dados que precisam persistir além do ciclo de vida de um contêiner são então armazenados em um volume, para que o novo contêiner possa usar esses arquivos.

@jmcejuela O construtor Docker aceita conteúdo Dockerfile em STDIN, então alguém poderia gerar um "relativamente" facilmente? Se um contexto tiver que ser passado adiante, então tudo deve ser tarado e alimentado em docker build . Pela minha experiência, esta é a maneira mais simples possível de obter uma composição.

Estou desenvolvendo (e brincando com) uma abordagem que se baseia no conceito acima. Um aplicativo nodejs prepara o arquivo TAR na memória (com Dockerfile e arquivos adicionados) e despeja-o em STDOUT. O STDOUT é canalizado para docker build . As partes composíveis são versionadas, testadas e lançadas como módulos NPM. Eu coloquei um exemplo muito curto, que demonstra uma imagem de teste para crond - http://pastebin.com/UqJYvxUR

Obrigado @thaJeztah. No final, eu só preciso de um único arquivo que meus co-desenvolvedores possam executar para ter a pilha dev inteira e, então, poder executá-la no prod também, se necessário. Vou analisar mais profundamente a composição docker.

Além disso, INCLUDE foi proposto há muito tempo (https://github.com/docker/docker/issues/735).

@jmcejuela O fato é que a maioria dos usuários do docker instala e usa ssh para configurar contêineres e corrigir problemas em um contêiner em execução. É assim que o docker é realmente usado.

Só se você estiver fazendo errado, o comando docker exec já existe há um bom tempo e eu nunca mais precisei do ssh desde ...

@anentropic Isso só é válido se você estiver implantando serviços simples sem dependências. Se você tiver uma cadeia complexa de dependências para qualquer serviço, qualquer coisa que envolva aprendizado de máquina, por exemplo, estará duplicando o código para implantar serviços. E não há nenhuma boa razão para você fazer isso. Só porque docker é uma linguagem de domínio específico não significa que a maior parte do conhecimento sobre linguagens de programação é jogada fora e nenhuma das lições antigas se aplica. A sanidade ainda precisa ser importante. Copiar e colar receitas é uma loucura.

Também só é válido se você assinar a visão de mundo de 'serviço único', que não abrange todos os usuários do docker.

@anentropic De acordo com o roteiro do Docker, o provisionamento em execução de contêineres por meio de docker exec pode ser (vir) igualmente errado.

PS O motor rkt atingiu a v1.0.

@rjurney,: 100:

A herança múltipla, seja ela amada ou odiada, é uma característica complexa e, sem dúvida, terá resistência. Incluir transforma os Dockerfiles de uma receita de construção em uma linguagem com problemas de caminho que são desafiadores a resolver.

E se olharmos para o problema de forma diferente. E se pudéssemos " ADD / COPY " selecionar arquivos de outra imagem do docker para uma que está sendo construída. Dessa forma, pode-se aproveitar a reutilização de funcionalidades e evitar a duplicação de código. Como não estamos usando FROM várias vezes em uma imagem, apenas copiando os binários de maneira explícita, isso deve se comportar de maneira bem definida e quando não o fizer é um fracasso. Visto que isso funciona com imagens docker e é capaz de alavancar registros como a solução em oposição a algum novo caminho de pesquisa, espero que esta seja uma proposta razoável. Um bônus adicional é que não precisamos executar novamente o mesmo código várias vezes. Além disso, esperançosamente, uma grande mudança no construtor poderia ser evitada. Pensamentos?

Talvez isso seja proposto em outro lugar, caso em que um link seria bom.

Olá,
Qualquer que seja a solução selecionada, preparar uma imagem de várias fontes independentes é algo que me surpreendeu muito por ser impossível.
Eu teria gostado de pular a preparação da imagem, pois em tempo de execução podemos realizar esse processo, de modo que em tempo de execução um conjunto de imagens seja implantado, sem a necessidade de refazer a imagem toda vez que uma dependência é modificada.
Procurei alternativas, ainda não encontrei nenhuma válida, essa é uma grande lacuna de uso.
Parece muito fácil de executar usando ACI.
Obrigado!

: +1: adoraria uma solução para isso e fico feliz que pelo menos esteja sendo falado. Mesmo que exija que as imagens básicas sejam as mesmas.

Acontece que a cópia de outras imagens é proposta em outro lugar. Este é o problema (https://github.com/docker/docker/issues/18596).

obrigado @jakirkham ..

+1 para funcionalidade de herança múltipla do docker

Acho que o problema que você está enfrentando é que a incapacidade de compor receitas não faz sentido. O Docker Compose é ótimo para usar vários contêineres em um aplicativo. O Docker swarm é ótimo para fazer o mesmo com vários nós. Mas não há como incluir o trabalho de outras pessoas no nível do código-fonte, em muitos casos. Você deve herdar uma vez ou recriá-lo, o que é limitante.

Na sexta-feira, 18 de março de 2016 às 9:01, Alvin Chevolleaux < notificaçõ[email protected]

escreveu:

A resposta de @thaJeztah https://github.com/thaJeztah é muito
esclarecedor. Eu sou novo no Docker e não entendo porque você não pode combinar
várias _imagens_ juntas, mas o Docker Compose parece ser a solução para
combinando vários _containers_ em um aplicativo que eu estava procurando
por.

Acho que o problema para mim é que pensei ter entendido Docker no começo
mas agora estou descobrindo que não. Eu vou voltar e fazer mais um pouco
lendo!

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente ou visualize-o no GitHub
https://github.com/docker/docker/issues/3378#issuecomment -198426036

Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

@rjurney Sim, depois de examinar o Docker Compose um pouco mais, você está correto, essa é exatamente a minha confusão. Por exemplo, há uma imagem PHP e uma imagem Centos, mas nenhuma herança entre imagens diferentes, então é quase tudo ou nada. Na imagem PHP oficial está usando debian:jessie mas eu quero que minha configuração seja baseada em Centos, então parece que se eu quiser usar uma imagem em particular, devo aceitar o resto da configuração ou copiar e colar o Dockerfile de origem e rolar minha própria imagem do zero, não parece haver um meio-termo onde posso misturar e combinar imagens.

EDITAR:
Só para esclarecer, eu entendo porque você não pode misturar imagens baseadas no Ubuntu e Centos, mas não vejo porque você não pode ter algum tipo de estrutura hierárquica. Então, em vez de baixar uma imagem inteira, você apenas baixaria as alterações de uma imagem para a outra.

INCLUDE seria extremamente útil para mim também. Sem ele, tenho que copiar e colar.

@RomanSaveljev Não entendi:

De acordo com o roteiro do Docker, o provisionamento em execução de contêineres por meio de docker exec pode ser (vir) igualmente errado.

Ele não diz que docker exec ficará obsoleto. docker exec sempre foi uma ferramenta de depuração, assim como o SSH em um contêiner do Docker.

Me sinto um tolo por participar disso, mas que diabos ... Vou sugerir de novo:

Por que não simplificamos o problema e começamos implementando INCLUDE para que não permita a herança? Em outras palavras, você só pode incluir arquivos que não tenham DE.

Isso lidaria com muitos casos de uso, e o ímpeto estaria nos arquivos que as pessoas INCLUEM para trabalhar em qualquer sistema operacional razoável. uname existe por uma razão. Essa seria uma primeira etapa, e o feedback sobre essa implementação ajudaria a definir mais detalhes.

Parece uma decisão fácil de tomar. Não seria muito trabalho. Não seria complexo. Direito?

@rjurney é basicamente o que https://github.com/docker/docker/pull/12749 faz

@rjurney : Não se sinta tolo. Embora um INCLUDE não cubra totalmente a pergunta inicial, é um passo na direção certa. Existem vários problemas encapsulados.

  1. Como combinar várias peças de trabalho independente?
  2. Como armazenar essas compilações de forma eficiente?
  3. Como combinar várias peças de trabalho em um nível binário, não em um nível de compilação?

Provavelmente, há mais itens que podem ser adicionados a esta lista. A solução INCLUDE lida com o primeiro marcador. Uma vez implementado, isso estabelece uma estrutura padrão em que a eficiência do armazenamento binário pode ser melhorada de forma transparente para o usuário final. Depois de implementado isso, faz sentido falar sobre ferramentas que fazem as mesmas manipulações diretamente nos arquivos de imagem. No entanto, esta última etapa é muito questionável. Assim que você estiver fazendo isso diretamente nos arquivos de imagem, há um grande potencial de apenas acabar com uma imagem quebrada. No entanto, se for assumido que apenas usuários avançados (aqueles que sabem exatamente o que estão fazendo) farão a terceira opção, isso para mim não parece um acréscimo irracional ... eventualmente.

Para aqueles que querem algo verdadeiramente combinável desta forma, você pode olhar o Nix (NixOS, uma distribuição Linux e sistema de gerenciamento de pacotes). Requer apenas que você recompacte todo o seu software, geralmente compilado a partir do código-fonte, e abandone tudo que você pensava que sabia sobre o Linux;). É um bom sistema, mas dá muito trabalho, visto que poucas pessoas o usam, mas espero sinceramente que pegue.

Como outros já disseram, a composibilidade do Docker é mais sobre a composição no nível de serviço.

: +1: defo vale a pena pensar em um modelo combinável - seria brilhante se você pudesse importar comportamentos para um dockerfile. por exemplo, agora tenho um caso de uso em que desejo incluir o apache thrift em vários contêineres de construção muito diferentes baseados no Alpine Linux - alguns construirão serviços Java, outros PHP e outros Node.

Seria bom ser capaz de incluir a instalação econômica ao invés de copiar e colar - eu acho que posso facilmente extrair para um script de shell e ADICIONAR e EXECUTAR.

Então, como faço para usar as imagens ruby-2.3 e java-8? Eles usam a mesma imagem debian jessie como a base (eu li os dockerfiles). Desejo apenas executar os comandos presentes em ambos. Do jeito que está, eu tive que copiar / colar o Java Dockerfile no Ruby Dockerfile. O aplicativo precisa de ambos, não há absolutamente nenhuma maneira de contornar isso.

Aproveitei a oportunidade para remover alguns comandos do Dockerfile enquanto os colava - eles não eram prejudiciais, mas simplesmente supérfluos, uma vez que o Dockerfile "base" (no qual eu estava colando os comandos) já executava essas etapas. Eu posso, então, meio que ver o argumento de que eu realmente não queria uma imagem "ruby" e "java", na verdade estava construindo uma terceira imagem "ruby + java all-in-one".

No entanto, neste caso específico, os comandos nessas duas imagens parecem ser totalmente compatíveis - se eu simplesmente os concatenasse, eles deveriam funcionar. Seria útil poder especificar tais circunstâncias. Não sou um grande fã da abordagem copiar / colar - no meu caso, os Dockerfiles Java e Ruby eram bastante simples, mas alguns Dockerfiles são muito mais complexos.

No entanto, para todos como eu que desejam esse recurso - posso ver muitas situações em que isso seria problemático. Portanto, não é apenas uma questão de fornecer a capacidade de executar "nginx" e "ssh" na mesma imagem docker - a mesma funcionalidade também permitiria que você execute "debian" e "centos", o que definitivamente não produzirá um imagem viável. Se alguma vez for introduzido, parece que terá que ser uma opção experimental, desativada por padrão, que contém muitos avisos anexados.

Portanto, qualquer que seja a interface para esse recurso, ele teria que deixar bem claro que a responsabilidade em obter os comportamentos reutilizáveis ​​(conjuntos de comandos) corretos é do desenvolvedor do Dockerfile.

EDIT: Ah, perdi a discussão INCLUDE.

Por que não simplificamos o problema e começamos implementando INCLUDE para que não permita a herança? Em outras palavras, você só pode incluir arquivos que não tenham DE.

Isso lidaria com muitos casos de uso, e o ímpeto estaria nos arquivos que as pessoas INCLUEM para trabalhar em qualquer sistema operacional razoável. uname existe por uma razão. Essa seria uma primeira etapa, e o feedback sobre essa implementação ajudaria a definir mais detalhes.

Parece uma decisão fácil de tomar. Não seria muito trabalho. Não seria complexo. Direito?

: +1:

@rjurney é basicamente o que # 12749 faz

: +1: perfeito, ansioso para ver o que isso será capaz de fazer em sua forma final.

Muito interessado neste conceito também. Um mecanismo "INCLUIR" é uma solução muito crua, mas honestamente representaria um grande passo em frente na manutenção de um conjunto de arquivos docker.

Pessoalmente, não gostaria que ele _fail_ quando encontrar um FROM , gostaria que _ignore_ o FROM e apenas aplicasse o resto dos comandos em sequência.

Que isso não tenha acontecido ainda sem o suporte do FROM é um código aberto
caricatura.

Em quinta-feira, 19 de janeiro de 2017 às 10:19, Ken Williams [email protected]
escreveu:

Muito interessado neste conceito também. Um mecanismo "INCLUIR" é muito
solução bruta, mas honestamente representaria um grande passo em frente
manutenção de um conjunto de arquivos docker.

Pessoalmente, não gostaria que falhasse ao encontrar um DE,
deseja que ele ignore o FROM e apenas aplique o resto dos comandos em
seqüência.

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/3378#issuecomment-273854850 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AACkpS8-EQ7r0BHid75rxeBDhOUDFRXlks5rT6kXgaJpZM4BWkJ9
.

-
Russell Jurney twitter.com/rjurney russell. [email protected] relato.io

É o seguinte, eu não preciso necessariamente de mesclar. Acho que muitos dos problemas poderiam ser resolvidos com um rebase. Meu caso de uso normal é

A (ubuntu) -> B (por exemplo, nginx)
A (ubuntu) -> C (por exemplo, nó)

E eu quero uma imagem B & C combinada. Normalmente eles não têm nada a ver um com o outro, então seria suficiente apenas realocar todas as diferenças entre A e C em B. ou

A -> B -> C '

Parece um problema mais simples de resolver.

@cloutiertyler Normalmente, os aplicativos Node.js não precisam desse recurso para funcionar com o Nginx (na minha opinião). O modo Docker seria dois contêineres, um para Nginx e outro para Node. Configuramos o contêiner Node para expor sua porta apenas ao contêiner Nginx e deixamos o contêiner Nginx escutar a porta pública (como 80). Alguma razão pela qual o Nginx precisa estar no mesmo contêiner que o Node?

Um exemplo de arquivo Docker Compose pode ser

version: "2.1"

services:
  app: # Node.js application image
    build: .
  nginx: # Nginx container who can make request to app container
    image: nginx:1.10-alpine
    depends_on:
      - app
    ports:
      - "${PORT:-8080}:80" # public port, you may want PORT=80

@franklinyu Agradeço a resposta. Na verdade, usei apenas dois serviços aleatórios como exemplo. Meu caso de uso usual seria começar com um serviço genérico (por exemplo, nó baseado no Ubuntu) e uma imagem personalizada minha (também baseada no Ubuntu) e querer combiná-los.

Aliás, não é exatamente rebase, mas abre muitos casos de uso para Dockerfiles.
Dockerfile agora oferece suporte a compilações de vários estágios. Exemplo:

FROM golang AS myapp
COPY . /myapp
RUN cd /myapp && go build

FROM scratch
COPY --from=myapp /myapp /usr/bin/myapp

Você pode ter quantos estágios quiser.
O parâmetro --from basicamente muda o contexto para o nome de destino de compilação especificado.
Quando você docker build -t myapp . , a imagem resultante chamada myapp:latest será do último estágio.
Você também pode construir estágios específicos com docker build --target=myapp , por exemplo.

Existem alguns outros aprimoramentos muito bons do Dockerfile no 17.05 (atualmente disponível como RC1), experimente!

Agora isso é interessante! Eu não sabia que você poderia fazer isso. Terei que fazer uma tentativa para ver se resolve meus casos de uso comuns.

Embora este seja um ótimo recurso, depois de testá-lo, não resolve realmente meu problema mais comum. Eu apenas corri para ele de novo hoje.

Eu gostaria de uma imagem do Jenkins que tenha o Docker instalado para que eu possa construir de dentro do contêiner. O fato é que não há como fazer isso sem replicar o processo de instalação de um ou outro em meu Dockerfile.

Este é um caso em que os argumentos intermitentes sobre isso não ser necessário, uma vez que cada contêiner deve ser apenas um serviço, obviamente não se aplicam. Meu "um serviço" combina a funcionalidade do Docker e do Jenkins.

O fato é que não há como fazer isso sem replicar o processo de instalação de um ou outro em meu Dockerfile.

Então você quer quebrar dois dockerfiles em um para não ter que copiar / colar coisas?

Copiar / colar é equivalente a bifurcação neste caso. O que eu quero fazer é evitar a bifurcação de um Dockerfile para não perder melhorias de bug / segurança ou outras mudanças quando ele muda invariavelmente mais tarde.

Não posso simplesmente passar. Procurando uma maneira de distribuir as alterações em uma longa cadeia de herança de imagens (mais profunda que 2). Multiestágio não parece ser o que esclarece um problema. Ter uma entidade que poderia conter apenas um bloco de diretivas, permitindo-me incluí-la em todas as minhas imagens de herdeiros, junto com a funcionalidade da imagem de base, parece uma evolução racional.

Para aqueles que estão se perguntando a maneira certa de fazer isso, da perspectiva do Docker, reserve alguns minutos para revisar:
https://github.com/floydhub/dockerfiles

Aqui, ele cria uma árvore inteira de Dockerfiles. Conforme você desce na árvore, encontra diferentes combinações de dependências, cada uma DO nível acima na árvore. Então, se você seguiu a árvore de
-ubuntu->common-deps->python3->deepLearningBase->pyTorch
e você realmente queria

-ubuntu->common-deps->python3->deepLearningBase->pyTorch 
+
-ubuntu->common-deps->python3->deepLearningBase->TensorFlow 

Tudo que você faria é adicionar um nó (pasta) em deepLearningBase para ambos, por exemplo
-ubuntu->common-deps->python3->deepLearningBase->TensorFlow-pyTorch

Agora, você ainda precisa fazer um dockerfile que combine os dockerfiles pyTorch e TensorFlow, mas
A chave é que esses arquivos serão MUITO SIMPLES, apenas algumas linhas de instalação no topo do deepLearningBase.

Então, o que é realmente necessário é para vários repositórios github de grande escala como este, para diferentes "mundos", como Desenvolvimento Web, Aprendizado profundo, software incorporado, etc.

Então você apenas seguiria a árvore para sua construção necessária, e se ninguém mais o fez ainda, apenas adicione um nó e combine 2 ou 3 linhas apt-get e faça seu novo ambiente.

Parece o estilo de composição "escolha sua própria aventura". INCLUDE seria muito mais simples. Inferno, eu só quero compor uma imagem gcc especificada com nano para que eu não precise instalar o nano a partir do apt-get todas as vezes!

Concordo com @chambm em seu comentário acima. Não há razão para que isso não seja possível na maioria dos casos (os conflitos devem ser bastante raros, pois ocorrem em sistemas operacionais gerenciados manualmente).

Este é um caso de uso bastante semelhante ao que @cloutiertyler comentou , onde nem a solução de @franklinyu , nem as compilações de vários estágios comentadas por @ cpuguy83 se aplicam:

Onde:

  • As etapas de A a C são exatamente as mesmas de B a D (dockerfileAC).
  • A equipe de desenvolvimento de B não sabe nada sobre C, D ou E.
  • A equipe de desenvolvimento de C não sabe nada sobre B, D ou E.

Um usuário que deseja construir D (e / ou E) deve ter acesso a dockerfileAC, mas não é necessário saber sobre dockerfileAB. Portanto, o usuário deve ter um melhor entendimento de uma dependência (C) do que da outra (B). Idealmente, deveria ser possível contar com as equipes A e B e apenas construir D como A + (diff(B,A) + diff(C,A)) (fusão) ou A + diff(B,A) + diff(C,A) (rebase).

Como o GHDL não é um serviço da web e o VUnit não é um cliente da web, as duas ferramentas precisam ser instaladas na mesma imagem / contêiner (E). Compilações em vários estágios não são úteis, porque precisamos criar um dockerfile (provavelmente desconhecido) com dois rótulos FROM , não é uma única cadeia de encaminhamento.

Se encontrar este caso de uso semelhante ao merge / rebase de dois branches git: às vezes não há conflitos, às vezes os conflitos são facilmente resolvidos, às vezes não pode ser mesclado porque não há histórico comum ... Existe alguma ferramenta, oficial ou externo, que fornece esse recurso? Observe que está tudo bem se a ferramenta apenas exportar duas imagens para ramos do git e realmente usar o git para a fusão.

Incrível, isso ainda é um problema e um tópico. Quão difícil é "INCLUIR alguma imagem", então ao analisá-la, verifique se a base é compatível (na cadeia FROM) e se for, execute o resto desse arquivo naquele ponto (como se eu tivesse copiado o Dockerfile do projeto e colei no meu)?

Toda a desculpa "as pessoas farão coisas ruins que não percebem" é absurda neste contexto. Isso já é extremamente complexo e é por isso que precisamos disso para ajudar a simplificá-lo.

@rainabba Este é um comentário totalmente inútil.
Existem basicamente duas razões para que isso não seja feito:

  1. Não é tão fácil
  2. Ninguém se deu ao trabalho de fazer o trabalho.

Na realidade, geralmente são os dois.

  1. É um problema de análise e substituição de string que qualquer novo codificador poderia realizar em 10 minutos SE soubesse em que parte do código. Não estou dizendo que seria utilizável em todos os casos, mas para os casos limitados que estou vendo sugeridos aqui repetidamente (onde as bases são efetivamente comuns), é um toque morto.

  2. Claro que não, este tópico fornece ~ 102 motivos pelos quais não pode ou não deve ser feito, então por que alguém pensaria em fazê-lo de qualquer maneira?

Por outro lado, meu comentário serve (como tantos outros aqui) para demonstrar que há uma necessidade e com a esperança de influenciar as atitudes obstrutivas ou, pelo menos, servir de lembrete. Se isso for "totalmente inútil", então você acabou de explicar por que esse problema (solicitação de recurso ignorado) ainda está aqui e ativo e não é técnico.

É muito mais do que analisar uma string.
O Docker e o Dockerfile são usados ​​por milhões de pessoas. Adicionar APIs é uma coisa significativa ... mesmo fora disso, a implementação subjacente não é "analisar uma string".

Em qualquer caso, existem muitas propostas para resolver o problema e este é um assunto muito antigo e fechado.

Eu realmente acho que se o Docker não descobrir uma solução limpa para este cenário, ele provavelmente será substituído por qualquer ferramenta que descobrir.

Percebi um dos meus colegas usando o seguinte padrão, o que pode ser uma solução alternativa decente:

ARG from
FROM $from
... rest of dockerfile

Eu mesmo não tentei, então não tenho certeza de como funcionaria na prática, por exemplo, como se comporta com cache, etc.

Na verdade, esse é um problema muito importante e não foi tratado de maneira adequada. Estou surpreso que uma empresa tão grande como a Docker ainda não tenha resolvido isso.

Apenas meus dois centavos ... Estou aprendendo mais sobre o Docker no momento e acho que algo como INCLUDE seria muito útil. Gostei do exemplo de herança múltipla acima e gostaria de abordar os comentários sobre possíveis problemas e conflitos com ele.

A herança múltipla é difícil em qualquer linguagem que a suporte, mas quando ocorre um conflito, é responsabilidade do criador do arquivo Docker repensar o que está fazendo e começar de novo. O Docker deve apenas construir a imagem e não tentar provar que a construção não tem problemas.

@cosminonea

Acho que algo como INCLUIR seria muito útil

Eu tenho suporte para macros em https://github.com/larytet/dockerfile-generator/ Eu poderia oferecer suporte para "incluir" também.

Isso seria perder o ponto. O objetivo é não incluir o Dockerfile
definição. O objetivo é incluir a imagem do docker. Isso vai
parece absurdo porque está fora da minha cabeça:

do fedora
inclui ubuntu / ubuntu
inclui debian / debian

Razoavelmente, eu esperaria que isso começasse com a imagem do fedora.
Em seguida, adicione a imagem para ubuntu na pasta / ubuntu. Em seguida, adicionou o
imagem para debian em / debian.

Isso é obviamente absurdo, porque eu quero misturar um monte de
sistemas em uma imagem? Mas um exemplo mais útil pode ser:

do fedora
inclui plex / plex
incluir commericalremover / plex / add-on / commericalremover

Agora, neste caso, faz mais sentido. Nesse caso, se essas são outras imagens
não tenho componentes operacionais específicos, tenho uma maneira fácil de fazer as coisas
modular.

Na quarta-feira, 8 de agosto de 2018 às 15:48, Arkady Miasnikov [email protected]
escreveu:

Eu sinto algo como INCLUIR
Eu tenho suporte para macros em
https://github.com/larytet/dockerfile-generator/ Eu poderia adicionar "incluir"
suporte também.

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/3378#issuecomment-411529506 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/ADBcWAtBDEp_LXpW3HUkHd3Pw5IVAXvqks5uO0ChgaJpZM4BWkJ9
.

Esse último já é possível; COPY --from aceita um estágio de construção ou uma imagem, então, por exemplo;

FROM busybox

COPY --from=alpine:latest / /
COPY --from=docker:latest /usr/local/bin/docker /usr/local/bin/

Editar; ou para tomar o exemplo real;

FROM fedora

COPY --from=ubuntu:latest / /ubuntu/
COPY --from=debian:latest / /debian/

Exatamente. É por isso que eu consideraria a atualização de 2017 que adicionou "COPY
--from "como tendo concluído a solicitação original. Há absolutamente
nada mais que eu estava procurando neste ingresso.

Ideias que surgiram mais tarde, como rebase automático do include, seriam
recursos interessantes. Mas eles vão além da pergunta original.

Cumprimentos,

Conta

Em qui, 9 de agosto de 2018 às 12h55, Sebastiaan van Stijn [email protected]
escreveu:

Esse último já é possível; COPY - de aceita tanto um
estágio de construção, ou uma imagem, por exemplo;

DE Busybox

CÓPIA --de = alpino: mais recente / /
COPY --from = docker: último / usr / local / bin / docker / usr / local / bin /

-
Você está recebendo isto porque comentou.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/3378#issuecomment-411824851 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/ADBcWPE738cs9xf3ZHSOaUd1foI1XVIQks5uPGmYgaJpZM4BWkJ9
.

@thaJeztah O uso de compilações de vários estágios para isso ainda requer que você saiba quais arquivos _exatamente_ copiar de cada imagem; isso é ainda mais difícil de manter do que copiar e colar o código de configuração de outra imagem.

Claro, mesclar imagens do Docker não é trivial. Uma vez que scripts arbitrários podem ser executados durante as compilações, o processo de compilação resiste a qualquer tentativa geral de detecção automática de conflito; o problema da parada diz oi! O melhor que você pode fazer (sem limitar significativamente o que as compilações podem fazer) é definir uma semântica precisa: digamos que os últimos FROM / INCLUDE vitórias (por exemplo, se eles "escreverem" o mesmo arquivo) ou falha em conflito de nível de sistema de arquivos ou ....

O problema às vezes declarado de diferentes imagens "base" (extensão vs ubuntu vs alpino vs ...), no entanto, _é_ simples: exige que o DAG das dependências da imagem não tenha apenas uma única fonte (a imagem atual), mas também um único coletor (o "ancestral" compartilhado de todas as imagens na "hierarquia").

No final das contas, é claro, você colocaria o lixo dentro do lixo - é sempre diferente, realmente?

FWIW, meus casos de uso são:

  1. Execução de uma aplicação web Tomcat com banco de dados PostgreSQL e armazenamento de objetos S3.
    Embora isso possa ser resolvido usando o Docker Compose, um único contêiner pode ser mais agradável.
  2. As compilações multilíngues são executadas em contêineres do Docker (por exemplo, no Jenkins, Circle CI, ...).
    Existem imagens oficiais para a maioria dos conjuntos de ferramentas populares, mas obter um único contêiner equipado para lidar com mais de um é exatamente o problema discutido aqui.

@reitzig , se você precisar de geração dinâmica de Dockerfiles, sugiro adicionar uma linguagem específica de domínio. Existem alguns exemplos que conheço

@reitzig Esta não é a única opção. A opção certa é restringir INCLUDEs para evitar grandes problemas. INCLUDEs não podem herdar. Aí está. Simples. Ainda é incrivelmente útil.

Essa solicitação de recurso é popular, mas o Docker é gratuito como na cerveja, mas não é, de forma alguma, gratuito como no Freedom.

@rjurney Com a inclusão do suporte para buildkit desde 18.06, os usuários podem fornecer seu próprio analisador de front-end para o construtor. Já existe um analisador Dockerfile experimental oficial (da Docker Inc) que inclui muitos novos recursos (suporte para segredos para iniciantes).

É claro que você também pode adicionar seu próprio comportamento "INCLUIR" em um front-end personalizado do Dockerfile, ou pode fazer algo totalmente diferente que não seja Dockerfile (há um exemplo para buidpacks).

Para usar um front-end personalizado, basta apontar o Docker para uma imagem que pode lidar com isso. Faça isso como um comentário na primeira linha do Dockerfile (ou seja lá o que for) syntax = myCustomFrontendImage

Mais detalhes aqui:
https://docs.docker.com/develop/develop-images/build_enhancements/#overriding -default-frontends

Com o buildkit habilitado, o Docker pode construir o que você quiser (nem mesmo precisa ser um formato Dockerfile) com todos os recursos de que você precisa.

Essa solicitação de recurso é popular, mas o Docker é gratuito como na cerveja, mas não é, de forma alguma, gratuito como no Freedom.

Por mais offtopic que seja essa nota, acho que devemos observar que você está errado. Graças ao licenciamento do Apache do Docker, todos têm a liberdade de bifurcar e desenvolver seu próprio interpretador para Dockerfiles que fornece os recursos desenvolvidos aqui. Se eles forem cuidadosos, as imagens resultantes serão compatíveis com os tempos de execução / ferramentas existentes do Docker.
Claro, os mantenedores do projeto Docker são igualmente livres para não mesclar tal recurso em seu fork (o original?).

@reitzig Isso é obviamente apenas um discurso sem sentido sem realmente referir o que é software livre. Moby é um software livre, é claro.

Eu não sabia que agora era licenciado pela Apache. Peço desculpas pelo comentário e
acho que isso é ótimo!

Russell Jurney @rjurney http://twitter.com/rjurney
Russell. [email protected] LI http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

Na quarta-feira, 16 de janeiro de 2019 às 4:17, Raphael R. [email protected] escreveu:

Esta solicitação de recurso é popular, mas o Docker é gratuito como na cerveja, mas não por
qualquer significa Livre como em Liberdade.

Por mais offtopic que seja essa nota, acho que deve ser notado que você é
errado. Graças ao licenciamento do Apache do Docker, todos têm a liberdade de
bifurcar e desenvolver seu próprio interpretador para Dockerfiles que fornece o
recursos desenvolvidos aqui. Se eles forem cuidadosos, as imagens resultantes serão
compatível com ferramentas / tempos de execução Docker existentes.
Claro, os mantenedores do projeto Docker são igualmente livres para não
mesclar tal recurso em seu fork (o original?).

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/3378#issuecomment-454758482 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AACkpdj_YO76ge79bm4G8FBmhOdbjhO9ks5vDxhvgaJpZM4BWkJ9
.

Desculpe, não dormi bem e cometi um erro. Meu comentário permanece.
Livre como em Beer significa Apache. Livre como em Liberdade significa controle da comunidade.
Um projeto Apache ou alguma outra forma de governança.

Russell Jurney @rjurney http://twitter.com/rjurney
Russell. [email protected] LI http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

Na quarta-feira, 16 de janeiro de 2019 às 12h32 Russell Jurney [email protected]
escreveu:

Eu não sabia que agora era licenciado pela Apache. Peço desculpas pelo comentário e
acho que isso é ótimo!

Russell Jurney @rjurney http://twitter.com/rjurney
Russell. [email protected] LI http://linkedin.com/in/russelljurney FB
http://facebook.com/jurney datasyndrome.com

Na quarta-feira, 16 de janeiro de 2019 às 4:17, Raphael R. [email protected]
escreveu:

Esta solicitação de recurso é popular, mas o Docker é gratuito como na cerveja, mas não por
qualquer significa Livre como em Liberdade.

Por mais offtopic que seja essa nota, acho que deve ser notado que você é
errado. Graças ao licenciamento do Apache do Docker, todos têm a liberdade de
bifurcar e desenvolver seu próprio interpretador para Dockerfiles que fornece o
recursos desenvolvidos aqui. Se eles forem cuidadosos, as imagens resultantes serão
compatível com ferramentas / tempos de execução Docker existentes.
Claro, os mantenedores do projeto Docker são igualmente livres para
não mesclar tal recurso em seu fork (o original?).

-
Você está recebendo isso porque foi mencionado.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/moby/moby/issues/3378#issuecomment-454758482 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AACkpdj_YO76ge79bm4G8FBmhOdbjhO9ks5vDxhvgaJpZM4BWkJ9
.

Livre como em Beer significa Apache.

Discordo. O freeware pode ser um software proprietário.

Livre como em Liberdade significa controle da comunidade.

O que é controle da comunidade? Projetos administrados por uma fundação? Então, você consideraria o VS Code, o editor Atom e o Ubuntu como software não-livre? Então sua definição é significativamente diferente daquela proposta pela FSF, EFF e muitas outras organizações.

Concordo que a Docker Inc não está discutindo ativamente com a comunidade nesta questão, mas isso não tem nada a ver com "Free as in Freedom".

Desculpe pessoal, não vamos ter esse tipo de discussão sobre o rastreador de problemas.

Concordo que a Docker Inc não está discutindo ativamente com a comunidade nesta questão

Tornamos possível oferecer suporte a qualquer formato de compilação que você deseja por meio de docker build . O formato Dockerfile "oficial" não suporta essa opção, mas isso não significa que docker build não possa fazer uso dele.
Confira https://matt-rickard.com/building-a-new-dockerfile-frontend/ como um exemplo de construção de um front-end personalizado que funciona com docker build .
Observe que este front-end é um exemplo de como você pode fazer algo completamente diferente do formato Dockerfile, mas isso não é necessário. Você pode pegar o formato Dockerfile existente e adicionar sua própria funcionalidade, se desejar.

No que diz respeito a adicionar algo ao formato oficial do Dockerfile ... Direi que propostas são sempre bem-vindas, o formato é mantido em https://github.com/moby/buildkit.
Porém, tenha em mente que cada novo recurso significa uma nova carga de manutenção, incluindo muitas vezes a limitação do que pode ser feito no futuro.

Acho que é provável que muitos dos casos de uso para combinar vários Dockerfiles possam realmente ser resolvidos com a nova funcionalidade do Dockerfile ... especificamente a capacidade de COPY --from e RUN --mount de imagens arbitrárias.

Se este INCLUDE hipotético pudesse apenas criar os contêineres extras como um detalhe impl, sem eu ter que dar um @ # $%, isso reduziria muito a quantidade de frustração em torno do argumento de venda implícito e duvidoso de contêineres compostáveis. Eu realmente só quero voltar ao aplicativo e fornecer funcionalidade. Desculpe pelas más vibrações, mas sou docker / container noob e me deparei com a mesma confusão que muitos outros pôsteres já expressaram.

E se você pudesse fazer isso:

              /--- python:3.8.3-alpine3.12 ---\
             /                                 \
alpine:3.12.0                                   custom image (with both python and rust)
             \                                 /
              \----- rust:1.44-alpine3.12 ----/

_Observe que ambas as imagens são descendentes da mesma imagem. Esta é a chave! _

Tão facilmente quanto isto:

FROM alpine:3.12.0
INCLUDE rust:1.44-alpine3.12
INCLUDE python:3.8.3-alpine3.12

_Comparado ao usar a instrução "COPY --from image" (compilações de vários estágios), você não terá que pensar sobre os detalhes de implementação (quais arquivos / variáveis ​​de ambiente copiar) ._

Qual é a aparência agora, se você quiser combinar as imagens

FROM alpine:3.12.0

# INCLUDE rust:1.44-alpine3.12
COPY --from=rust:1.44-alpine3.12 / /
ENV RUSTUP_HOME=/usr/local/rustup \
    CARGO_HOME=/usr/local/cargo \
    PATH=/usr/local/cargo/bin:$PATH \
    RUST_VERSION=1.44.1

# INCLUDE python:3.8.3-alpine3.12
COPY --from=python:3.8.3-alpine3.12 / /
ENV PATH /usr/local/bin:$PATH
ENV LANG C.UTF-8
ENV GPG_KEY E3FF2839C048B25C084DEBE9B26995E310250568
ENV PYTHON_VERSION 3.8.3
ENV PYTHON_PIP_VERSION 20.1.1
ENV PYTHON_GET_PIP_URL https://github.com/pypa/get-pip/raw/eff16c878c7fd6b688b9b4c4267695cf1a0bf01b/get-pip.py
ENV PYTHON_GET_PIP_SHA256 b3153ec0cf7b7bbf9556932aa37e4981c35dc2a2c501d70d91d2795aa532be79

_INV-instruções são copiadas e coladas dos Dockerfiles dessas imagens._


Isso também permitiria uma reutilização de contêineres muito melhor e tornaria extremamente fácil juntar coisas que, de outra forma, levariam muito tempo para compilar ou construir você mesmo!

Considere que, com esta abordagem, um programa só precisa ser compilado uma vez por versão de plataforma / imagem base - e é mais fácil de reutilizar do que implementá-lo você mesmo. Pense em quantas vezes a "roda foi reimplementada" em C ++ devido à falta de um gerenciador de pacotes bom / universal. Queremos uma situação semelhante para o Docker?

@bergkvist , consulte https://github.com/moby/moby/issues/3378#issuecomment -381449355 e https://github.com/moby/moby/issues/3378#issuecomment -381641675.

Parece-me que nenhuma das soluções que você propõe corresponde ao diagrama. Em vez disso, você está fazendo:

              /--- python:3.8.3-alpine3.12 ---\
             /                                 \
alpine:3.12.0                                   \
             \                                   \
              \----- rust:1.44-alpine3.12 --------\ custom image 

Portanto, qualquer arquivo que foi modificado em ferrugem é sobrescrito pelo python . Combiná-los sem copiar um sobre o outro exigiria alguma fusão.

@eine Sim, em caso de conflito, os arquivos serão sobrescritos. Isso é verdade. Portanto, a figura sendo simétrica seria um caso especial de quando nenhum arquivo (relevante) se sobrepõe. Sua versão da figura é mais geral.

Meu ponto sobre ter ambas as imagens herdadas da mesma imagem exata, é que a chance de conflitos críticos pode ser pequena.

Imagino que possam surgir alguns conflitos relacionados aos arquivos do gerenciador de pacotes. Se ambas as imagens usaram o gerenciador de pacotes para instalar coisas diferentes. Não tenho certeza se há algum outro "conflito comum" como aquele que poderia ser tratado com algum tipo de caso especial.

A fusão de dois arquivos é tudo menos simples. Acho que, no caso geral, pode ser melhor apenas substituir do que tentar ser inteligente. Pelo menos é mais fácil depurar quando as coisas não funcionam.

Como comentei aqui há 4 dias, decidi aprender Golang e olhar para o código de front-end para o código moby / buildkit.

Agora criei um front-end personalizado que aceita instruções INCLUDE, conforme discutido acima.

#syntax=bergkvist/includeimage
FROM alpine:3.12.0
INCLUDE rust:1.44-alpine3.12
INCLUDE python:3.8.3-alpine3.12

Para usar a sintaxe personalizada, lembre-se de definir DOCKER_BUILDKIT = 1 ao compilar.

DOCKER_BUILDKIT=1 docker build -t myimage .

O código está disponível aqui: https://github.com/bergkvist/includeimage
E a imagem no Docker Hub: https://hub.docker.com/r/bergkvist/includeimage

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