Nesta parte da tradução da série Docker, falaremos sobre como otimizar o tamanho da imagem e acelerar a montagem. Em materiais anteriores, comparamos imagens do Docker com pizza, termos com rosquinhas e instruções do Dockerfile com bagels. Hoje não haverá cozimento. É hora de fazer dieta.
→
Parte 1: o básico→
Parte 2: termos e conceitos→
Parte 3: arquivos Dockerfile→
Parte 4: reduzindo o tamanho das imagens e acelerando sua montagem→
Parte 5: equipes→
Parte 6: trabalhando com dadosPara entender o que falaremos aqui, será útil atualizar a memória do que foi discutido na
terceira parte desta série de materiais. Nomeadamente, falamos sobre as instruções do arquivo Dockerfile. Conhecer essas instruções e os recursos do Docker que discutimos hoje ajudará você a otimizar seus arquivos de imagem do Docker.
Armazenamento em cache
Um dos pontos fortes do Docker é o cache. Graças a esse mecanismo, a montagem de imagens é acelerada.
Ao montar uma imagem do Docker, segue as instruções do Dockerfile, seguindo-as em ordem. No processo de análise das instruções, o Docker verifica o seu próprio cache em busca de imagens, que é o que obtemos nos estágios intermediários da montagem de outras imagens. Se tais imagens puderem ser encontradas, o sistema poderá usá-las sem perder tempo em recriá-las.
Se o cache for invalidado, a instrução durante a qual ele será executado será criada, criando uma nova camada sem usar o cache. O mesmo acontece ao executar as instruções a seguir.
Como resultado, se, durante a execução das instruções do Dockerfile, a imagem base estiver no cache, essa imagem do cache será usada. Isso é chamado de hit de cache. Se a imagem base não estiver no cache, todo o processo de montagem da imagem ocorrerá sem o uso do cache.
Em seguida, a instrução a seguir é comparada com todas as imagens do cache, que são baseadas na mesma imagem básica que já foi encontrada no cache. Cada imagem intermediária em cache é verificada para ver se contém o que foi criado pela mesma instrução. Se uma correspondência não puder ser encontrada, isso é chamado de "falha de cache" e o cache é considerado inválido. O mesmo acontece até que todo o Dockerfile seja processado.
A maioria das novas instruções é simplesmente comparada com o que já está nas imagens intermediárias. Se o sistema conseguir encontrar uma correspondência, a montagem usará o que já está no cache.
O uso de um cache pode acelerar a montagem de imagens, mas há um problema. Por exemplo, se uma instrução
RUN pip install -r requirements.txt
for encontrada em um Dockerfile, o Docker procurará a mesma instrução em seu cache local de imagens intermediárias. No entanto, o conteúdo das versões antiga e nova do arquivo
requirements.txt
não são comparados.
Isso pode causar problemas se as informações sobre novos pacotes forem adicionadas ao
requirements.txt
, após o qual, ao criar a imagem atualizada, para instalar um novo conjunto de pacotes, você precisará executar a instrução
RUN pip install
novamente. Em breve falaremos sobre como lidar com esse problema.
Ao contrário de outras instruções do Docker, ao executar as instruções
ADD
e
COPY
, o Docker precisa verificar o conteúdo do arquivo ou arquivos para determinar se o cache pode ser usado ao criar a imagem. Ou seja, a soma de verificação dos arquivos mencionados nestas instruções é comparada com a soma de verificação dos arquivos que estão nas imagens intermediárias que já estão no cache. Se o conteúdo dos arquivos ou seus metadados tiver sido alterado, o cache será invalidado.
Aqui estão algumas dicas para aproveitar o cache do Docker:
Se você conhece outras maneiras de lidar com o "problema requirements.txt", pode falar sobre elas nos comentários.
Reduzindo o tamanho das imagens
Selection Seleção cuidadosa da imagem básica
As imagens do Docker podem ser bem grandes. Isso contradiz o desejo bem fundamentado da pessoa que os cria de torná-los o mais compactos possível, o que facilitará o download de um repositório remoto e terá um efeito benéfico na quantidade de espaço livre no computador em que estão carregados. Vamos falar sobre como reduzir seu tamanho.
Em vez de rosquinhas e rosquinhas, agora vamos comer verdurasUma maneira de reduzir o tamanho das imagens é selecionar cuidadosamente as imagens básicas e seu ajuste subsequente.
Por exemplo, a imagem básica do Alpine é uma distribuição completa de um sistema operacional semelhante ao Linux, contendo um mínimo de pacotes adicionais. Seu tamanho é de aproximadamente 5 megabytes. No entanto, criar sua própria imagem com base no Alpine exigirá muito tempo para equipá-la com tudo o necessário para garantir a operação de um determinado aplicativo.
Existem também versões especializadas da imagem básica dos Alpes. Por exemplo, a imagem correspondente do repositório python no qual o script
print("hello world")
é empacotado pesa cerca de 78,5 MB. Aqui está o Dockerfile para criar uma imagem como essa:
FROM python:3.7.2-alpine3.8 COPY . /app ENTRYPOINT ["python", "./app/my_script.py", "my_var"]
Ao mesmo tempo, o Docker Hub diz que esta imagem básica tem um tamanho de 29 MB. O tamanho de uma imagem com base nessa imagem base é aumentado baixando e instalando o Python.
Além de usar imagens básicas baseadas no Alpine, você pode reduzir o tamanho das imagens através do uso da tecnologia de montagem em vários estágios.
Assembly Montagem de imagens em vários estágios
O Dockerfile, que descreve a montagem de vários estágios de uma imagem, usa várias instruções
FROM
. O criador dessa imagem pode configurar a cópia seletiva de arquivos chamados artefatos de construção de um nível de construção para outro. Ao mesmo tempo, torna-se possível se livrar de tudo o que não é necessário na imagem final. Graças a este método, você pode reduzir o tamanho da imagem final.
Veja como cada instrução
FROM
funciona:
- Ela inicia uma nova etapa de compilação.
- Não depende do que foi criado na etapa de compilação anterior.
- Ela pode usar uma imagem básica diferente da usada na etapa anterior.
Aqui está um exemplo modificado de um Dockerfile da
documentação do Docker
que descreve uma compilação de vários estágios.
FROM golang:1.7.3 AS build WORKDIR /go/src/github.com/alexellis/href-counter/ RUN go get -d -v golang.org/x/net/html COPY app.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=build /go/src/github.com/alexellis/href-counter/app . CMD ["./app"]
Observe que fornecemos o nome do primeiro estágio da montagem, especificando-o após a instrução
FROM
. Nós nos referimos à fase de construção nomeada na
COPY --from=
abaixo no arquivo de encaixe.
O uso do processo de montagem de imagens em vários estágios faz sentido em alguns casos quando você precisa criar muitos contêineres para o ambiente de produção. A montagem de vários estágios permite minimizar o tamanho da imagem final. Mas, às vezes, essa abordagem complica o suporte de imagens. Portanto, você provavelmente não usará montagem de imagens em vários estágios nos casos em que pode ficar sem ela. Você pode ler sobre os recursos desta tecnologia
aqui e
aqui .
Como você pode ver, a montagem em vários estágios é uma tecnologia interessante, mas não é adequada para todos os casos. A mesma maneira de reduzir o tamanho das imagens, que discutiremos abaixo, pode ser recomendada a absolutamente todos.
▍ arquivo .dockerignore
Absolutamente todo mundo que deseja aprender o Docker precisa conhecer os arquivos
.dockerignore
. Esses arquivos são semelhantes aos arquivos
.gitignore
. Eles contêm uma lista de arquivos e pastas, na forma de nomes ou modelos que o Docker deve ignorar durante a montagem da imagem.
Esse arquivo é colocado onde o Dockerfile está localizado e tudo o mais incluído no contexto do assembly da imagem.
Quando você executa o
docker build
, que inicia a montagem da imagem, o Docker verifica a pasta quanto à presença do arquivo
.dockerignore
nela. Se esse arquivo puder ser encontrado, ele será analisado e as
regras da função
Match()
do pacote
filepath
Go e algumas
regras próprias do Docker serão usadas para determinar a lista de arquivos a serem ignorados.
Portanto, por exemplo, se um modelo do formulário
*.jpg
encontrado no arquivo
.dockerignore
, ao criar uma imagem, os arquivos com qualquer nome e com a extensão
.jpg
serão ignorados. Se a sequência de
videos
no arquivo, o sistema ignorará a pasta de
videos
e todo o seu conteúdo.
Ao compilar um arquivo
.dockerignore
, você pode comentá-lo usando o símbolo
#
.
Aqui está o que o arquivo
.dockerignore
oferece a quem cria imagens do Docker:
- Isso permite excluir dos arquivos de imagem que contêm informações confidenciais, como logins e senhas.
- Isso permite reduzir o tamanho da imagem. Quanto menores os arquivos na imagem, menor será o tamanho e mais rápido será possível trabalhar com ele.
- Isso torna possível reduzir o número de razões para invalidar o cache ao montar imagens semelhantes. Por exemplo, se durante a remontagem da imagem alguns arquivos de serviço do projeto forem alterados, como arquivos de log, pelos quais os dados armazenados no cache são, em essência, invalidados de forma irracional, isso torna a montagem das imagens mais lenta.
.dockerignore
pode ler mais sobre o arquivo
.dockerignore
na
documentação do Docker.
Pesquisa de tamanho de imagem
Vamos falar sobre como usar as ferramentas de linha de comando para descobrir os tamanhos das imagens e contêineres do Docker.
- Para descobrir o tamanho aproximado de um contêiner em execução, você pode usar um comando do
docker container ls -s
formulário docker container ls -s
. - O
docker image ls
exibe os tamanhos da docker image ls
. - Você pode usar o
docker image history my_image:my_tag
da docker image history my_image:my_tag
descobrir os tamanhos das imagens intermediárias nas quais uma determinada imagem é montada. - A
docker image inspect my_image:tag
permite descobrir informações detalhadas sobre a imagem, incluindo o tamanho de cada uma de suas camadas. As camadas são um pouco diferentes das imagens intermediárias que compõem a imagem final, mas, na maioria dos casos, podem ser consideradas entidades idênticas. Aqui está um bom material sobre os detalhes da estrutura interna das imagens do Docker. - Para examinar o conteúdo dos contêineres, você pode instalar o pacote de mergulho .
Agora que discutimos as possibilidades de reduzir o tamanho das imagens, trago à sua atenção oito recomendações sobre como reduzir o tamanho das imagens e acelerar o processo de montagem.
Recomendações para reduzir o tamanho das imagens e acelerar o processo de montagem
- Sempre que possível, use imagens oficiais como imagens básicas. Imagens oficiais são atualizadas regularmente, são mais seguras que imagens informais.
- Para coletar imagens o mais compactas possível, use imagens básicas baseadas no Alpine Linux.
- Se você usar o
apt
, combine os comandos apt-get update
e apt-get install
em uma instrução RUN
. Além disso, combine os comandos de instalação do pacote em uma única instrução. Listar pacotes em ordem alfabética em várias linhas, separando a lista com \
. Por exemplo, pode ser assim:
RUN apt-get update && apt-get install -y \ package-one \ package-two \ package-three && rm -rf /var/lib/apt/lists/*
Esse método reduz o número de camadas que devem ser adicionadas à imagem e ajuda a manter o código do arquivo de forma decente. - Inclua uma construção como
&& rm -rf /var/lib/apt/lists/*
no final da instrução RUN
usada para instalar pacotes. Isso limpará o cache do apt
e fará com que ele não seja salvo na camada formada pelo comando RUN
. Detalhes sobre isso podem ser encontrados na documentação . - Use seus recursos de armazenamento em cache com sabedoria, colocando comandos no Dockerfile com alta probabilidade de alteração perto do final do arquivo.
- Use o arquivo
.dockerignore
. - Dê uma olhada no
dive
, uma ótima ferramenta para explorar imagens do Docker que ajuda a reduzir seu tamanho. - Não instale pacotes que possam ser dispensados.
Sumário
Agora você sabe como criar imagens do Docker rapidamente, carregar rapidamente de repositórios e não ocupar muito espaço no computador. Da próxima vez, falaremos sobre as equipes do Docker.
Caros leitores! Você encontrou problemas com os mecanismos de cache ao criar imagens do Docker?
