[ad_1]
As imagens do Docker são criadas criando Dockerfiles. O processo de compilação executa as instruções no Dockerfile para criar as camadas do sistema de arquivos que compõem a imagem final.
E se você já tiver uma imagem? Você pode recuperar o Dockerfile do qual ele foi criado? Neste artigo, veremos dois métodos que podem fazer isso.
O objetivo
Ao criar suas próprias imagens do Docker, você deve armazenar seus Dockerfiles como arquivos com controle de versão em seu repositório de origem. Essa prática garante que você sempre possa recuperar as instruções usadas para montar suas imagens.
No entanto, às vezes você não terá acesso a um Dockerfile. Talvez você esteja usando uma imagem que está em um registro público, mas tem um repositório de origem inacessível. Ou você pode estar trabalhando com instantâneos de imagem que não correspondem diretamente a um Dockerfile com versão. Nesses casos, você precisa de uma técnica que possa criar um Dockerfile a partir de uma imagem em sua máquina.
O Docker não oferece nenhuma funcionalidade interna para fazer isso. As imagens de compilação não têm uma associação com o Dockerfile a partir do qual foram criadas. No entanto, você pode fazer engenharia reversa do processo de compilação para produzir uma boa aproximação do Dockerfile de uma imagem sob demanda.
O comando de histórico do Docker
a docker history
O comando revela o histórico da camada de uma imagem. Ele mostra o comando usado para construir cada camada sucessiva do sistema de arquivos, tornando-o um bom ponto de partida ao reproduzir um Dockerfile.
Aqui está um Dockerfile simples para um aplicativo Node.js:
FROM node:16 COPY app.js . RUN app.js --init CMD ["app.js"]
Construa a imagem usando docker build
:
$ docker build -t node-app:latest .
Agora inspecione o histórico da camada da imagem com docker history
:
$ docker history node-app:last IMAGE CREATED BY SIZE COMMENT c06fc21a8eed 8 segundos atrás /bin/sh -c# (nop) CMD ["app.js"] 0B 74d58e07103b 8 segundos atrás /bin/sh -c ./app.js --init 0B 22ea63ef9389 19 segundos atrás /bin/sh -c # (nop) COPY file: 0c0828d0765af4dd ... 50B 424bc28f998d 4 dias atrás /bin/sh -c # (não) CMD ["node"] 0B4 dias atrás /bin/sh -c# (nop) PONTO DE ENTRADA ["docker-entry... 0B ...
The history includes the complete list of layers in the image, including those inherited from the node:16
base image. Layers are ordered so the most recent one is first. You can spot where the layers created by the sample Dockerfile begin based on the creation time. These show Docker’s internal representation of the COPY
and CMD
instructions used in the Dockerfile.
The docker history
output is more useful when the table’s limited to just showing each layer’s command. You can disable truncation too to view the full command associated with each layer:
$ docker history node-app:latest --format "{{.CreatedBy}}" --no-trunc /bin/sh -c #(nop) CMD ["app.js"]/bin/sh -c ./app.js --init /bin/sh -c # (nop) COPIAR arquivo: 0c0828d0765af4dd87b893f355e5dff77d6932d452f5681dfb98fd9cf05e8eb1 em . /bin/sh -c # (não) CMD ["node"]/bin/sh -c # (nop) PONTO DE ENTRADA ["docker-entrypoint.sh"]...
A partir desta lista de comandos, você pode obter uma visão geral das etapas realizadas para montar a imagem. Para imagens simples como essa, essas informações podem ser suficientes para reproduzir com precisão um Dockerfile.
copiar comandos de docker history
é um processo trabalhoso. Também é necessário remover o /bin/sh -c
no início de cada linha, já que o Docker tratou cada instrução como um comentário Bash sem operações.
Felizmente, existem ferramentas da comunidade disponíveis que podem automatizar a criação de um Dockerfile a partir do histórico de camadas de uma imagem. Para os propósitos deste artigo, vamos nos concentrar no Whaler, que está incluído no alpine/dfimage
(Dockerfile-from-Image) Imagem do Docker da organização Alpine.
executando o dfimage
image e fornecer uma tag do Docker gerará um Dockerfile que pode ser usado para reproduzir a imagem referenciada. Você precisa vincular o soquete Docker do seu host no dfimage
container para que você possa acessar sua lista de imagens e extrair a tag se necessário.
$ docker run --rm -v /var/run/docker.sock:/var/run/docker.sock alpine/dfimage node-app:latest Analyzing node-app:latest Docker Version: 20.10.13 GraphDriver: overlay2 Environment Variables |PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin |NODE_VERSION=16.14.2 |YARN_VERSION=1.22.18 Image user |User is root Dockerfile: ... ENTRYPOINT ["docker-entrypoint.sh"] CMD ["node"] COPY file:bcbc3d5784a8f1017653685866d30e230cae61d0da13dae32525b784383ac75f in . app.js RUN ./app.js --init CMD ["app.js"]
O Dockerfile criado contém tudo o que você precisa para ir scratch
(um sistema de arquivos vazio) para a camada final da imagem especificada. Inclui todas as camadas que vêm da imagem base. Você pode vê-los no primeiro ENTRYPOINT
S CMD
instruções na saída de exemplo acima (as outras camadas de imagem base foram omitidas por questões de brevidade).
Com a exceção de COPY
, as instruções específicas em nossa imagem correspondem ao que foi escrito no Dockerfile original. Agora você pode copiar estas instruções para um novo Dockerfile
seja usando todo o dfimage
saída ou pegando apenas a parte que pertence à imagem final. A última opção só é uma possibilidade se você souber a identidade da imagem base original para poder adicionar uma FROM
instruções no topo do arquivo.
limitações
Em muitos casos dfimage
você poderá montar um Dockerfile utilizável. No entanto, não é perfeito e uma correspondência exata não é garantida. A extensão das discrepâncias em comparação com o Dockerfile original na imagem varia de acordo com as instruções usadas.
Nem todas as instruções são capturadas no histórico da camada. Os que não são compatíveis serão perdidos e não há como determinar quais eram. A melhor precisão é obtida com instruções de comando e metadados como RUN
, ENV
, WORKDIR
, ENTRYPOINT
S CMD
. RUN
as instruções ainda podem estar faltando se o seu comando não resultar em alterações no sistema de arquivos, o que significa que uma nova camada de imagem não foi criada.
COPY
S ADD
As instruções apresentam desafios únicos. O histórico não contém o caminho do arquivo host que foi copiado para o contêiner. Você pode ver que ocorreu uma cópia, mas o caminho de origem se refere ao hash do arquivo que foi copiado para a imagem do contexto de compilação.
Ao chegar ao destino final, isso pode ser suficiente para ajudá-lo a determinar o que foi copiado e por quê. Você pode usar essas informações para interpolar um novo caminho de origem no Dockerfile que pode ser usado para compilações futuras. Em outros casos, inspecionar o arquivo dentro da imagem pode ajudar a revelar a finalidade da cópia para que você possa determinar um nome de arquivo significativo para o caminho do host.
Resumo
As imagens do Docker não incluem uma maneira direta de retornar ao Dockerfile a partir do qual foram criadas. No entanto, ainda é possível reconstruir o processo de construção. Para imagens simples com poucas instruções, muitas vezes você pode descobrir as instruções manualmente observando o CREATED BY
coluna na docker history
saída do comando.
Imagens maiores com processos de construção mais complexos são melhor analisadas com ferramentas como dfimage
. Isso faz o trabalho duro de analisar os detalhes docker history
saída para você, produzindo um novo Dockerfile que provavelmente é uma correspondência melhor para o original.
Os esforços de engenharia reversa não são perfeitos e algumas instruções do Dockerfile são perdidas ou corrompidas durante o processo de compilação. Consequentemente, você não deve presumir que os Dockerfiles criados dessa maneira são uma representação precisa do original. Você pode ter que fazer alguns ajustes manuais para ADD
S COPY
instruções também, ressuscitando caminhos de arquivo host que foram convertidos para criar referências de contexto.
[ad_2]