Dockerfile para Node.js: cache e contexto com .dockerignore
Aprenda a criar uma imagem Docker para Node.js, organizar as camadas para reaproveitar o cache e excluir arquivos desnecessários do contexto com .dockerignore.
Criar uma imagem Docker para um projeto Node.js envolve mais do que reunir comandos em um arquivo. A ordem das instruções influencia o reaproveitamento do cache, enquanto o contexto de build determina quais arquivos são enviados ao mecanismo de construção e ficam disponíveis para cópia.
Monte a imagem em etapas
O exemplo parte da imagem oficial node:24-alpine, escolhe /app como diretório de trabalho e instala as dependências de produção antes de copiar o restante do código. Essa sequência permite que alterações nos arquivos da aplicação não exijam reinstalar dependências a cada build.
Para reproduzir o teste, o projeto Node.js precisa fornecer um servidor HTTP que atenda na porta 3000 e um script npm start configurado. O Dockerfile abaixo mostra a sequência de construção, mas não inclui os arquivos da aplicação nem a configuração desse script.
FROM node:24-alpine WORKDIR /app COPY package*.json ./ RUN npm install --omit=dev COPY . . EXPOSE 3000 CMD ["npm", "start"]
FROM, WORKDIR, COPY e RUN participam da construção da imagem. Já EXPOSE e CMD definem configurações relacionadas à execução: eles não aparecem como etapas de build. Distinguir essas instruções ajuda a interpretar a saída do Docker sem esperar que cada linha execute uma ação durante a construção.
Entenda o contexto de build
O comando docker build -t hello-node . cria a imagem chamada hello-node. A opção -t atribui esse nome, e o ponto final indica que a pasta atual será o contexto. O Docker envia esse conteúdo para o mecanismo de build, e as instruções COPY só podem acessar arquivos que estejam dentro dele.
Na primeira construção do exemplo, a pasta contém apenas três arquivos pequenos, e a saída informa que foram transferidos 759B de contexto. Esse número ajuda a observar o volume enviado antes da conclusão do build. Manter o contexto enxuto reduz transferências desnecessárias e torna mais claro quais arquivos podem ser usados na imagem.
Execute e teste o servidor
Depois de construir a imagem, o servidor pode ser iniciado em segundo plano com uma publicação da porta 3000 do contêiner na porta correspondente do computador. O comando abaixo nomeia o contêiner como hello e usa a imagem criada no passo anterior.
docker run -d -p 3000:3000 --name hello hello-node
Uma solicitação local permite conferir a resposta do servidor: curl -s http://localhost:3000 retorna Hello from Docker! no projeto demonstrado pela fonte. Como o Node.js está dentro da imagem, não é necessário instalá-lo no computador para executar esse exemplo; a resposta confirma que a aplicação atende pela porta publicada.
Organize as camadas para reaproveitar o cache
Se apenas o texto de resposta em server.js mudar, o novo build pode reaproveitar as etapas anteriores. No exemplo, WORKDIR, a cópia dos arquivos de dependências e a instalação aparecem como etapas em cache; somente COPY . . precisa rodar novamente para levar a alteração do código à imagem.
Esse comportamento depende da ordem das instruções e dos arquivos envolvidos em cada camada. Como os arquivos de dependências permanecem iguais, a instalação não precisa ser repetida quando muda somente o código. Se a cópia de todo o projeto viesse antes de RUN npm install, uma alteração na aplicação também invalidaria o cache da instalação.
Reduza o contexto com .dockerignore
Pastas locais como node_modules, .git e arquivos de log podem aumentar o contexto sem serem necessários para a imagem. No caso apresentado, um diretório node_modules de 30 MB elevou a transferência para 30.01MB; com COPY . ., esse conteúdo também seria copiado para a imagem.
Para excluir esses itens, crie um arquivo .dockerignore na raiz do contexto com as entradas do exemplo. A lista também ignora .env, evitando que esse arquivo local seja incluído junto ao restante do projeto.
node_modules .git .env *.log
Após aplicar o arquivo, a transferência de contexto no exemplo cai para 159B. Essas entradas reduzem o envio e evitam que mudanças nos arquivos listados invalidem o cache da cópia. Como a lista não especifica arquivos de chaves privadas, inclua entradas correspondentes a esses arquivos no .dockerignore caso o projeto os tenha.
Excluir node_modules também evita levar para o contêiner Linux módulos nativos compilados para outro sistema operacional. Em conjunto, a ordem que copia primeiro os arquivos de dependências e o uso de .dockerignore tornam o build mais enxuto e ajudam a preservar etapas em cache quando só o código da aplicação muda.
Informações deste conteúdo
Tecnologias: Docker, Dockerfile, HTTP, JSON, NPM, Node.js
Carreiras: Desenvolvedor Node.js, Desenvolvedor de Aplicações Web, Especialista em Docker
Idiomas: Português
Tags: arquivos, docker, git, npm