Oi Pessoal,

O MundoDocker trás hoje para você um pequeno tutorial de 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, nesse tutorial vamos focar 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 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 uso 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 <[email protected]>",
"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:

Alpine

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 por que 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 menos a sua imagem, melhor é para transitar ela entre os hosts (não é necessário baixar megas e megas da imagem no primeiro deploy por exemplo) .

Gostou? nos ajude divulgando o Blog 😉

Grande abraço!

Entusiasta Open Source, seu principal foco é ir atrás de ideias novas e torna-las realidade através de soluções simples e eficientes, o menos é mais, e o dividir é multiplicar.
  • Armando

    Fala pessoal,

    Como o exemplo não utiliza nada do expressJS, e o único arquivo é o “app.js” o package.json pode ser apenas:
    “`
    {
    “name”: “docker_web_app”,
    “version”: “1.0.0”,
    “description”: “Node.js on Docker”,
    “author”: “First Last “,
    “main”: “app.js”
    }
    “`
    e dentro do “app.js” tomar cuidado para o ‘listen’ utilizar a mesma porta descrita no EXPOSE do Dockerfile, ficaria algo assim no final do arquivo:
    “`
    }).listen(8080);
    “`

    Abs,

  • Oi Armando!
    Arrumando em 3..2..1..
    Muito obrigado pelo feedback!

  • Gustavo Henrique

    Opa Cristiano, somente uma dúvida, você usaria o Alpine em produção para rodar a aplicação, ou somente ela para ambiente de desenvolvimento ?

    abraços

  • Oi Gustavo,
    Não vejo problema em utilizar ele em produção, atualmente usamos ele em algumas imagens nossas, e por ele ser mais enxuto, facilita em muito a administração. Mas cada caso é um caso, você deve se sentir a vontade em utilizar ele, e não apenas por ser ‘cool’.

  • Caio Rodoli

    Olá Cristiano, tem alguma vantagem de usar o alpine ao inves de busybox ou vice-versa ?

  • Oi Caio!
    Na verdade uma não anula a outra, pois Alpine é baseada na Busybox, com a vantagem de ter um repositório de pacotes bem mais atualizado, sendo que para a busybox muitas coisas bem que serem instaladas na mão.