Formação AWS

← Todos os artigos

Dockerfile: estender imagem, cache de build e Nginx no Docker

ContainersPor Henrylle Maia · 15 out 2026 · 8 min de leitura

O FROM do Dockerfile aceita qualquer imagem, inclusive uma que você mesmo construiu, e a ordem das linhas decide quanto do docker build vem do cache. Aqui eu monto uma imagem em cima de outra, rodo um container em segundo plano com -d e publico uma página HTML com a imagem oficial do Nginx e o -p.

Estender uma imagem: do Ubuntu para a sua

Estender é pegar uma imagem pronta e incrementar. Partindo do Ubuntu 20.04 eu adiciono o Git, dou um nome ao resultado, ubuntu-custom, e passo a lançar containers dessa imagem, que já vem com coisas instaladas. Depois posso estender de novo, agora a partir do ubuntu-custom e não mais do Ubuntu.

O RUN executa os comandos na hora de construir a imagem, e o -y evita que o build fique parado esperando uma resposta:

dockerfile
FROM ubuntu:20.04
RUN apt-get update -y
RUN apt-get install git -y

Construa e entre no container:

bash
docker build -t ubuntu-custom .
docker run -ti ubuntu-custom

Dentro do container, git --version responde: o Git já vem na imagem. O curl ainda não, e esse é o gancho para o cache.

Cache: por que a ordem das linhas importa

Acrescentei RUN apt-get install curl -y como quarta linha e construí de novo. As etapas 2 e 3 já tinham rodado e apareceram com Using cache; só a 4, a nova, executou do zero. Por isso o build ficou rápido.

Saída do docker build: as etapas 2/4 (apt-get update) e 3/4 (instalação do git) com "Using cache"
Saída do docker build: as etapas 2/4 (apt-get update) e 3/4 (instalação do git) com "Using cache"

A regra vale para a linha em que você mexe: da linha alterada em diante, o cache recomeça. Se eu tivesse mexido na linha 3, tudo dali para baixo rodaria de novo. Por isso o Dockerfile vai do mais genérico para o mais específico, ou do que muda menos para o que muda mais. O que você altera com frequência fica embaixo.

1Criar uma imagem a partir da sua

Agora não quero mais partir do Ubuntu 20.04. Crio um segundo arquivo, Dockerfile-custom, e digo que parto da imagem que acabei de construir. Para ter algo útil, clono o projeto da Bia, uma aplicação em Node e React (aqui o Git que eu coloquei na primeira imagem faz o serviço):

dockerfile
FROM ubuntu-custom
RUN git clone https://github.com/henrylle/bia.git

Como o arquivo não se chama Dockerfile, o -f diz qual usar. O contexto, o ponto no fim, continua obrigatório: na primeira tentativa eu esqueci e o Docker reclamou que o build exige um argumento.

bash
docker build -t ubuntu-custom-2 -f Dockerfile-custom .
docker run -ti ubuntu-custom-2

O ls mostra a pasta bia na raiz do container, e dentro dela estão todos os arquivos do projeto. Todo container lançado de ubuntu-custom-2 já nasce com o Git instalado e o projeto baixado.

Terminal dentro do container ubuntu-custom-2: o ls da raiz lista a pasta bia, e o ls dentro dela lista os arquivos do projeto
Terminal dentro do container ubuntu-custom-2: o ls da raiz lista a pasta bia, e o ls dentro dela lista os arquivos do projeto

2Rodar em segundo plano com -d

Até aqui eu uso -ti, que deixa o terminal ligado ao container. Ele só vive enquanto eu estou dentro. Para rodar em segundo plano existe o -d (detached), que não prende o terminal.

Só que, rodando docker run -d ubuntu-custom-2, o container morre na sequência, e o docker ps não lista nada. Um container só continua rodando se algum processo o segura. No modo -ti quem segura é o terminal; aqui, terminou a execução, ele acaba.

Para o teste, usei um artifício. O tail -f fica imprimindo o conteúdo de um arquivo, e apontando para /dev/null ele nunca retorna nada e fica preso no processo. Coloco como ENTRYPOINT no Dockerfile-custom, o comando que o container executa sempre que é lançado:

dockerfile
FROM ubuntu-custom
RUN git clone https://github.com/henrylle/bia.git
ENTRYPOINT ["tail", "-f", "/dev/null"]

Construí de novo (as etapas anteriores vieram do cache, então foi rápido) e subi com -d:

bash
docker build -t ubuntu-custom-2 -f Dockerfile-custom .
docker run -d ubuntu-custom-2
docker ps
Saída do build com a etapa 3/3 ENTRYPOINT tail -f /dev/null, depois o ID do container devolvido pelo docker run -d
Saída do build com a etapa 3/3 ENTRYPOINT tail -f /dev/null, depois o ID do container devolvido pelo docker run -d

O docker run -d devolve o ID do container, e agora o docker ps o lista rodando. Para parar, passe os primeiros caracteres do ID:

bash
docker stop <primeiros-caracteres-do-id>

Esse truque é só para o exemplo. Numa imagem de verdade o ENTRYPOINT aponta para o processo que o container deve executar, como uma aplicação web ou um trabalho que roda e termina. Quando o processo acaba, o container acaba, e é isso que se quer: o container tem um conceito de finitude, por isso é tão usado em microsserviços.

Uma imagem construída em cima da outra, até virar um containerubuntu:20.04imagem do Docker Hububuntu-customcom o git instaladoubuntu-custom-2com o projeto clonadoContainerdocker run -d
Uma imagem construída em cima da outra, até virar um container

3Usar uma imagem pronta do Docker Hub, o Nginx

Em vez de partir de um sistema operacional, dá para partir de uma imagem que já faz o que você quer. Quero servir uma página HTML estática, então busco nginx no Docker Hub. O selo de imagem oficial e o número de downloads, mais de um bilhão, indicam que é a oficial. Veja a página em hub.docker.com/_/nginx: ela traz o exemplo de Dockerfile e o comando de build.

Crio a pasta meu_html com um hello.htm ("Oi Mundo... Saí da máquina local e fui para o container") e um Dockerfile-nginx, que copia a pasta para o diretório que o Nginx publica:

dockerfile
FROM nginx
COPY meu_html /usr/share/nginx/html
bash
docker build -t meu-nginx -f Dockerfile-nginx .

Na primeira tentativa esqueci o -f e o Docker pegou o Dockerfile padrão. Com o -f, ele baixa o Nginx, copia o conteúdo da pasta e a imagem fica pronta.

4Publicar a porta com -p

O container roda na minha máquina, mas para abrir a página como localhost preciso compartilhar uma porta dele. O Nginx responde na porta 80 dentro do container. Do lado da minha máquina eu escolho qualquer porta livre: a documentação sugere a 8080 porque a 80 pode estar ocupada, e eu usei a 8081. O -p mapeia as duas, <porta-da-máquina>:<porta-do-container>:

bash
docker run --name meu-container-nginx -d -p 8081:80 meu-nginx

O --name dá um nome ao container; sem ele o Docker gera um nome aleatório. O docker ps confirma que está rodando e mostra o mapeamento. Abri localhost:8081/hello.htm e a página apareceu.

5Atualizar a página exige uma imagem nova

Mudei o texto do HTML, acrescentando "(Sou a v2)". Rodar o container de novo não muda nada, porque o HTML foi copiado para dentro da imagem. O caminho é parar o container, construir a imagem outra vez e subir de novo, agora na porta 8082:

bash
docker stop <id>
docker build -t meu-nginx -f Dockerfile-nginx .
docker run -d -p 8082:80 meu-nginx

A 8081 saiu do ar e a 8082 mostrou a página com a v2. Um container roda de uma imagem: para o container mudar, a imagem muda primeiro. O mesmo raciocínio aparece em Docker na EC2, com o Apache, e os comandos que você usa no dia a dia estão em Comandos Docker essenciais.

Checklist

  • Parta de uma imagem sua com FROM <nome-da-imagem> e construa a próxima em cima dela.
  • Use -f <arquivo> quando o Dockerfile não se chama Dockerfile, e não esqueça o contexto (o ponto) no fim do docker build.
  • Ponha no Dockerfile o que muda menos nas primeiras linhas: da linha alterada em diante o cache recomeça.
  • Com docker run -d, garanta que um processo segura o container, senão ele termina na hora.
  • Pare um container com docker stop e os primeiros caracteres do ID.
  • Para servir uma página, parta da imagem oficial do Nginx e copie o HTML para /usr/share/nginx/html.
  • Publique a porta com -p <porta-da-máquina>:80 e confira no docker ps.
  • Mudou o conteúdo? Pare o container, construa a imagem de novo e suba outro.

Estender imagens, ordenar bem o Dockerfile e publicar uma porta são a base para o passo seguinte: pegar uma aplicação local, containerizar e levar para a nuvem da AWS.

O que os alunos dizem

  • “Eu queria voltar para a área técnica, mas aprender AWS sozinho só me deixava frustrado.”

    William Santos, Tech Lead

    Ver depoimento
  • “Eu sempre fugi da AWS. Achava complicado, distante da minha rotina de dev. Mas só a primeira aula do Bootcamp já mudou tudo: usei o conteúdo para resolver um problema real de um cliente e fui contratado por causa disso.”

    André Scherrer, Engenheiro de Software

    Ver depoimento
  • “Só quando coloquei a mão na massa com a Formação AWS é que avancei de verdade. Essa prática me levou ao próximo nível”

    Caio, Desenvolvedor (Dev)

    Ver depoimento

Formação AWS

Aprenda AWS e IA na prática, com projeto real e acompanhamento. Converse com o time sobre a Formação AWS.

Agende uma conversa

Prefere assistir?

A aula completa (29 min) está no canal Domine AWS. O vídeo toca aqui mesmo.

Leia também

Compartilhe este post