O que são camadas de imagem do Docker?

0
34


As imagens do Docker consistem em várias camadas que juntas fornecem o conteúdo que você vê em seus contêineres. Mas o que é realmente uma camada e como ela é diferente de uma imagem completa?

Neste artigo, você aprenderá a distinguir esses dois conceitos e por que a diferença é importante. Embora você possa usar o Docker sem uma compreensão profunda das camadas, entender sua finalidade o ajudará a identificar oportunidades de otimização.

O que é uma imagem?

Uma “imagem” do Docker se comporta como um modelo a partir do qual contêineres consistentes podem ser criados. Se o Docker fosse uma máquina virtual tradicional, a imagem poderia ser comparada ao ISO usado para instalar sua VM. Essa não é uma comparação forte, pois o Docker difere das máquinas virtuais em termos de conceito e implementação, mas é um ponto de partida útil.

As imagens definem o estado inicial do sistema de arquivos de novos contêineres. Eles agrupam o código-fonte do aplicativo e suas dependências em um pacote independente que está pronto para uso com um tempo de execução de contêiner. Dentro da imagem, o conteúdo do sistema de arquivos é representado como várias camadas separadas.

O que são camadas?

As camadas são o resultado da maneira como as imagens do Docker são criadas. Cada etapa em um Dockerfile cria uma nova “camada” que é essencialmente uma diferença das alterações do sistema de arquivos desde a última etapa. instruções de metadados como LABEL S MAINTAINER não crie camadas porque elas não afetam o sistema de arquivos.

Esta imagem tem duas instruções (COPY S RUN) para criar duas camadas:

FROM ubuntu:latest
COPY foo.txt /foo.txt
RUN date > /built-on.txt
  • O primeiro passo copia foo.txt em uma nova camada que é baseada no ubuntu:latest imagem.
  • A segunda etapa executa o date e canalize sua saída para um arquivo. Isso cria uma segunda camada que se baseia na anterior.

Para criar foo.txt em seu diretório de trabalho:

$ echo "Hello World" > foo.txt

Agora crie a imagem de exemplo:

$ docker build . -t demo:latest
Sending build context to Docker daemon   2.56kB
Step 1/3 : FROM ubuntu:latest
 ---> df5de72bdb3b
Step 2/3 : COPY foo.txt /foo.txt
 ---> 4932aede6a15
Step 3/3 : RUN date > /built-on.txt
 ---> Running in 91d260fc2e68
Removing intermediate container 91d260fc2e68
 ---> 6f653c6a60fa
Successfully built 6f653c6a60fa
Successfully tagged foo:latest

Cada etapa de construção gera o ID da camada criada. A camada da última etapa torna-se a imagem final, por isso é rotulada com foo:latest.

A sequência revela que camadas são imagens válidas do Docker. Embora o termo “camada” não seja normalmente usado para se referir a uma imagem marcada, todas as imagens marcadas são tecnicamente apenas camadas com um identificador atribuído.

Você pode iniciar um contêiner a partir de uma imagem da camada intermediária:

$ docker run -it 4932aede6a15 sh
# cat /foo.txt
Hello World
# cat /built-on.txt
cat: /built-on.txt: No such file or directory

Este exemplo inicia um contêiner da camada criada pela segunda etapa de compilação. foo.txt está disponível no recipiente, mas built-on.txt não existe porque não é adicionado até a terceira etapa. Esse arquivo está disponível apenas nos sistemas de arquivos das camadas posteriores.

O papel das camadas

As camadas contêm as alterações criadas por uma etapa de compilação, em relação à camada anterior no Dockerfile. FROM As instruções são um caso especial que se refere à camada final de uma imagem existente.

As camadas permitem que as etapas de construção sejam armazenadas em cache para evitar trabalho redundante. O Docker pode pular instruções sem alterar seu Dockerfile reutilizando a camada criada anteriormente. Baseie a próxima etapa nessa camada existente, em vez de construir uma nova.

Você pode ver isso modificando seu Dockerfile da seguinte forma:

FROM ubuntu:latest
COPY foo.txt /foo.txt
RUN date +%Y-%m-%d > /built-on.txt

A terceira etapa de construção foi alterada. Agora reconstrua sua imagem:

$ docker build . -t demo:latest
Sending build context to Docker daemon  3.584kB
Step 1/3 : FROM ubuntu:latest
 ---> df5de72bdb3b
Step 2/3 : COPY foo.txt /foo.txt
 ---> Using cache
 ---> 4932aede6a15
Step 3/3 : RUN date +%Y-%m-%d > /built-on.txt
 ---> Running in 2b91ec0462c4
Removing intermediate container 2b91ec0462c4
 ---> c6647ff378c1
Successfully built c6647ff378c1
Successfully tagged demo:latest

A segunda etapa de construção é mostrada como Using cache e produz o mesmo ID de camada. O Docker pode pular a criação dessa camada, pois ela já foi criada anteriormente e foo.txt não mudou desde a primeira compilação.

Esse cache só funciona até o ponto em que uma camada é modificada. Todas as etapas após essa camada também precisarão ser reconstruídas para se basearem na nova revisão do sistema de arquivos.

Outro benefício das camadas é como elas permitem que imagens parciais sejam extraídas. Depois de baixar algumas imagens para sua máquina, você descobrirá que novos pulls podem pular algumas camadas que você já possui. Esta imagem contém 13 camadas, mas a operação de extração precisou baixar apenas seis:

docker pull php:8.0-apache
8.0-apache: Pulling from library/php
7a6db449b51b: Already exists 
ad2afdb99a9d: Already exists 
dbc5aa907229: Already exists 
82f252ab4ad1: Already exists 
bf5b34fc9894: Already exists 
6161651d3d95: Already exists 
cf2adf296ef1: Already exists 
f0d7c5221e44: Pull complete 
f647198f6316: Pull complete 
c37afe1da4e5: Pull complete 
09c93531cbca: Pull complete 
fef371007dd3: Pull complete 
52043dbb1c06: Pull complete 
Digest: sha256:429889e8f9eac0a806a005b0728a004303b0d49d77b09496d39158707abd6280
Status: Downloaded newer image for php:8.0-apache
docker.io/library/php:8.0-apache

As outras camadas já estavam presentes no host do Docker para que pudessem ser reutilizadas. Isso melhora o desempenho e evita o desperdício de largura de banda da rede.

Inspeção da camada de imagem

Você pode listar as camadas dentro de uma imagem executando o docker image history domínio. Cada camada mostra o ID da imagem criada e a instrução Dockerfile que causou a alteração. Você também pode ver o tamanho total do conteúdo dentro da camada.

$ docker image history 
IMAGE          CREATED         CREATED BY                                      SIZE      COMMENT
6f653c6a60fa   4 minutes ago   /bin/sh -c date > /built-on.txt                 29B       
f8420d1a96f3   4 minutes ago   /bin/sh -c #(nop) COPY file:a5630a7506b26a37...   0B        
df5de72bdb3b   4 weeks ago     /bin/sh -c #(nop)  CMD ["bash"]                 0B        
<missing>      4 weeks ago     /bin/sh -c #(nop) ADD file:396eeb65c8d737180...   77.8MB    

A última camada é mostrada como <missing> porque se refere a uma camada dentro do ubuntu:latest imagem base Não está disponível localmente, pois apenas a camada final da imagem base (df5de72bdb3b) é puxado para baixo durante as compilações. Não é necessário extrair independentemente todas as camadas intermediárias quando você deseja usar uma imagem específica.

Resumo

Imagens e camadas do Docker geralmente são termos intercambiáveis. Uma camada é uma imagem e uma imagem é composta de uma ou mais camadas. A principal diferença está nas tags: uma imagem será marcada e renderizada para usuários finais, enquanto o termo “camada” normalmente se refere às imagens intermediárias não marcadas criadas como parte de uma operação de compilação. Estes não são visíveis a menos que você vá procurá-los.

Há mais um problema relacionado às camadas: os contêineres em execução adicionam uma camada de escrita adicional na parte superior da sua imagem. As camadas provenientes da imagem do contêiner são somente leitura, portanto, as modificações do sistema de arquivos feitas pelo contêiner apontam para sua camada gravável efêmera. A camada de gravação é descartada quando o contêiner é interrompido ou excluído.