Containers e Docker
O que é um container, como ele difere de uma máquina virtual e como se constrói uma imagem pequena, rápida e segura.
O problema: funciona na minha máquina
A aplicação roda no computador do desenvolvedor com Node 24, uma biblioteca de imagens instalada no sistema e uma variável de ambiente que ninguém lembra de ter configurado. No servidor, o Node é outra versão, a biblioteca falta e a variável não existe. O deploy falha, ou pior, funciona com um comportamento diferente.
Antes dos containers, as soluções eram documentar a instalação passo a passo, manter servidores configurados à mão ou criar uma máquina virtual inteira para cada aplicação. As três são lentas, frágeis ou caras.
Um container resolve empacotando a aplicação junto com o ambiente de que ela precisa: o sistema de arquivos com as bibliotecas, o interpretador, as dependências e a configuração de execução. O pacote roda igual em qualquer máquina que tenha um mecanismo de containers.
Container não é máquina virtual
| Máquina virtual | Container | |
|---|---|---|
| O que isola | Um computador inteiro, com o próprio sistema operacional | Um processo, com sistema de arquivos e rede próprios |
| Núcleo do sistema (kernel) | Um para cada máquina virtual | Compartilhado com a máquina hospedeira |
| Tamanho típico | Gigabytes | Dezenas a centenas de megabytes |
| Tempo para iniciar | Dezenas de segundos a minutos | Frações de segundo a poucos segundos |
| Isolamento | Forte: um núcleo por máquina | Bom, porém menor: todos dividem o mesmo núcleo |
Um container é, por dentro, um processo comum da máquina hospedeira, com recursos do núcleo do Linux que o fazem enxergar só o próprio mundo:
- namespaces dão ao processo a sua própria visão de processos, rede, sistema de arquivos e usuários;
- cgroups limitam quanta CPU e memória ele pode usar.
Por isso um container inicia tão rápido: não há sistema operacional para ligar, só um processo para iniciar. E por isso o isolamento é menor que o de uma máquina virtual: uma falha no núcleo afeta todos os containers da máquina.
Imagem e container
Dois termos que se confundem:
- Imagem: o pacote congelado, que não muda. Contém o sistema de arquivos e a instrução de qual processo iniciar. É o que se constrói, versiona e publica.
- Container: uma imagem em execução. Da mesma imagem saem quantos containers forem necessários, todos iguais.
A analogia mais próxima é a de uma classe e seus objetos, ou de um instalador e o programa instalado.
docker build -t loja/api:1.4.2 . # constrói a imagem a partir do Dockerfile
docker run -p 3000:3000 loja/api:1.4.2 # inicia um container a partir delaO Dockerfile e as camadas
A imagem é descrita num Dockerfile, uma receita com uma instrução por linha:
# Parte de uma imagem com Node já instalado
FROM node:24-alpine
WORKDIR /app
# Instala as dependências
COPY package.json package-lock.json ./
RUN npm ci --omit=dev
# Copia o código
COPY . .
# O processo que o container inicia
CMD ["node", "server.js"]Cada instrução gera uma camada, e a imagem é a pilha dessas camadas. As camadas são guardadas em cache: se uma instrução e tudo o que vem antes dela não mudaram, a reconstrução reaproveita a camada pronta.
Essa regra tem uma consequência prática enorme. O exemplo acima copia primeiro só os arquivos de dependências e instala, e só depois copia o código. Uma mudança no código invalida apenas as últimas camadas, e as dependências vêm do cache.
Medimos a diferença com uma aplicação Node pequena. Depois de mudar uma linha de código, a reconstrução levou 5,4 segundos com um Dockerfile que copia tudo antes de instalar, e 0,4 segundo com as dependências numa camada separada. Em projetos reais, com centenas de dependências, a diferença passa de minutos.
Por que o tamanho e o usuário importam
No mesmo teste, a imagem montada do jeito mais simples (imagem base completa, dependências de desenvolvimento incluídas) ficou com 1,73 GB. A versão com uma imagem base enxuta e só as dependências de produção ficou com 236 MB. Uma aplicação Go compilada como binário estático, sobre uma imagem mínima, ficou com 14 MB.
| O tamanho afeta | Por quê |
|---|---|
| Tempo de deploy | Cada máquina que vai rodar o container baixa a imagem |
| Escala automática | Uma cópia nova só começa depois que a imagem chega |
| Segurança | Cada pacote a mais é uma possível vulnerabilidade, e um shell dentro da imagem ajuda quem invadir |
| Custo | Armazenamento no registro e tráfego de rede |
E, por padrão, o processo dentro do container roda como root. Se alguém explorar uma falha da aplicação, ganha o máximo de poder dentro do container, e fica mais perto de escapar para a máquina hospedeira. A versão simples do teste rodava como root; a cuidadosa, como um usuário sem privilégios.
Por que isso importa quando a IA escreve o código
Pedir "crie um Dockerfile para este projeto" gera um arquivo que funciona. Ele quase sempre tem estes problemas:
COPY . .antes da instalação das dependências, refazendo tudo a cada mudança de código.- A imagem base completa, com compiladores e ferramentas que a produção não usa.
- Dependências de desenvolvimento e arquivos de teste dentro da imagem final.
- Nenhum
.dockerignore, levandonode_modules,.gite até arquivos.envcom segredos para dentro da imagem. - O processo rodando como root.
CMD npm startna forma de texto, que impede o processo de receber o sinal de encerramento.
O próximo nível compara as escolhas de imagem base, de construção e de execução.
Prompts para aprofundar
Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.
Containers em cinco minutos
Explique em no máximo cinco minutos de leitura o que é um container e o que o Docker faz, para alguém que programa mas sempre instalou as aplicações direto no servidor. Cubra só o essencial: o problema de "funciona na minha máquina", a diferença entre container e máquina virtual, a diferença entre imagem e container, e o que é um Dockerfile. Use uma analogia simples. No final, me faça três perguntas curtas para eu verificar se entendi, e corrija as minhas respostas.
O que um container é por dentro
Quero entender o que um container é de verdade, por dentro do sistema operacional. Aja como um mentor de infraestrutura. Pergunte primeiro qual é a minha experiência com Linux. Conduza assim, uma etapa por vez: 1. Mostre que um container é um processo comum da máquina hospedeira, com um comando que eu possa rodar para ver isso. 2. Explique os namespaces: o que cada tipo isola (processos, rede, sistema de arquivos, usuários). 3. Explique os cgroups e como eles limitam CPU e memória. 4. Explique o sistema de arquivos em camadas de uma imagem. 5. Compare com uma máquina virtual: o que é compartilhado, o que é isolado e as consequências para segurança. Faça uma pergunta de verificação em cada etapa e espere a minha resposta antes de continuar.
Camadas e cache na construção
Quero entender como as camadas de uma imagem Docker e o cache de construção funcionam. Explique: 1. Como cada instrução do Dockerfile gera uma camada. 2. A regra que decide quando uma camada vem do cache e quando é reconstruída. 3. Por que copiar os arquivos de dependências e instalar antes de copiar o código faz tanta diferença. 4. O papel do .dockerignore no cache e no conteúdo da imagem. 5. Por que apagar um arquivo numa camada posterior não o remove da imagem, e o que isso significa para segredos. Depois me mostre quatro Dockerfiles, um por vez, e pergunte o que acontece com o cache quando eu mudo uma linha de código em cada um. Corrija as minhas respostas.
O processo principal e os sinais
Quero entender por que a forma de escrever o CMD no Dockerfile afeta o encerramento do container. Explique: 1. O que é o PID 1 dentro de um container e por que ele é especial. 2. A diferença entre a forma de texto e a forma de lista no CMD e no ENTRYPOINT, e qual processo vira o PID 1 em cada uma. 3. O que acontece quando o docker stop envia o SIGTERM para um shell que não o repassa. 4. Como escrever um script de entrada que não quebre isso, usando exec. 5. Quando um init mínimo, como o tini, é necessário. Depois me mostre cinco variações de CMD e ENTRYPOINT e pergunte quanto tempo o docker stop vai levar em cada uma. Corrija as minhas respostas.