Moby: Redefinir propriedades herdadas da imagem pai

Criado em 6 jan. 2014  ·  153Comentários  ·  Fonte: moby/moby

Ao construir uma imagem, posso querer redefinir algumas de suas propriedades em vez de herdá-las da imagem principal. Faz sentido herdar todas as propriedades por padrão, mas deve haver uma maneira de redefini-las explícita e seletivamente quando fizer sentido.

Esta é uma solução mais genérica para # 2210 que aborda apenas expose .

arebuilder kinenhancement statuneeds-attention

Comentários muito úteis

Eu definitivamente gostaria de ter alguma maneira de remover pontos de VOLUME herdados de imagens pai.

Por exemplo, suponha que eu tivesse uma imagem principal de um aplicativo que usava um ponto de montagem externo para dados persistentes, mas também queria uma imagem com base nela que fosse pré-preenchida com dados de teste. No estado em que se encontra, não posso fazer isso se a imagem pai usar VOLUME porque quaisquer alterações / adições a esses diretórios, mesmo que essas alterações sejam durante uma compilação do docker, são perdidas no commit.

Todos 153 comentários

Sugestões são bem-vindas para sintaxe.

O melhor que posso inventar são comandos correspondentes como UNVOLUME ou mais genericamente -VOLUME (mas isso acrescentaria mais confusão e, potencialmente, até criaria o equívoco de que +VOLUME deve funcionar, e deve funcionar de forma diferente de apenas VOLUME ).

Eu definitivamente quero tal coisa (mais especialmente para VOLUMEs). Também é um pouco desorientador que coisas como VOLUME se apliquem a seguir as linhas RUN, mas coisas como ENTRYPOINT não. Às vezes isso é muito útil e às vezes não é, mas um genérico "desative a instrução X anterior" poderia resolver os problemas em torno disso muito bem.

Existe uma solução alternativa para isso entretanto? Estou estendendo uma imagem com um ENTRYPOINT (https://github.com/jagregory/pandoc-docker/blob/master/Dockerfile) e preciso remover o ponto de entrada. Tentei usar o seguinte em meu Dockerfile:

FROM jagregory/pandoc
ENTRYPOINT [] # this basically gets ignored (bug?)

FROM jagregory/pandoc
ENTRYPOINT [""] # this will make docker try to exec '' (the empty string)

FROM jagregory/pandoc
ENTRYPOINT ["/bin/sh", "-c"] 
# this will only work if docker run args are quoted:
#   docker run dergachev/pandoc "echo a b c"

Obrigado!

Eu definitivamente gostaria de ter alguma maneira de remover pontos de VOLUME herdados de imagens pai.

Por exemplo, suponha que eu tivesse uma imagem principal de um aplicativo que usava um ponto de montagem externo para dados persistentes, mas também queria uma imagem com base nela que fosse pré-preenchida com dados de teste. No estado em que se encontra, não posso fazer isso se a imagem pai usar VOLUME porque quaisquer alterações / adições a esses diretórios, mesmo que essas alterações sejam durante uma compilação do docker, são perdidas no commit.

Apenas para atualizar a partir do comentário de CMD [] e ENTRYPOINT [] estavam funcionando da última vez que os testei recentemente e ainda devem estar funcionando (qualquer outra coisa estaria pronta para o arquivamento de bugs).

Você pode redefinir todos os comandos de opção única via

ENTRYPOINT []
CMD []
USER 0
WORKDIR /

Isso deve deixar os metadados restantes não redefiníveis como ENV , VOLUME , EXPOSE e talvez ONBUILD .

(Isso está vindo de # 8709)

Se eu expusesse soquetes 9000-9002 no pai, mas precisasse desfazer 9001 na criança, eu teria que escrever no estilo de "desmontar"

EXPOR
EXPOR 9000
EXPOR 9002

que funcionaria, mas

UNEXPOSE 9001

parece melhor.

Uma vantagem é que ele não afeta nenhum EXPOSE de mais para cima na cadeia de herança, o que eu posso querer adicionar mais tarde.

+1 @ codeon-nat

Isso foi discutido no # 8177, estamos fechando isso por falta de casos de uso do mundo real.

Por que isso está sendo fechado? Havia 9 pessoas comentando aqui. Eu acho que isso seria uma coisa muito útil de se ter. Os casos de uso do mundo real estão sendo capazes de se basear em imagens existentes com facilidade. Às vezes você deseja adicionar uma propriedade, às vezes deseja removê-la. Isto é normal.

Eu concordo, por exemplo, estou estendendo a imagem nginx para um descarregador SSL e quero UNEXPOSE 80 mas deixar 443 .

Ser capaz de expor portas é muito crítico se você deseja executar várias instâncias de, por exemplo, nginx.

Esqueça, esta foi apenas uma configuração ruim da minha parte.

(15 de abril: "Nenhum caso de uso do mundo real" Estou surpreso que você não consiga imaginar pelo menos um e fechou isto)

Eu tenho uma imagem de base que expõe volumes ou portas para software opcional, então dela em outro Dockerfile para fazer uma imagem que não deve expor nada que não queira, ou mesmo coisas que desinstalou do ancestral. Por que NÃO queremos remover essas configurações?

Eu também tenho um caso de uso para isso. Eu quero ser capaz de criar uma imagem contendo um instantâneo do banco de dados, mas todos os pacotes mysql têm VOLUME /var/lib/mysql definido. Seria bom poder desligar o volume em que as alterações no banco de dados feitas em meu Dockerfile ficarão com a imagem.

A única outra opção é recriar completamente uma imagem mysql customizada, mas isso de alguma forma parece um desperdício, visto que muitas outras pessoas já criaram servidores mysql padrão melhores do que eu.

Adicionando um caso de uso adicional - estou herdando da imagem oficial do RabbitMQ, mas só quero expor as portas do websocket (80 e 443) e não a porta AMQP padrão (5672). Parece que isso deveria ser uma coisa bastante razoável a se fazer?

Adicionando outro caso de uso. Eu quero construir um ambiente de teste git usando a imagem gogs, mas é tedioso ter os dados persistentes, já que estão todos armazenados em um volume. Seria ótimo se eu pudesse simplesmente UNVOLUME o volume e construir minha imagem após configurar o ambiente.

+1

herdando do php oficial e deseja usar soquetes em vez de portas, então preciso remover a porta 9000 exposta

Qualquer pessoa que tenha usado o Docker em uma capacidade não trivial terá encontrado essas limitações com os contêineres herdados.

@shykes @icecrime como isso está fechado agora? É muito difícil resolver com a sintaxe atual e a necessidade de compatibilidade com versões anteriores? Qual é o plano?

+1 - caso de uso do mundo real para substituir EXPOSE aqui.

Considerando que isso vem acontecendo há mais de 3 anos (problema encontrado desde 2013), quando poderemos remover as portas expostas?

+1. precisa ser capaz de "UNEXPOSE" as portas nginx padrão 80 e 443.

Para aquelas pessoas aqui pedindo UNEXPOSE ; a instrução EXPOSE apenas dá uma dica de quais portas são expostas pelo contêiner, mas não _expõe_ realmente essas portas; você precisa _publicar_ essas portas ( -p / -P ) para expô-las no host. Em outras palavras; omitir a instrução EXPOSE de um Dockerfile não tem _não_ efeito direto na imagem (você ainda pode, por exemplo, alcançar a "porta 80" do contêiner).

Além disso, se você quiser expor portas adicionais, basta fazer o serviço no contêiner ser executado nessas portas e isso funcionará.

Verdade, mas se usar -P (para expor todas as portas) e sua imagem de base expor uma porta que você não deseja mais expor, você está preso. Você precisaria alternar para usar -p e listar todas as outras portas.

@thaJeztah, é bom saber. No entanto, qual é o mal em adicionar UNEXPOSE? Seria útil para mim também, mesmo que seja apenas para ter containers melhor documentados.

@kgx nenhum dano (além do possível inchaço de recursos), mas queria explicar que não ser capaz de " UNVOLUME (ou UNSET VOLUME ) ainda está na minha lista pessoal de desejos. :-)

Acho divertido ter encontrado esse problema nas primeiras 72 horas de tentativas do docker. Cada configuração ou linguagem para qualquer outra ferramenta importante que eu uso e que possui qualquer tipo de herança tem um tipo de recurso "substituir o pai".

Aqui está um caso de uso: estou usando a imagem docker padrão para go-ethereum e preciso ser capaz de configurar uma versão de teste que nunca se conectará ao mundo exterior. Eu preciso ser capaz de me conectar a ele do host e de outros contêineres. A maneira mais segura de fazer isso é mudar as portas porque o programa tenta ansiosamente se conectar aos pares. Também preciso substituir o CMD e o ENTRYPOINT para fazer uma versão "configurar o banco de dados" da imagem que executo uma vez para criar o volume adequado. Todos esses são extremamente difíceis de realizar no Dockerfile.

Você pode atribuí-lo a outro endereço IP ... Ou vincular uma porta de host diferente. O mais tarde sobre como sobrepor o ponto de entrada e o cmd é apenas redefini-los.

--- Enviado do Boxer | http://getboxer.com

Em 20 de fevereiro de 2016 às 08:57:00 GMT, barkthins [email protected] escreveu: Aqui está um caso de uso: estou usando a imagem docker padrão para go-ethereum e preciso ser capaz de configurar um teste versão que absolutamente nunca se conectará ao mundo exterior. Eu preciso ser capaz de me conectar a ele do host e de outros contêineres. A maneira mais segura de fazer isso é mudar as portas porque o programa tenta ansiosamente se conectar aos pares. Também preciso substituir o CMD e o ENTRYPOINT para fazer uma versão "configurar o banco de dados" da imagem que executo uma vez para criar o volume adequado. Todos esses são extremamente difíceis de realizar no Dockerfile. —Responda a este e-mail diretamente ou visualize-o no GitHub.

CMD e ENTRYPOINT podem ser substituídos em tempo de execução; docker run --entrypoint=foo myimage mycmd . A questão aqui é se é útil ter uma imagem diferente, com um ponto de entrada / cmd diferente durante o teste, já que você não _testará_ a imagem real que será executada na produção. (apenas uma nota lateral)

a partir dessas respostas, parece que o dockerfile está sendo preterido em favor das opções de linha de comando, pelo menos no que diz respeito a entrypoint, cmd, expose e provavelmente alguns outros. A linha de comando já faz coisas que o Dockerfile não pode fazer, então essa parece ser a direção. Se essa for a intenção, moverei o máximo possível das informações do Dockerfile para o tempo de instanciação para reduzir a confusão. É essa a intenção?

@barkthins não, o Dockerfile não está obsoleto. Usar um Dockerfile ainda é a maneira normal de produzir uma imagem. Além disso, você pode substituir CMD e ENTRYPOINT em imagens herdadas. Meu exemplo foi mostrar que em certos casos (por exemplo, executando um comando alternativo em sua imagem), você pode substituí-los em tempo de execução.

Na página do manual do Dockerfile:

     -- EXPOSE <port> [<port>...]
     The EXPOSE instruction informs Docker that the container listens

no
portas de rede especificadas em tempo de execução. O Docker usa essas informações para
interconectar contêineres usando links e _para configurar a porta
redirecionamento no host_

  • sistema.*
    [...]
    HISTÓRIA
    * Maio de 2014, compilado por Zac Dover (zdover at redhat ponto com) com base
    na documentação do Dockerfile do docker.com. * Fev 2015, atualizado por Brian Goff (
    [email protected])
    para legibilidade * setembro de 2015, atualizado por Sally O'Malley (
    [email protected])

[meu itálico] parece enganoso (ou pelo menos ambíguo) se o que você diz é
verdadeiro.

Na quinta-feira, 28 de janeiro de 2016 às 6h43, Sebastiaan van Stijn <
notificaçõ[email protected]> escreveu:

Para aquelas pessoas aqui pedindo UNEXPOSE; a instrução EXPOSE apenas
dá uma _dica_ quais portas são expostas pelo contêiner, mas não
na verdade, _exponha_ essas portas; você precisa _publicar_ essas portas (-p / -P)
para expô-los no host. Em outras palavras; omitindo a instrução EXPOSE
de um Dockerfile não tem _não_ efeito direto na imagem (você pode
ainda, por exemplo, alcançar a "porta 80" do contêiner).

Além disso, se você quiser expor portas adicionais, basta fazer o
serviço no contêiner executado nessas portas, e isso funcionará.

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

Atualmente coautor de um livro no Docker: Obtenha 39% de desconto com o código 39miell
http://manning.com/miell/?a_aid=zwischenzugs&a_bid=e0d48f62

thaJeztah Meu ponto e eu acho que o ponto deste tópico é que a herança é inconsistente. Sim, você pode substituir ENTRYPOINT e CMD, mas EXPOSE adiciona exposição, você não pode substituir a exposição do pai, exceto na linha de comando. Não examinei outros comandos para ver se há um terceiro comportamento. Também não está documentado quais comandos estendem ou substituem o comando de um pai.

@thaJeztah , precisamos UNEXPOSE

Existem várias soluções que leem os metadados do contêiner e fornecem configuração upstream adicional. Por exemplo; com HAPROXY eu tenho que definir EXCLUDE_PORTS=8080 para bloqueá-lo tentando fornecer dinamicamente acesso a essa porta em meus aplicativos Tomcat.

Os desenvolvedores olham para as portas expostas e fazem suposições sobre o comportamento do contêiner. Por exemplo, eu tenho uma imagem de base que estende o Tomcat (EXPOSE 8080), mas a imagem usa uma porta diferente do padrão (EXPOSE 8888). Se você adicionar um servidor da web em uma imagem composta (por exemplo, executando NGINX e Tomcat), você servirá conteúdo via HTTP (EXPOSE 80 e EXPOSE 443).

No último exemplo, você pode acabar com uma imagem que se auto-documenta como expondo 8080, 8888, 80 e 443, onde apenas 80/443 é relevante.

Esses são problemas reais, conforme evidenciado pelo fato de que tenho que continuar explicando coisas aos desenvolvedores em nossa comunidade, apesar da documentação muito específica; quem precisa de documentação quando você pode apenas olhar a imagem? <- todos quando a imagem está autodocumentando a coisa errada.

Existem soluções alternativas para este problema, mas são soluções alternativas. Este é um grande problema arquitetônico? Por que o Docker não pode considerar uma solução mais elegante para este problema real.

Qual é o status disso?

O status da

@modius @BillBrower mesmo que esteja fechado, as coisas sempre podem ser reconsideradas; basicamente, "não é temporário", mas "sim é para sempre" ao mesclar / implementar recursos, então, se houver preocupações sobre um recurso, a escolha correta para os mantenedores é dizer "não".

O PR implementando isso foi encerrado porque os mantenedores não tinham certeza sobre o recurso e estavam procurando por exemplos mais reais para seu uso; https://github.com/docker/docker/pull/8177#issuecomment -93587164

Estamos fechando isso porque discordamos em grande parte, mas sinta-se à vontade para provar que estamos errados nos comentários e podemos reconsiderar

Isso foi há mais de um ano, então possivelmente as coisas mudaram; Vou reabrir este problema, e trarei isso na próxima sessão de mantenedores. (Observe que devido ao DockerCon e à versão 1.12 pendente, isso pode demorar um pouco mais do que o normal)

Obrigado, @thaJeztah. Isso faz muito sentido. Agradeço por ter explicado a razão por trás da decisão original e delineando o que você precisa para ver se queremos que isso aconteça.

Um caso de uso para a solicitação _UNVOLUME_

Especialmente porque atualmente, quando você usa um driver de volume personalizado, ele se aplica a TODOS os volumes de um determinado contêiner.

Eu tive o caso de um driver de volume EFS: funciona bem quando eu especifico a ligação de volume na inicialização. Se eu não definir nenhuma ligação, ele falha porque tenta montar o compartilhamento NFS a partir de um UUID gerado automaticamente. Isso significa que devo fornecer uma encadernação para todos os meus volumes, mesmo aquele que não me interessa, criado por uma imagem pai, por exemplo.

A única solução alternativa agora é vincular na inicialização todo o volume de que não preciso a uma subpasta vazia do mesmo compartilhamento EFS.

Nota: Não posso usar o comando docker volume porque tudo isso é iniciado pelo Marathon e deve ser utilizável em um único comando docker run.

+1 UNEXPOSE necessário

+1 para UNEXPOSE

+1 para UNEXPOSE

+1 para UNEXPOSE

+100 para UNEXPOSE

+9000 para UNEXPOSE

+ ∞
Por exemplo, eu uso o repositório oficial nginx (FROM nginx: stable) , que contém no Dockerfile:

EXPOSE 80 443

Mas eu quero remover para outra camada, a porta 80. Ex:

UNEXPOSE 80

Por favor!
Adicione este recurso !!!!

@frekele , se eu fosse sua mãe ou pai, você não entenderia. sem chance.

UNEXPOSE +++
Recurso muito necessário!

Por favor, você não precisa enviar spam para todos os outros com notificações por e-mail e você definitivamente não precisa atrapalhar a discussão com todos esses comentários '+1'. Você pode simplesmente reagir com 👍 à descrição do problema para expressar sua concordância.

@underyx, isso é offtopic, mas vou morder porque estou sempre vendo pessoas dizendo isso. É mais sutil do que você pensa. Para muitas equipes maiores, o número de comentários sobre um problema é a única maneira de avaliar o envolvimento, uma vez que as reações são projetadas como um recurso social - não um mecanismo de votação e, portanto, não são uma maneira confiável de gerar relatórios por meio da API GH (por exemplo, não classificável, entre outras coisas). Além disso, adicionar um comentário automaticamente me inscreve no tópico, que na maioria dos casos é o que eu desejo - caso contrário, eu teria que clicar em 👍 _e_ também clicar em "Inscrever-se".
Veja https://github.com/isaacs/github/issues/9#issuecomment -195120703 (todo o tópico é bom, mas é nessa época que GH adicionou reações).
Agora, não vamos complicar a discussão;)
/offtopic .

Discutimos esse assunto na reunião de mantenedores e, de modo geral, podemos começar a trabalhar nisso novamente.

@duglin, talvez você esteja interessado em trabalhar nisso?

Não sei se ainda tenho tempo, mas apenas para resumir ... com base nos comentários acima, acredito que o requisito é garantir que as pessoas possam limpar / desmarcar o seguinte:

EXPOSE  (all or specific one)
ENV  (specific - not sure we need to clear all yet)
LABEL  (ditto)
VOLUME  (all or just specific paths? probably both)
CMD  (possible but only using the json format)
ENTRYPOINT  (possible with json format)

Eu perdi alguma coisa?

+10000 para UNVOLUME

@duglin Acho que começar com aqueles que atualmente _não_ são possíveis e os mais solicitados seria o melhor ( EXPOSE , VOLUME ). Não vi muitos pedidos para os outros (mas não contra).

O PR original usava UNSET <SOMETHING> , mas depois foi alterado para UN<SOMETHING> . Eu _pessoalmente_ gostei mais do primeiro (mais genérico), mas @shykes preferiu UN<SOMETHING> , não tenho certeza se isso mudou.

UNVOLUME seria bom.

Meu caso de uso: estou usando a imagem mysql e quero confirmar meu banco de dados contido no diretório /var/lib/mysql para uma nova imagem, mas não posso porque é declarado um volume no Dockerfile pai.

@thaJeztah Acho UNSET <something> mais fácil de ler e não tão estranho; não há necessidade de começar a inventar palavras. Também é familiar para pessoas que criam scripts. Também se pode fazer

UNSET  EXPOSE VOLUME LABEL

Meu exemplo,

Estou configurando uma instalação do dokuwiki. A imagem que escolhi estava expondo todos os volumes de configuração em potencial. O que eu gostaria de fazer é personalizar minha instalação a partir desta imagem base. Como os volumes são expostos, não posso modificar os arquivos de configuração do PHP no momento da construção da imagem.

Posso modificar a imagem de base para UNVOLUME esses volumes, mas então vou precisar manter essa imagem para sempre ... a magia de usar "mais recente" se foi :(

+1 para UNEXPOSE :)

+1 para UNVOLUME ou melhor ainda UNSET VOLUME.

+1 para UNVOLUME. Isso pode ser útil para mim agora. Também pode ser útil em cenários universitários onde os alunos aceleram sem se preocupar em ter que montar volumes.

sem se preocupar em ter que montar volumes.

Não acho que será necessário para isso; uma definição VOLUME em um Dockerfile cria automaticamente um volume "anônimo" do conteúdo naquele local na imagem.

@duglin , você já está trabalhando nisso? Se não, eu pegaria e começaria com o mais solicitado (VOLUME e EXPOR). Avise.

@runcom vá em frente - não consegui encontrar tempo ainda.

Como um lembrete, observe que um comando UNENV ainda seria útil, para desconfigurar variáveis ​​de ambiente seletivamente (por exemplo, para combinar com um volume que é UNVOLUME d ao mesmo tempo). Uma variável não definida não é o mesmo que uma variável definida como em branco, particularmente quando usada com set -ue no shell.

Seria possível remover VOLUME e EXPOSE das imagens oficiais se
eles são um problema.

Em 28 de janeiro de 2017 21:23, "henryptung" [email protected] escreveu:

Como um lembrete, observe que um comando UNENV ainda seria útil, para
não definir variáveis ​​de ambiente seletivamente (por exemplo, para combinar com um
volume que é UNVOLUMEd ao mesmo tempo). Uma variável não definida não é o
mesmo que uma variável definida como em branco, particularmente quando usada com set -ue em
Concha.

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub
https://github.com/docker/docker/issues/3465#issuecomment-275875623 ou mudo
o segmento
https://github.com/notifications/unsubscribe-auth/AAdcPAKP1tii706MY-8MxVPSFLTFme8Dks5rW7HggaJpZM4BXt2-
.

+1 para UNVOLUME

+1 para UNVOLUME

Meu caso de uso para UNVOLUME:

Usando a imagem da biblioteca / worpress em um cenário S2I onde a fonte do site é copiada para / var / www / html

VOLUME elimina isso montando um FS vazio na imagem resultante. -> biblioteca / wordpress não pode ser usado.

@groulot Na verdade, se você não montar um volume explicitamente com --volume sobre ele, o conteúdo da imagem será copiado para o volume na criação do contêiner.

O comando docker run inicializa o volume recém-criado com todos os dados existentes no local especificado na imagem de base.

https://docs.docker.com/engine/reference/builder/#/volume

Há uma solução alternativa de hacky usando docker save / load, consulte http://stackoverflow.com/q/42316614/808723

+1 para UNVOLUME

Eu quero ecoar a justificativa de DES-EXPOR . Uma das primeiras coisas em que os desenvolvedores se agarram ao aprender o docker é digitar docker ps para ver o que está acontecendo com seus contêineres. Eles verão a porta padrão listada como disponível. Os desenvolvedores estão acostumados com as portas padrão para coisas de seus ambientes locais ou de teste que eles configuraram em um mundo pré-Docker, então apresentar o Docker é difícil porque eles veem a porta padrão e acham que vai funcionar - mas na verdade eles estão não conectando ao contêiner do docker.

+1 para UNVOLUME, UNEXPOSE, UNENV, ...

Parece que está aberto há um tempo. Alguma tração aqui?
Também quero usar a imagem oficial do PHP fpm alpine e os soquetes UNIX em vez da porta TCP 9000.
Não pode substituir o EXPOSE do pai, e prefere não construir essa imagem apenas para se livrar do EXPOSE.

+1

+1

Adoraria a capacidade de cancelar um comando de VOLUME. A imagem oficial do Wordpress despeja à força sua base de código completa em um volume - eu preferiria muito mais ter apenas um volume para o diretório wp-content / uploads para que o resto da base de código pudesse ser incluído na imagem.

Ao implantar uma imagem no cluster do kubernetes que restringe o acesso raiz, os diretórios VOLUME não podem ser acessados, a solução seria substituir os volumes definidos na imagem pai

+1 de mim

Caso de uso para UNEXPOSE

Suponha que eu tenha quatro hosts docker e desejo executar 16 contêineres maven tomcat, todos padronizados para a porta interna 8080.

Agora imagine que estou usando o registrador com o fazendeiro CNI - que me tranca na porta interna.
https://github.com/gliderlabs/registrator/issues/541#issuecomment -305012416
Isso significa que só posso executar uma porta 8080 interna por host. (Já que tenho que fazer mapeamentos de portas 8080: 8080)

Nesta situação - o mapeamento da porta interna-> externa do docker não é suficiente para resolver o meu problema. Na verdade, preciso substituir o mapeamento da porta interna, de preferência sem reconstruir o contêiner original.

Julian, não sei como você tem um mapeamento 1 para 1. Para mim, registrador como
nada a ver com o tráfego de roteamento, ele apenas registra e cancela o registro
contêineres em execução. Por exemplo, eu o uso de uma forma que o Registrador manterá
uma instância Etcd colocando o IP alocado do Docker e a porta exposta em
lá. Em seguida, usando confd, ele observará uma instância Etcd e atualizará o nginx
config em seu próprio contêiner.
No sábado, 17 de junho de 2017 às 04:06, Julian Gamble [email protected]
escreveu:

Caso de uso para UNEXPOSE

Suponha que eu tenha quatro hosts docker e quero executar 16 maven tomcat
contêineres, todos padronizados para a porta interna 8080.

Agora imagine que estou usando o registrador com o fazendeiro CNI - o que me bloqueia
para a porta interna.
gliderlabs / registrator # 541 (comentário)
https://github.com/gliderlabs/registrator/issues/541#issuecomment-305012416
Isso significa que só posso executar uma porta 8080 interna por host. (Desde que eu tenho
para fazer mapeamentos de portas 8080: 8080)

Nesta situação - o mapeamento da porta interna-> externa do docker não é suficiente
para resolver meu problema. Na verdade, preciso substituir o mapeamento de porta interna,
de preferência sem reconstruir o recipiente original.

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

Oi Bradley,

Obrigado por olhar para isso. Estou usando o registrador em combinação com o ipsecurity integrado ao Rancher. Como você pode ver no link aqui:
https://github.com/gliderlabs/registrator/issues/541#issuecomment -305012416
A capacidade de visualizar portas externas no registrador em contêineres programados pelo fazendeiro era restrita. Isso significa que você só pode usar portas internas.

Você pode ver que há usuários angustiados em busca de uma solução aqui:
https://forums.rancher.com/t/do-you-kill-registrator/5152

E uma solução proposta aqui:
https://github.com/cabrinoob/rancher-registrator
(O que não era viável para algumas pessoas).

Você pode encontrar mais se você pesquisar no google "registrator rancher".

Eles recomendam que você execute o registrador em um modo 'interno' - onde você mapeia suas portas internas 1: 1 para suas portas externas. Isso leva ao problema com UNEXPOSE - ficando sem portas internas rapidamente.

Meu ponto é que ipsecurity usado para rede de contêiner docker intra-host pode levar a um caso de uso em que você está bloqueado em portas internas mapeadas 1: 1 para portas externas no docker. Para isso, você precisa ter um comando UNEXPOSE .

Obrigado por olhar para isso.

Felicidades
Julian

3,5 anos se passaram e nenhum progresso neste assunto? ...

+10086 para UNEXPOSE. às vezes, a imagem pai pode não ser oficial, ela usa portas não oficiais, devemos ter a capacidade de sobrescrever as portas.

@ pumba-lt
Aposto que a razão para isso não ter solução é que eles não sabem como fazer isso tecnicamente.

Ele também adiciona complexidade à linguagem Dockerfile quando há soluções alternativas claras. Não coloque muita configuração no Dockerfile pai e deixe-o para as imagens herdadas. (também conhecido como: parar de fornecer imagens aleatórias no hub do docker: D)

Desde o docker 17.05, há também uma nova maneira de fazer compilações em vários estágios que elimina a maior parte da necessidade desse problema (este é um único Dockerfile ):

# First import the original image
FROM nginx AS source-image

# Second step of the build, start with an empty image
FROM scratch
# Copy the data from the original image
COPY --from=source-image / /
# Re-define all the config
EXPOSE 80
STOPSIGNAL SIGTERM
CMD ["nginx", "-g", "daemon off;"]

EDIT: Esqueci de dizer, a segunda solução esmaga todas as camadas anteriores. Não acho que seja grande coisa, mas é bom saber.

@zimbatm - Isso é incrível!

Aposto que a razão para isso não ter solução é que eles não sabem como fazer isso tecnicamente.

A mudança em si não é muito complicada; uma implementação pode ser encontrada neste PR; https://github.com/moby/moby/pull/8177. Não houve consenso na época, mas se você acompanhar meu comentário de janeiro; https://github.com/moby/moby/issues/3465#issuecomment -247405438, as coisas mudaram e (a menos que as pessoas mudaram de ideia desde então), aceitaríamos uma contribuição para implementar isso.

Por que ainda não está lá; simplesmente porque ninguém teve tempo de começar a trabalhar nisso, mas se alguém estiver interessado, muito provavelmente será aceito.

@zimbatm sim, seu exemplo resolveria o problema direto, só fique atento que ele também cria uma camada diferente e nivela todas as camadas da imagem. Embora isso possa, em alguns casos, reduzir o tamanho da imagem, também faz com que essas camadas não sejam mais compartilhadas com imagens que usam nginx como pai, portanto, pode resultar em mais imagens necessárias para download. Por exemplo;

A imagem nginx original:

$ docker inspect nginx -f '{{json .RootFS.Layers}}' | jq .

[
  "sha256:54522c622682789028c72c5ba0b081d42a962b406cbc1eb35f3175c646ebf4dc",
  "sha256:1c3fae42c5007fd0e70309b5b964eb5d49046562bd425424da734784098894e7",
  "sha256:87823f21b7939eac6e099fa878871a806c1904a7698793edb63bf6e5f5371e1f"
]

E a imagem nginx que você criou;

$ docker inspect nginx2 -f '{{json .RootFS.Layers}}' | jq .
[
  "sha256:9a71ba430225d4f24e0d57837a71b6b2b68bf88ca7530c0a89c98783c98531b5"
]

Obrigado pela atualização @thaJeztah

Posso repetir minha sugestão de uso

UNSET XXXX

em vez de inventar novas e estranhas palavras de vocabulário (por exemplo: UNVOLUME).

Também poderíamos remover a definição de várias propriedades em uma linha dessa maneira.

UNSET VOLUME EXPOSE LABEL

Pessoalmente, estou bem em fazer UNSET fazer um ou outro provavelmente não será uma grande mudança, então deixarei isso para o processo de revisão quando um PR chegar

Olá, mesmo se usar FROM pela segunda vez, como retenho tudo da imagem pai, exceto para não expor algumas das portas expostas na imagem docker pai? existe alguma resolução oficial sobre isso, vamos aceitar isso e trabalhar ou rejeitar

vamos aceitar isso e trabalhar ou rejeitar

@rajiff veja meu comentário acima https://github.com/moby/moby/issues/3465#issuecomment -313549657 contribuições são bem-vindas

A mudança em si não é muito complicada; uma implementação pode ser encontrada neste PR; # 8177. Não houve consenso na época, mas se você acompanhar meu comentário de janeiro; # 3465 (comentário), as coisas mudaram e (a menos que as pessoas mudem de ideia desde então), aceitaríamos uma contribuição para implementar isso.

Portanto, se o consenso pode ter mudado, por que não reabrir o # 8177 ?

Portanto, se o consenso pode ter mudado, por que não reabrir o # 8177?

Esse PR foi aberto há mais de três anos; o código não se aplica mais

Em vez de ter que usar especificamente um comando UNsomething,
por que não melhorar o comando FROM e tornar possível listar o que realmente queremos herdar?

Podemos usar algo como:
FROM baseimage (VOLUME, EXPOSE, PORT, ..)
ou se você realmente quer com negação:
FROM baseimage (*, -VOLUME, -EXPOSE)
ou tem uma sintaxe melhor;)

Parece-me que tudo isso deve fazer parte do comando FROM em primeiro lugar.

Alterando o volume de dentro do Dockerfile: Se qualquer etapa de construção alterar os dados dentro do volume depois que ele for declarado, essas alterações serão descartadas.

Isso não parece totalmente verdade. Você ainda pode fazer isso:

VOLUME /avolume/subdir
WORKDIR /avolume
COPY ./Dockerfile /avolume/subdir

Não sei se poderia ser usado para desfazer um volume.

Substituir a imagem pai / contêiner ENTRYPOINT não funciona nas versões mais recentes.

17.09.1-ce versão

$ docker run --name=experiment --entrypoint=/bin/bash ubuntu:16.04
$ docker inspect experiment --format "{{.Config.Entrypoint}}"
[/bin/bash]
$ IMAGE=$(docker commit -c "ENTRYPOINT []" experiment)
$ docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[]

desde 17.10.0-ce versão

$ docker run --name=experiment --entrypoint=/bin/bash ubuntu:16.04
$ docker inspect experiment --format "{{.Config.Entrypoint}}"
[/bin/bash]
$ IMAGE=$(docker commit -c "ENTRYPOINT []" experiment)
$ docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[/bin/bash]

UNSET ENTRYPOINT também não funciona.
É um bug?

@ alexey-igrychev você pode abrir uma edição separada para isso? O problema que você está comentando é uma _solicitação de recurso_ para implementar instruções UNSET xx no Dockerfile. (A instrução UNSET ainda não foi implementada, então isso é esperado.)

Como uma solução alternativa para esse problema, usar [""] vez de [] para o ponto de entrada parece funcionar;

IMAGE=$(docker commit -c "ENTRYPOINT [\"\"]" experiment)
docker inspect $IMAGE --format "{{.Config.Entrypoint}}"
[]

Eu também preciso de uma maneira de remover a configuração do volume, para poder criar uma imagem de banco de dados pré-carregada com tabelas e dados.
Infelizmente, a imagem base é privada (oracle) e, portanto, não posso nem copiar o dockerfile base, pois não tenho acesso a ele. Eu só posso estender a imagem.
Esta edição tem toneladas de + 1s e casos de uso do mundo real listados, e vários PRs foram feitos para ele, mas os PR foram encerrados. Então, o que precisamos fazer para obter esse recurso?

@veqryn desde a reabertura deste problema, ninguém começou a trabalhar em uma solicitação de pull; a solicitação pull existente não se aplicava mais de forma limpa na base de código, portanto, uma nova deve ser aberta; se alguém estiver interessado em trabalhar nisso, as coisas podem começar de novo.

Veja meu (s) comentário (s) anterior (es); https://github.com/moby/moby/issues/3465#issuecomment -247405438

Discutimos esse assunto na reunião de mantenedores e, de modo geral, podemos começar a trabalhar nisso novamente.

@duglin, talvez você esteja interessado em trabalhar nisso?

E https://github.com/moby/moby/issues/3465#issuecomment -313549657

Por que ainda não está lá; simplesmente porque ninguém teve tempo de começar a trabalhar nisso, mas se alguém estiver interessado, muito provavelmente será aceito.

Meu caso de uso vem de docker-compose.yaml: Eu gostaria de ter um arquivo de composição para desenvolvimento com substituições para produção que adicionam um proxy reverso TLS, repositório Maven, assume a PORTA 80/443, não expõe a porta 80 e 5432 que o arquivo de composição de desenvolvimento expõe. Ou um arquivo de composição para produção com substituição de desenvolvimento.

A natureza somente de adição dos arquivos de composição em camadas herdados dos Dockerfiles complica o design do sistema. Seria muito legal se alguns parâmetros pudessem ser recolhidos ou se eu simplesmente tivesse um contêiner diferente construído com substituições ativas. Eu não sou exigente em como funciona sob o capô wrt docker-compose.

Obrigado @thaJeztah - você poderia nos indicar a linha de código que, em sua opinião, é o lugar para começar a ler para ver como consertar isso com uma solicitação pull?

Eu não trabalhei muito no código do construtor, mas as mudanças provavelmente devem estar no pacote https://github.com/moby/moby/tree/master/builder .

Esse problema tem 3 anos! É tão difícil concordar com um recurso tão básico ou estou faltando alguma coisa?

@caruccio sim, está faltando alguma coisa: role para cima 4 comentários https://github.com/moby/moby/issues/3465#issuecomment -356988520

Também tenho alguns casos de uso (um de projeto pessoal e o segundo de trabalho) em que desejo sobrecarregar uma instrução VOLUME , EXPOSE e ENTRYPOINT de uma imagem pai.

Embora eu tenha uma solução alternativa para ENTRYPOINT apenas definindo um novo ponto de entrada vazio com ENTRYPOINT [] , e provavelmente posso aprender a viver ignorando EXPOSE , ... Eu fico coçando minha cabeça sobre como não herdar VOLUME definições.

Acabei de encontrar esse problema em minha base de código em que a imagem pai tinha um VOLUME, o que significa que todas as minhas alterações neste volume em uma imagem filho foram descartadas. Eu pensei que estava ficando louco por 2 dias até que finalmente encontrei meu caminho para este problema. Alguém poderia implementar isso.

Existe uma SOLUÇÃO ALTERNATIVA.

Você sempre pode docker save image -o image.tar , descompactar esse arquivo, editar os metadados e empacotar novamente para docker load -i image2.tar . Dessa forma, pode-se fazer uma imagem2 que não contenha nenhuma das declarações anteriores de VOLUME.

Como tenho que fazer essas etapas com bastante regularidade, criei um pequeno script para ajudar na tarefa de limpar uma imagem de terceiros. Dê uma olhada no docker-copyedit

Trabalho fantástico @gdraheim ! Uma solução viável em <250 linhas de python.

@gdraheim uau, isso é ótimo! Do README:

O desejo de REMOVER TODOS OS VOLUMES veio do fato de que eu queria baixar uma imagem testada para testes locais onde a parte de dados deveria ser comprometida com o histórico também a fim de retornar o programa e os dados a um estado definido para que outro o teste de funcionamento começará exatamente no mesmo ponto de verificação.

Este é o nosso caso de uso também.

Eu expandi docker-copyedit para cobrir todas as entradas de metadados de uma imagem, para que ele possa funcionar em todas as propriedades herdadas, mesmo além dos casos problemáticos das listas EXPOSE e VOLUME. Isso seria user, workingdir, labels, env settings para coisas vistas com frequência. Copiar ENTRYPOINT para CMD também é uma modificação que faço regularmente. Não há mais necessidade de fazer uma etapa intermediária de compilação do docker, basta ir para docker-copyedit . ;)

O tempo gasto pela equipe do Docker para rastrear e ignorar repetidamente esse problema provavelmente teria sido suficiente para corrigi-lo.

Podemos agora, por favor, reabrir isto depois de, obviamente, uma tonelada de usuários solicitando isso ...
ou pelo menos dê um argumento razoável contra isso, não apenas ignorando todos os casos de uso (eu quero expor uma porta também e apenas para obter uma saída mais limpa do docker ps sem porra nenhuma (80/80 / tcp) antes de construir minha própria imagem. .. (o que é mais difícil para Dockerfiles sem código aberto)

A questão ainda está aberta; É código aberto; contribuições são bem-vindas https://github.com/moby/moby/issues/3465#issuecomment -356988520

Estou certo de pensar que isso seria corrigido no moby / buildkit agora? Vejo a maior parte da infraestrutura de comando do

Também sou fã de UNSET , gosto

UNSET EXPOSE 9000

ou

UNSET LABEL foo

Então, estou olhando para comandos que têm formas semelhantes a subcomandos, como a forma HEALTHCHECK CMD e noto que HEALTHCHECK já tem uma forma não definida ...

HEALTHCHECK NONE

Esta é uma escolha interessante, mas HEALTHCHECK também define apenas 1 configuração (e substitui com a mais recente), não permite definir múltiplos, como LABEL , EXPOSE , e VOLUME fazem.

Eu só me pergunto como eles devem interagir ou se há algum outro tipo de formulário NONE que pode funcionar.

É realmente necessária alguma maneira de remover portas expostas para controlar o que é exposto ao usar a rede host.

+1 EXPOR []

Então .... pelos 5 anos da equipe Docker incapaz de implementar o operador UNSET, fantástico

Como @AnthonyMastrean disse, devemos mover este problema para o projeto moby/buildkit ?

Há também um PR, bem documentado e testado, mas não mesclado. Devemos mover / rebase este PR também?

Esse recurso seria muito apreciado e resolveria um problema com imagens baseadas em nginx no Azure.

UNSET , CLEAR , RESET , OVERRIDE , IGNORE estaria ok - Eu evitaria UNxxx porque isso duplicaria a lista de chaves reservadas para apoiar e documentar.

O que ignorar / redefinir também pode ser especificado ao usar FROM , por exemplo

FROM nginx:1.13 IGNORE EXPOSE, ENTRYPOINT

Eu sugiro mais uma solução alternativa, usando compilações de vários estágios.
Ele irá copiar todos os arquivos da imagem original para a nova imagem, mas sem metadados.

FROM postgres as orig

FROM alpine:3.8 as postgres
COPY --from=orig / /
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 5432
CMD ["postgres"]

Não acredito que não pensei nisso. Isso é realmente muito bom, @kotofos. Você perde as camadas do contêiner a montante, mas isso não é uma grande perda.

@kotofos Por que não FROM scratch as postgres ?

@farcaller good catch. zero seria definitivamente melhor, já que você está sobrescrevendo todo o sistema de arquivos

Da última vez que testei, COPY --from=xxx ... não preservaria o sistema de arquivos
propriedade, então você pode querer ter cuidado com essa solução alternativa.

@tianon Você está correto, embora para contêineres de processo único isso não deva ser um problema, pois você pode usar o sinalizador --chown para definir o usuário que está executando como no contêiner

https://docs.docker.com/engine/reference/builder/#copy

Isso remonta a 2014. Já se passaram 5 anos e parece que não haverá um "não definido" ou "redefinido" genérico para todas as propriedades em um futuro próximo. Eu também sou a favor de uma abordagem genérica, mas há muitas coisas a se considerar e, realmente: isso não vai acontecer tão cedo.

Então: podemos pelo menos obter um "UNEXPOSE" para fechar todas as portas abertas ou obter pelo menos o mesmo comportamento que para CMD e ENTRYPOINT (o último vence)? É a propriedade "não configurada" mais solicitada e um potencial risco de segurança para usuários que desconhecem o comportamento (não intuitivo), considerando que o comportamento "o último ganha" de outros comandos.

Eu sugiro mais uma solução alternativa, usando compilações de vários estágios.
Ele irá copiar todos os arquivos da imagem original para a nova imagem, mas sem metadados.

FROM postgres as orig

FROM alpine:3.8 as postgres
COPY --from=orig / /
ENTRYPOINT ["docker-entrypoint.sh"]
EXPOSE 5432
CMD ["postgres"]

Eu queria ignorar o volume do docker apontado por PGDATA para que pudesse ter seu conteúdo empacotado com a imagem e não como um volume.
Uma solução mais leve para mim foi simplesmente alterar o valor de PGDATA :

FROM postgres:11.2-alpine
ENV PGDATA /var/lib/postgresql/test-data

# stuff that will create all my schemas
COPY create-scripts /docker-entrypoint-initdb.d/

# a weird way to trigger the entrypoint script to run the stuff in docker-entrypoint-initdb.d but not hang after starting postgres
RUN /docker-entrypoint.sh postgres --version

Existe alguma vantagem em ter EXPOSE e VOLUME em dockerfiles? Afinal, você pode defini-los facilmente em docker run (e em docker-compose arquivos), com --expose (ou -p ) e volumes nomeados ou montagens de ligação. Fui mordido por causa deles mais de uma vez e não há como redefini-los (criar um novo dockerfile não é muito viável, especialmente ao estender imagens oficiais ou imagens criadas com makefiles). Eu os vejo como um antipadrão e acho que seria melhor rejeitá- los.

@lucasbasquerotto EXPOSE é usado por ferramentas como o gitlab-runner para detectar se as portas declaradas expostas pela imagem estão realmente abertas ou não. Eu concordo que isso deveria ser mais uma função HEALTHCHECK para detectar se o contêiner está pronto ou não, mas ter uma lista de portas declaradas pode ser realmente útil para automação.
VOLUME é necessário para fornecer a experiência amigável de parar / iniciar um contêiner e ter os dados persistidos automaticamente. Novamente, acho que isso pode ser resolvido de alguma outra maneira, mas ter os dados inspecionáveis ​​é bom para o conjunto de ferramentas (e para os humanos também neste caso).

ps não defendendo a sintaxe do Dockerfile, estou apenas apontando que os antipadrões não são causados ​​pelas próprias palavras-chave, mas sim porque o ecossistema não está avançando para resolver problemas que podem surgir em casos de uso comum como este, ou como fornecer uma imagem com um volume declarado e alguns dados iniciais no volume (por exemplo, uma imagem mysql com esquema pré-carregado)

@zarelit Não sei exatamente como gitlab-runner funciona, mas acho que deveria haver uma maneira de especificar as portas a serem verificadas fora do Dockerfile (encontrei um problema que provavelmente se deve a isso, porque o MySQL expõe 2 portas, mas deve verificar apenas a porta 3306: https://gitlab.com/gitlab-org/gitlab-runner/issues/4143). Pelo que vejo, ele também usa apenas a porta exposta do último Dockerfile.

Sobre VOLUME , você pode persistir dados com estado usando volumes nomeados ou montá-los com -v em um diretório existente (se quiser preservar os dados ao recriar um recipiente). Também acho que seria melhor usar essa abordagem porque VOLUME dentro do dockerfile é meio obscuro para quem estende esse dockerfile, e se você não souber que está lá, pode pensar que seu contêiner é reproduzível em ambientes diferentes e que você pode alterar as versões sem efeitos colaterais, apenas para ser mordido mais tarde porque está usando dados persistentes sob o capô.

Ele também não permite que você mova arquivos para esse diretório durante a compilação (supondo que você não queira usá-lo como um volume, mas herda um Dockerfile que define o diretório como um volume, como wordpress que define /var/www/html/ como um VOLUME e precisei usar alguns hacks para usar outro diretório).

Usando -v você declara explicitamente que deseja o volume e evita surpresas indesejáveis ​​devido à magia negra de VOLUME no Dockerfile.

Além disso, pode acabar criando muitos volumes anônimos:

Definir um volume dentro da imagem diz ao docker para armazenar esses dados separados do resto do contêiner, mesmo se você não definir o volume ao girar o contêiner. A maneira do Docker de armazenar esses dados é criar um volume local sem um nome. O nome em si é uma longa string de id exclusiva que não contém nenhuma referência à imagem ou ao contêiner ao qual está anexado. E, a menos que você diga explicitamente ao docker para remover os volumes quando você remove o contêiner, esses volumes permanecem, improváveis ​​de serem usados ​​novamente

Fonte: https://boxboat.com/2017/01/23/volumes-and-dockerfiles-dont-mix/

@lucasbasquerotto Concordo em grande parte com você, são todos problemas antigos, acho que uma depreciação deve seguir um caminho onde eles não se tornem inválidos, eles se tornem informativos como ... caminhos sugeridos que você poderia transformar em um volume, portas sugeridas nas quais um servidor pode estar escutando.

Acho que a parte boa da jornada do Docker agora foi extraída para o padrão OCI e, portanto, devemos escrever novas ferramentas que não tenham todo esse legado nas costas.

Para quem o achar útil, sinta-se à vontade para usar as imagens do docker de tugboat.qa . Eles são extensões de várias imagens docker oficiais com volumes removidos. Repositório GitHub minimamente documentado aqui, onde o trabalho pesado é feito: https://github.com/TugboatQA/images

Existe alguma vantagem em ter EXPOSE e VOLUME em dockerfiles? Afinal, você pode defini-los facilmente em docker run (e em docker-compose arquivos), com --expose (ou -p ) e volumes nomeados ou montagens de ligação. Fui mordido por causa deles mais de uma vez e não há como redefini-los (criar um novo dockerfile não é muito viável, especialmente ao estender imagens oficiais ou imagens criadas com makefiles). Eu os vejo como um antipadrão e acho que seria melhor rejeitá- los.

Muitos fornecedores hoje em dia fornecem seus aplicativos como uma imagem de contêiner simples e fornecem dockerfiles com eles.
Ter EXPOSE e VOLUME nesses arquivos permite o uso de aplicativos simples com um simples docker run no diretório do aplicativo. Você não precisa saber nada sobre quais parâmetros o aplicativo espera, ele funciona com todos os padrões fornecidos no dockerfile.
Então, sim: embora tenhamos melhores, armas maiores como compose ou k8s para aplicativos complexos para dockerfiles de aplicativos simples e locais ainda são uma ótima opção. E ter padrões que funcionam torna o uso conveniente.

@ m451 Uma execução mais curta do docker pode ser preferível do que uma mais longa (com mais opções definidas), mas não considero isso um bom argumento para expor portas e volumes no dockerfile.

Em vez de docker run some_image você pode facilmente executar docker run --expose 3000 -v my_volume:/container/dir some_image e ter uma compreensão clara das portas expostas ao host e dos volumes que persistirão mesmo depois que o contêiner for destruído.

Além disso, isso é uma coisa trivial de se fazer , e você expõe e mapeia volumes apenas quando precisa (talvez você não precise de todas as portas expostas no dockerfile, nem de todos os volumes definidos. Se for realmente importante expor alguma porta ou usar algum volume, é melhor documentar no repositório para que as pessoas não saibam apenas o que precisa ser exposto ou mapeado, mas porque, afinal isso é algo que afetará o exterior do container, podendo persistir depois o contêiner é destruído).

Se estiver no dockerfile, pode realmente tornar mais difícil saber o que está acontecendo e causar surpresas inesperadas no longo prazo quando um volume é persistido e você não sabe (especialmente se um dockerfile é herdado de outro, você pode não saber de antemão que um volume é definido, a menos que você inspecione mais profundamente o que ele faz). Portanto, consideraria VOLUME e EXPOSE ruins, mesmo se esse problema fosse resolvido.

Além disso, enquanto esse problema não está resolvido (e não tenho ideia de quantos anos vai demorar para resolvê-lo, considerando que está aberto há mais de 5 anos e meio) então simplesmente NÃO TENHO COMO REINICIAR eles .

Existe alguma vantagem em ter EXPOSE e VOLUME em dockerfiles? Afinal, você pode defini-los facilmente em docker run (e em docker-compose arquivos), com --expose (ou -p ) e volumes nomeados ou montagens de ligação. Fui mordido por causa deles mais de uma vez e não há como restaurá-los (criar um novo dockerfile não é muito viável, principalmente ao estender imagens oficiais ou imagens criadas com makefiles). Eu os vejo como um antipadrão e acho que seria melhor rejeitá- los.

Muitos fornecedores hoje em dia fornecem seus aplicativos como uma imagem de contêiner simples e fornecem dockerfiles com eles.
Ter EXPOSE e VOLUME nesses arquivos permite o uso de aplicativos simples com um simples docker run no diretório do aplicativo. Você não precisa saber nada sobre quais parâmetros o aplicativo espera, ele funciona com todos os padrões fornecidos no dockerfile.
Então, sim: embora tenhamos melhores, armas maiores como compose ou k8s para aplicativos complexos para dockerfiles de aplicativos simples e locais ainda são uma ótima opção. E ter padrões que funcionam torna o uso conveniente.

Eu diria que os fornecedores que fazem isso o fazem por ignorância. Não entender os problemas que isso causa para as pessoas que desejam usar seu produto em um ambiente de produção. Claro, isso torna mais fácil para alguém criar uma instância de teste / demonstração do produto. Mas agora, se eu quiser executá-lo de verdade, tenho que clonar / sed seu Dockerfile ou criar meu próprio apenas para obter uma imagem funcional.

@ m451 Uma execução mais curta do docker pode ser preferível do que uma mais longa (com mais opções definidas), mas não considero isso um bom argumento para expor portas e volumes no dockerfile.

Em vez de docker run some_image você pode facilmente executar docker run --expose 3000 -v my_volume:/container/dir some_image e ter uma compreensão clara das portas expostas ao host e dos volumes que persistirão mesmo depois que o contêiner for destruído.

Além disso, isso é uma coisa trivial de se fazer , e você expõe e mapeia volumes apenas quando precisa (talvez você não precise de todas as portas expostas no dockerfile, nem de todos os volumes definidos. Se for realmente importante expor alguma porta ou usar algum volume, é melhor documentar no repositório para que as pessoas não saibam apenas o que precisa ser exposto ou mapeado, mas porque, afinal isso é algo que afetará o exterior do container, podendo persistir depois o contêiner é destruído).

Se estiver no dockerfile, pode realmente tornar mais difícil saber o que está acontecendo e causar surpresas inesperadas no longo prazo quando um volume é persistido e você não sabe (especialmente se um dockerfile é herdado de outro, você pode não saber de antemão que um volume é definido, a menos que você inspecione mais profundamente o que ele faz). Portanto, consideraria VOLUME e EXPOSE ruins, mesmo se esse problema fosse resolvido.

Além disso, enquanto esse problema não está resolvido (e não tenho ideia de quantos anos vai demorar para resolvê-lo, considerando que está aberto há mais de 5 anos e meio) então simplesmente NÃO TENHO COMO REINICIAR eles .

Acordado. Portanto, vamos definir uma maneira padrão de comunicar quais parâmetros são necessários.
Se não houver nenhum, acabaremos com a mesma bagunça que tivemos em aplicativos legados: documentos específicos de fornecedores e formatos de documentação. Alguns dizem quais portas abrir, outros não. Alguns indicam apenas metade, outros indicam as portas erradas. Alguns apenas informam o número da porta, mas não o protocolo e assim por diante.

Os Dockerfiles têm sido uma ótima maneira de padronizar essa bagunça.

@ m451 Concordo com você nisso, mas é bom considerar que apenas expor uma porta não transmite informações úteis. Que tipo de dados / conexões a porta exposta espera? Se houver várias portas, o que cada porta faz?

Se você deseja manter os dados que deseja montar em um volume nomeado ou em algum local no host, o VOLUME não ajuda nisso. Se você deseja que os dados temporários sejam armazenados com mais desempenho, VOLUME ajuda (este é o único caso em que VOLUME pode ser útil). A gravação no contêiner é mais lenta porque usa a estratégia de

Usando VOLUME e expor como um tipo de documentação não justifica mau (ou a falta de um) documentação. E também pode (e provavelmente irá) prejudicar alguns consumidores da imagem.

@ m451 Concordo com você nisso, mas é bom considerar que apenas expor uma porta não transmite informações úteis. Que tipo de dados / conexões a porta exposta espera? Se houver várias portas, o que cada porta faz?

Correto. A ideia do buraco das portas a partir de um segundo. perspectiva está desatualizada. Ainda: aqui estamos tentando definir quais portas precisam ser abertas e quais portas podem permanecer fechadas e entender quais dados são trocados em cada porta. HTTPS se tornou um wrapper para quase tudo hoje e, além do autor do código, normalmente não há ninguém que saiba exatamente quais dados são transferidos por uma porta em particular. E mesmo assim, pode mudar a cada atualização.

No RL, você não se preocupa com quais dados / informações são transportados por qual porta, além de acabar resolvendo os problemas do aplicativo. Você decide confiar no aplicativo. Portanto, se o aplicativo abrir as portas X e Y, você também pode confiar nele.
Para operações diárias padrão, é bom apenas iniciar um aplicativo e ele funciona imediatamente (padrões seguros assumidos).
Os contêineres se tornaram uma forma de empacotar aplicativos para que funcionem imediatamente.

Dito isso, concordo que bons documentos são importantes. Ainda assim, em RL ninguém quer ler documentos por horas apenas para saber quais portas abrir. Não traz nenhum benefício para as tarefas de operações diárias.

Meu pedaço da torta.

Usar VOLUME no Dockerfile é inútil . Se um usuário precisar de persistência, ele fornecerá um mapeamento de volume ao executar o contêiner especificado. Foi muito difícil descobrir que meu problema de não conseguir definir a propriedade de um diretório (/ var / lib / influxdb) era devido à declaração de VOLUME no Dockerfile do InfluxDB. Sem um tipo de opção UNVOLUME , ou eliminando-a completamente , não consigo alterar _algo_ relacionado à pasta especificada. Isso é menos do que ideal, especialmente quando você está ciente da segurança e deseja especificar um determinado UID, a imagem deve ser executada para evitar que um usuário aleatório, com mais permissões do que o necessário, execute software em seu host.

Deve haver uma maneira de substituir essas diretivas de VOLUME ao estender imagens para personalização do usuário. Minha única solução no momento é recriar completamente a imagem sozinho, tornando todo o _Dockerfile FROM_ dinâmico inútil.

DE nginx: mais recente
após implantar no heroku, a porta 80 foi exposta pelo nginx, mas isso não será permitido pelo heroku, então o que posso fazer? copie todos os dockerfile do nginx e remova o EXPOSE 80?

Não vou escrever nada novo ... mas seria muito bom substituir a diretiva EXPOSE.

Compartilhando isto - https://github.com/gdraheim/docker-copyedit/blob/master/docker-copyedit.py (não foi minha criação, para ser claro, obrigado @gdraheim!)

Isso me ajudou a remover um volume de um contêiner postgres que foi definido no dockerfile com o comando:

python docker-copyedit.py FROM postgres:11.5-alpine INTO postgres:11.5-alpine remove volume /var/lib/postgresql/data

Parece ter feito o trabalho sem danificar o container, pegou a imagem original, adaptou, criou uma nova imagem sem o volume (de acordo com o docker inspect executado em um container criado a partir da imagem ajustada), não usei-o para qualquer outra coisa, mas o README do git permite uma variedade de operações, ou seja,

 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     REMOVE PORT 4444
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     remove port ldap and rm port ldaps
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     remove all ports
 ./docker-copyedit.py FROM image1 INTO image2 -vv \
     add port ldap and add port ldaps

LABEL é outra 'propriedade' (ainda não mencionada) que pode usar a capacidade de 'cancelar'

Conforme mencionado nesta postagem do SO: https://stackoverflow.com/questions/50978051/how-do-i-unset-a-docker-image-label

Outro caso de uso para redefinir / remover VOLUME das imagens upstream:

Estou trabalhando na ampliação de uma imagem de banco de dados oracle, mas tem um volume em /opt/oracle/oradata . Na imagem oracle padrão, o banco de dados é criado na inicialização do contêiner e grava nesse volume. Mas isso faz com que o contêiner precise de 25 minutos para a primeira inicialização, o que não é aceitável. Estou trabalhando em uma imagem em que o banco de dados é criado no build da imagem, mas para isso preciso remover o VOLUME /opt/oracle/oradata bacause meu banco de dados é criado, mas quando eu inicio o contêiner, o sistema de arquivos /opt/oracle/oradata está vazio novamente e meu banco de dados falha ao iniciar.

Estou trabalhando na ampliação de uma imagem de banco de dados oracle, mas tem um volume em /opt/oracle/oradata .

Exatamente meu caso de uso também. Gostaria de gerar um banco de dados plugável pré-alocado que outras pessoas possam obter de nosso registro docker privado ... mas o volume está faltando. Terei que cavar mais fundo e decidir pela solução menos feia.

Eu resolvi da seguinte maneira:

Usei docker-copyedit para remover o volume, então escrevi um script bash para criar o banco de dados (você pode olhar os scripts de inicialização do oracle para ver como isso é feito). Agora, com o PDB pré-configurado, leva apenas 25 segundos para iniciar um contêiner a partir da imagem. Mas a imagem fica muito grande.

Seria uma abordagem melhor estender a especificação docker existente para incluir um conceito de opções de substituição / substituição de env aderentes, como;

por exemplo, meu projeto baseado na imagem upstream do tomcat:

--ENV CATALINA_HOME / algum / outro / caminho
DE tomcat: 8.5.54-jdk8-openjdk
...

Onde um ENV é declarado com - deve ser elevado a um status fixo e manter o valor declarado / substituir qualquer valor encontrado para esta variável posteriormente na cadeia de processamento do Dockerfile.

--ENV = deste ponto em diante no Dockerfile.

Portanto, isso pode ser usado no início de um Dockerfile se você quiser que tenha precedência sobre qualquer outro encontro da mesma variável, como em compilações de vários estágios. Também permitiria flexibilidade, dependendo de onde no Dockerfile ele foi colocado para que as referências superiores no arquivo fossem independentes.

Não seria necessário um UNVOLUME, pois a abordagem correta seria que VOLUME fosse declarado com uma referência ENV que outra pessoa poderia substituir.

por exemplo

ENV PROJ_VOL / algum / caminho
VOLUME $ PROJ_VOL

Parece que ENTRYPOINT [] e ENTRYPOINT [""] invalidam o cache em cada compilação quando não estão usando o BuildKit. Simples Dockerfile para demonstrar:

FROM jrottenberg/ffmpeg:4.3-alpine311 as base

ENTRYPOINT []

RUN echo "HERE!"

As etapas 2 e 3 _nunca_ usarão cache. Esta é a minha solução alternativa:

FROM jrottenberg/ffmpeg:4.3-alpine311 as base

ENTRYPOINT ["/usr/bin/env"]

RUN echo "HERE!"

Não consigo reproduzir uma falha de cache em seu primeiro padrão:: confused:

$ cat Dockerfile
FROM alpine:3.12
ENTRYPOINT []
RUN echo 'HERE!'

$ docker build .
Sending build context to Docker daemon  17.25MB
Step 1/3 : FROM alpine:3.12
 ---> a24bb4013296
Step 2/3 : ENTRYPOINT []
 ---> Running in d921be2e563d
Removing intermediate container d921be2e563d
 ---> 7801c649d895
Step 3/3 : RUN echo 'HERE!'
 ---> Running in 9e2ca2cf1f9f
HERE!
Removing intermediate container 9e2ca2cf1f9f
 ---> d398fdd442b1
Successfully built d398fdd442b1

$ docker build .
Sending build context to Docker daemon  17.25MB
Step 1/3 : FROM alpine:3.12
 ---> a24bb4013296
Step 2/3 : ENTRYPOINT []
 ---> Using cache
 ---> 7801c649d895
Step 3/3 : RUN echo 'HERE!'
 ---> Using cache
 ---> d398fdd442b1
Successfully built d398fdd442b1

Acho que você deve usar uma imagem que defina ENTRYPOINT . Tente usar a imagem que fiz ou mysql .

Que interessante - posso reproduzir usando mysql:8.0 . Bug sólido! : +1:

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