Docker resolve o problema clássico do "na minha máquina funciona". A ideia é empacotar a aplicação junto com tudo que ela precisa pra rodar — biblioteca, configuração, sistema de arquivos — num único container que roda igual no laptop do dev, no servidor de produção e na máquina do CI. O ganho é reprodutibilidade: a versão que passou no teste é exatamente a mesma que sobe.
Antes de container, a forma de isolar aplicação era máquina virtual (VirtualBox, VMware). Cada VM tinha um sistema operacional inteiro dentro — kernel, drivers, tudo. Pesado, lento pra ligar, ocupa GB.
Container compartilha o kernel do host. Cada container só tem o que a aplicação precisa: binário, biblioteca, config. Resultado:
| Máquina Virtual | Container | |
|---|---|---|
| Kernel | Próprio | Compartilha do host |
| Tamanho típico | GBs | MBs (algumas vezes KBs) |
| Tempo pra subir | Minutos | Segundos |
| Quantos cabem num servidor | Dezenas | Centenas/milhares |
| Isolamento | Forte (hardware virtualizado) | Médio (namespaces e cgroups do Linux) |
Pra produção moderna, container é o padrão. VM ainda aparece quando precisa rodar SO diferente do host (Windows num Linux, por exemplo).
Dois conceitos que confundem no início:
postgres:16, node:20-alpine).Da mesma imagem você sobe quantos containers quiser, todos idênticos. Mata o container, a imagem continua intacta — sobe outro.
Imagens vivem em registry: o público é o Docker Hub, mas tem AWS ECR, GitHub Container Registry, e registry privado interno em empresa.
O Dockerfile é um arquivo de texto que descreve passo a passo como montar uma imagem. Cada linha vira uma camada (layer) — Docker reutiliza camadas iguais entre imagens, economizando espaço e tempo de build.
# Imagem base
FROM node:20-alpine
# Diretório dentro do container onde os comandos vão rodar
WORKDIR /app
# Copia package.json e instala dependências (camada cacheada)
COPY package*.json ./
RUN npm ci --only=production
# Copia o resto do código
COPY . .
# Porta que o container expõe
EXPOSE 3000
# Comando que roda quando o container sobe
CMD ["node", "server.js"]
Para construir e rodar:
# Build da imagem (cria 'minha-app:1.0')
docker build -t minha-app:1.0 .
# Sobe o container, expondo porta 3000 do container na 8080 do host
docker run -p 8080:3000 minha-app:1.0
Quando você começa a usar Docker, são uns 10 comandos que cobrem 90% do uso:
| Comando | O que faz |
|---|---|
docker ps | Lista containers rodando |
docker ps -a | Lista todos (inclusive parados) |
docker images | Lista imagens disponíveis localmente |
docker pull nome:tag | Baixa imagem do registry |
docker run [opções] imagem | Cria e inicia um container novo |
docker exec -it nome bash | Abre um shell dentro de um container rodando |
docker logs -f nome | Mostra os logs (acompanha em tempo real) |
docker stop nome | Para o container |
docker rm nome | Remove o container parado |
docker rmi imagem | Remove a imagem |
O -d (detached) faz o container rodar em background. O --name dá um nome amigável (em vez do ID hexa).
Aplicação real raramente é um container só. Tem app + banco + cache + fila — cada um num container. O docker-compose descreve esse conjunto num único arquivo YAML.
services:
app:
build: .
ports:
- "8080:3000"
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_USER: dev
POSTGRES_PASSWORD: secret
POSTGRES_DB: minhaapp
volumes:
- db-data:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
db-data:
Comandos principais:
# Sobe tudo em background
docker compose up -d
# Para tudo
docker compose down
# Acompanha logs de todos
docker compose logs -f
# Reconstrói as imagens
docker compose build
Em desenvolvimento local, docker compose é o comando mais usado — sobe o ambiente inteiro com 1 linha.
Brilha em:
docker compose upNão é a ferramenta certa pra:
Pra orquestração em escala (centenas de containers em vários servidores), entra Kubernetes — que usa Docker (ou outro runtime de container) por baixo.