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!
Então é isso! Espero que tenham gostado.
Neste post aprendemos três coisas:
- Utilizar imagens baseadas em Alpine por serem bem menores
- Procurar por opções de instalação que removam o cache, neste caso –no-cache
- Remover as camadas utilizadas para compilação ou qualquer outra ação que gere arquivos desnecessários no futuro
Até a próxima !
About author
Você pode gostar também
Integração de Chat Funcional com Ferramenta Rocket.Chat: Passo a Passo
Dando continuidade o nosso post anterior onde entendemos como utilizar as APIs do Rocket.Chat para manipular o Omnichannel, agora iremos integrar um chat funcional com essa ferramenta. Irei partir do
Aumente sua empregabilidade: Conheça Linux e entre no mundo DEVOPS
Em 2013 eu escrevi um artigo intitulado “Por que você deve aprender Linux?” e quem teve a oportunidade de aprender linux nestes últimos 4 anos deve estar bem feliz com
Keycloak: Gerenciamento de Identidade e Acesso para WebApps e Serviços RESTful
O Keycloak [1] é um software open source de gerenciamento de identidade e acesso voltado para WebApps e RESTful web services. Inicialmente desenvolvido em 2014 pela comunidade de JBoss. Em