Oi, pessoal!
Hoje trouxemos para você um pequeno artigo mostrando como é possível criar uma imagem enxuta, somente com o que você precisa e utilizando menos espaço possível. Para isso, será necessário utilizar uma das duas imagens mais limpas do Docker, são elas: Alpine ou BusyBox. Focaremos na Alpine, uma das mais buscadas atualmente.
Para que não conhece, a Alpine é uma distribuição construída com musl libc e BusyBox, que é conhecida como canivete suíço, pois combina versões minúsculas de muitos utilitários comuns no UNIX em um único pequeno executável. Algumas características de Alpine:
Pequena
Enquanto a menor imagem para Docker precisa de cerca de 130MB de espaço em disco, a Alpine precisa de no máximo 8MB. Isso faz com que, mesmo você montando todo o seu ambiente, ele nunca terá o mesmo tamanho do que se montando em um imagem tradicional. Isso é ótimo, pois deixa o ambiente ainda mais enxuto e simples de migrar.
Simples
Você tem apenas aquilo que é necessário para o funcionamento de sua aplicação. Se precisar de mais alguma biblioteca, é só instalar. Você não precisa se preocupar em desativar ou remover lixos. Eles simplesmente não existem.
Segura
Alpine foi desenvolvida pensando em segurança; e para garantir isso, os desenvolvedores se preocuparam em aprimorar os recursos de segurança do kernel, como grsecurity/PaX. Além disso, todos os binários foram compilados em executáveis independente de posição, isso previne alguns problemas relacionados a buffer overflow e outros tipos de ataques envolvendo estouro de pilha.
Mãos a obra?
Nosso exemplo consistirá em montarmos uma imagem de com Alpine e Nodejs, e vamos comparar o tamanho da nova imagem que montamos com Alpine e outras distros disponíveis.
A aplicação será algo bem simples, apenas uma aplicação “olá, mundo”:
var http = require('http'); http.createServer(function(req,res) { res.writeHead(200, { 'Content-Type': 'text/plain; charset=utf-8' }); res.end('Exemplo Node.js Mundo Docker!'); }).listen(8080);
Colocamos o nome de app.js – não esqueça de criar o package.json com as dependências da aplicação:
{ "name": "docker_web_app", "version": "1.0.0", "description": "Node.js on Docker", "author": "First Last <first.last@example.com>", "main": "app.js" }
Agora criamos nosso Dockerfile:
FROM alpine:3.1 # Update RUN apk add --update nodejs # Cria a pasta da app RUN mkdir -p /usr/src/app WORKDIR /usr/src/app # Instala as dependencias da app COPY package.json /usr/src/app/ RUN npm install # copia a app COPY . /usr/src/app EXPOSE 8080 CMD ["node", "/usr/src/app/app.js"]
Não é nada muito complexo. Basta você informar qual imagem base utilizará e a diferença está no instalador de dependências, que para o Alpine é o apk. Agora vamos gerar a imagem:
docker build -t alpineteste .
Será gerado uma nova imagem com o nome de alpineteste. Agora vamos comparar o tamanho dessa imagem com outras:
Lembrando, que utilizamos a imagem base de cada distribuição e em cima dela instalamos o node e subimos essa aplicação. Note que a diferença é exorbitante, isso porque a Alpine tem apenas o que é necessário para essa aplicação rodar, nada além disso.
Como podem ver, utilizando essa abordagem seu ambiente fica ainda mais escalável e, claro, ainda mais portável, pois quanto menor a sua imagem, melhor é para transitá-la entre os hosts (não é necessário baixar megas e megas da imagem no primeiro deploy por exemplo) .
Grande abraço!