Buildando a sua aplicação em containers intermediários com Docker multi-stage build

Bruno Alves
Huia
Published in
2 min readDec 28, 2018

Devs e DevOps utilizando Docker mais cedo ou mais tarde precisarão fazer deploy das suas aplicações. E o container deve (ou deveria) levar somente o necessário para a aplicação executar e não um monte de aplicativos/módulos intermediários que são utilizados apenas para build.

Ninguém quer levar aquele diretório node_modules (gigante) desnecessário em uma aplicação html/js estática por exemplo.

Antes de conhecer a feature de multi-stage do Docker minha equipe e eu criávamos ambientes específicos para build das aplicações. Como trabalhamos com diversas stacks com linguagens, frameworks e versões diferentes era muito ̶i̶n̶s̶a̶n̶o̶ complexo dar manutenção nisso tudo.

Indo ao que interessa

Tudo acontece dentro do seu próprio arquivo de Dockerfile, basicamente você referencia e builda containers intermediários dando nomes antes do seu conteiner de aplicação, olha só:

FROM node as build #container intermediario com nome de build
RUN mkdir -p /usr/src/app
COPY . /usr/src/app
WORKDIR /usr/src/app
RUN npm install
RUN npm run build

FROM nginx #container final que faz uso dos arquivos gerados em build
COPY — from=build /usr/src/app/dist /usr/share/nginx/html

Minha aplicação estática em html/js precisa instalar módulos via NPM para compilar o SaSS, minificar arquivos e comprimir imagens. Nesse caso estamos usando uma imagem do node (FROM node as build) e executando o npm install (que vai baixar todas as dependências do packages.json no node_modules) e o npm run build que vai de fato executar as tarefas de deploy.

O container intermediário levou o nome de build, poderia ser qualquer um, e poderiam ser vários containers intermediários resolvendo cada etapa do seu build.

Após executado o npm run build minha aplicação cria um diretório dist com o html e todos os assets necessários, a partir de agora a node_modules não é mais necessária, então no container final eu copio do container intermediário apenas o que preciso para publicar a aplicação (no meu caso, o diretório dist) COPY — from=build /usr/src/app/dist /usr/share/nginx/html

Como é possível criar vários containers intermediários e utilizar todos você só precisa referenciar no COPY ou no ADD o nome que você deu, ex: COPY — from=build2 ou COPY — from=build-qualquer-coisa.

Essa feature está disponível a partir da versão 17 do docker. Espero que ajude quem ainda não conhecia e que salve muito tempo assim como aconteceu comigo. :)

--

--