Dicas para Reduzir o Tamanho das Imagens do Docker e Melhorar seu Desempenho

Dicas para Reduzir o Tamanho das Imagens do Docker e Melhorar seu Desempenho

Não há mais como fugir, cedo ou tarde estaremos esbarrando com a pequena baleia amigável. Aprenderemos o que é container, qual o papel do Docker no meio disso tudo, e começaremos a criar nossas imagens.

Ao fornecer nossas aplicações empacotadas com todas as dependências embutidas, uma nova gama de possibilidades aparece. Porém, com a facilidade que o Docker nos oferece e a velocidade das entregas, podemos esperar que essas imagens ficarão ligeiramente inchadas. E aquela baleia ali em cima poderá não ficar tão contente com o peso dos seus containers.

Mas porque reduzir o tamanho das imagens do Docker?

Se você pensou nisso, você não está errado. O Docker tem seu sistema de arquivos baseado em camadas, e uma vez que a camada esteja disponível por conta do download ou upload da imagem, outras instâncias não necessariamente significam mais espaço alocado.

Mas outras perguntas podem, e provavelmente serão feitas:

  • Com muitas camadas, uma aplicação com leitura excessiva seria prejudicada?
  • Se estivermos rodando o container em um cluster Swarm ou Kubernetes, o deploy ficará mais demorado?
  • Se a imagem ficar muito grande, os desenvolvedores terão dificuldades em baixar?
  • Se estivermos guardando essas versões em um repositório de artefatos, terei problemas com muitas versões simultâneas?
  • Durante as etapas da pipeline de construção, testes e integrações, o tamanho da imagem interferiria em sua movimentação?

No geral, para as perguntas acima, as respostas são sim. Mas pense que, quanto menos dados existirem em suas imagens, proporcionalmente menores serão as chances de problemas e vulnerabilidades.

Talvez a primeira pergunta seja a mais interessante, quanto mais camadas existirem mais verificações o Docker deverá fazer para encontrar o arquivo procurado.

Dito isso, aqui vão 3 dicas para você diminuir o tamanho de suas imagens:

1 – Alpine

Se você não precisa de nenhuma especificidade de algum sistema, considere o uso de imagens baseadas em Alpine. Veja a diferença entre uma imagem baseada em Alpine e outra baseada na imagem slim do Debian:

$ docker images
REPOSITORY   TAG            IMAGE ID       CREATED       SIZE
alpine       latest         cdf98d1859c1   3 weeks ago   5.53MB
debian       stretch-slim   c08899734c03   5 weeks ago   55.3MB

O Debian, talvez minha distribuição Linux favorita, possuí praticamente 50MB a mais que o Alpine!

2 – Sem cache de instalação

É muito comum que ao instalarmos alguns pacotes, uma nova lista seja baixada e guardada no sistema, ou mesmo que alguns pacotes fiquem armazenados por questões de cache. Como estamos trabalhando com containers, esse comportamento é quase sempre indesejado. Se você não estiver utilizando nenhum repositório extra, haverá uma economia de pouco mais de 1MB nas imagens baseadas em Alpine:

# Com cache
FROM alpine
RUN apk add curl

# Sem cache
FROM alpine
RUN apk add --no-cache curl

Vamos ver a diferença entre elas:

$ docker images
REPOSITORY       TAG      IMAGE ID       CREATED         SIZE
alpine-cache     latest   6183cfea7d5a   8 seconds ago   8.39MB
alpine-no-cache  latest   752388fc4db8   28 seconds ago  7.08MB

Você já deve estar se imaginando que seus containers baseados em Debian estão cheios de lixo, certo? Não se preocupe, as imagens do Debian estão configuradas para não manter cache dos pacotes!

3 – Multi-Stage Build

Os pacotes de compilação representam um conjunto quase sempre descartável do container, utilizado para obter um binário. Portanto, depois da compilação não são mais necessários.

Mas qual o problema?

Talvez alguém aí já passou por isso porque compilou o módulo do MongoDB para o PHP por exemplo. E agora? É verdade, aqui está o Dockerfile:

FROM alpine
EXPOSE 8080
RUN apk add --no-cache php7-cli php7-json php7-openssl php7-pear php7-dev gcc libc-dev openssl-dev make; \
pecl channel-update pecl.php.net; \
pecl install mongodb; \
echo extension=mongodb.so > /etc/php7/conf.d/10_mongodb.ini; \
mkdir -p /var/www/html; \
echo '<?php phpinfo();' > /var/www/html/index.php
CMD ["/usr/bin/php", "-S", "0.0.0.0:8080", "-t", "/var/www/html"]

Construa a imagem com o subcomando build:

docker build -t php-mongo .

Qual será o tamanho desta imagem? Vamos verificar!

docker images

A saída mostrará que a imagem possuí mais de 200 megas!

REPOSITORY              TAG                 IMAGE ID            CREATED             SIZE
php-mongo               latest              a9e51dc72612        3 minutes ago       212MB

A imagem ficou deste tamanho pois precisamos baixar o GCC e o código fonte necessários dos pacotes que queríamos compilar, bem como suas dependências.

A partir da versão 17.05 o Docker passou a suportar multi-stage build, dessa forma é possível separar e descartar toda a camada utilizada para a compilação, copiando apenas o necessário, neste caso descartaremos uma camada temporária propositalmente para utilizar apenas o binário resultante da compilação:

FROM alpine
RUN apk add --no-cache php7-cli php7-json php7-openssl php7-pear php7-dev gcc libc-dev openssl-dev make; \
pecl channel-update pecl.php.net; \
pecl install mongodb

FROM alpine
EXPOSE 8080
RUN apk add --no-cache php7-cli php7-json php7-openssl; \
echo extension=mongodb.so > /etc/php7/conf.d/10_mongodb.ini; \
mkdir -p /var/www/html; \
echo '<?php phpinfo();' > /var/www/html/index.php
COPY --from=0 /usr/lib/php7/modules/mongodb.so /usr/lib/php7/modules/mongodb.so
CMD ["/usr/bin/php", "-S", "0.0.0.0:8080", "-t", "/var/www/html"]

Construa a imagem com o subcomando build:

docker build -t php-mongo-multi .

E agora, qual o tamanho da nova imagem?

REPOSITORY         TAG       IMAGE ID       CREATED              SIZE
php-mongo-multi    latest    2c891f81f76d   About a minute ago   21.4MB
php-mongo          latest    a9e51dc72612   17 minutes ago       212MB

Incrível, não? Faça o teste, ambas as imagens funcionam exatamente da mesma forma:

docker run -ti -p 8080:8080 php-mongo sh
docker run -ti -p 8181:8080 php-mongo-multi sh

Se você quiser, pode abrir a página no seu navegador com localhost:8080 e 8181 e procurar por mongodb, as extensões estarão instaladas!

Está vendo aquela camada imensa? Sim, nós removemos!

Então é isso! Espero que tenham gostado.

Neste post aprendemos três coisas:

  1. Utilizar imagens baseadas em Alpine por serem bem menores
  2. Procurar por opções de instalação que removam o cache, neste caso –no-cache
  3. Remover as camadas utilizadas para compilação ou qualquer outra ação que gere arquivos desnecessários no futuro

Até a próxima !

 

CURSOSCONSULTORIA    CONTATO

Anterior Entenda o Terraform e como ele se encaixa na Infraestrutura Ágil
Próxima Kubernetes - Configurando um Cluster Multi-Master

About author

Hector Silva
Hector Silva 11 posts

Hector Vido Silva atua como Consultor de Infraestrutura em Software Livre, cursando Engenharia da Computação, formado em Análise e Desenvolvimento de Sistemas com MBA em Cibersegurança. Atua desde 2006 com desenvolvimento, implantação, arquitetura e resolução de problemas em ambientes envolvendo diferentes plataformas. Na 4Linux também ministra os cursos de desenvolvimento, banco de dados e infraestrutura para ambientes ágeis e automatizados com forte utilização de contêineres. Sim, é um generalista. Possuí certificações CKA, Openshift, LPIC-2, LPI DevOps, GCP Engineer, MongoDB, Blockchain e ZCE.

View all posts by this author →

Você pode gostar também

Infraestrutura TI

Autenticando terraform na Google Cloud sem compartilhamento de chaves

O terraform atualmente é, de longe, a ferramenta de infraestrutura como código mais popular no mundo de TI e de Cloud. Ele tem suporte aos principais provedores de cloud e

Infraestrutura TI

Entenda o Log Binário do MySQL e suas aplicações práticas

O log binário do MySQL é, por vezes, mal compreendido, principalmente por usuários de outros bancos de dados. Nesta postagem pretendo abordar alguns aspectos desse importante mecanismo. Write-ahead logging? Também

Infraestrutura TI

Descubra o poder do Kubernetes e como ele pode impulsionar suas aplicações

    Kubernetes ou “k8s” para os íntimos, é uma ferramenta de código aberto originalmente desenvolvido pela Google, utilizado para a orquestração de containers, ou seja, para implantação, dimensionamento e