Imagens do Docker – Como Reduzi-las na Prática!

Imagens do Docker – Como Reduzi-las na Prática!

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 Provisionamento de hosts automatizado no VMWare-vSphere utilizando Terraform.
Próxima Kubernetes - Configurando um Cluster Multi-Master

About author

Hector Silva
Hector Silva 4 posts

Hector Vido Silva atua como Analista de Infraestrutura em Software Livre, cursando MBA em Segurança, formado em Análise e Desenvolvimento de Sistemas. Possuí mais de 10 anos de experiência em desenvolvimento, implantação e arquitetura de sistemas envolvendo diferentes plataformas. Atualmente ministra os cursos de desenvolvimento, banco de dados e infraestrutura para ambientes ágeis e automatizados com forte utilização de contêineres. Possuí as certificações CKA, LPIC-2, LPI DevOps e ZCE.

View all posts by this author →

Você pode gostar também

Infraestrutura

Conheça mais sobre os serviços de Gestão de Riscos e Testes de Intrusão

Tecnologia de informação está cada vez mais relacionada aos processos produtivos e já mudou a forma de fazer negócios. Se a evolução dos setores de TI possibilitou maior produtividade e

DevOps

DevOps – o que é e quais são seus benefícios?

Provavelmente você conheça o termo DevOps e tenha dúvida sobre do que realmente se trata. Há quem defenda que se trata de uma cultura, outros apostam que seja uma metodologia, há quem

Infraestrutura

MongoDB: como gerenciar dados com noSQL

Dando continuidade na série de MongoDB, após construir um Cluster de MongoDB usando o passo a passo do desse artigo, vamos agora manipular os dados dentro desse banco, ou como