
Docker para desenvolvedores: do zero ao primeiro deploy em 2026
Conteúdo educativo. Exemplos testados em Docker Engine 27 e Docker Desktop 4.35 (out/2025). Comandos válidos em Linux, macOS e Windows (WSL2). Referências oficiais no fim.
Docker virou requisito de fato em vaga back-end e full-stack desde ~2018, mas continua sendo o tópico que mais trava iniciante. O motivo é simples: a maioria dos tutoriais salta da motivação direto para Kubernetes. Aqui vamos do conceito (o que diabos é um container) até o seu primeiro deploy reproduzível, passando só pelo que realmente importa.
O que é um container, sem mística
Um container é um processo do sistema operacional isolado em três coisas: sistema de arquivos próprio, rede própria e visão própria de outros processos. Não é uma máquina virtual — não tem kernel próprio, não roda um SO inteiro. É o seu Linux compartilhando o kernel do host, usando recursos do kernel (namespaces e cgroups) para fingir que está sozinho.
| Aspecto | VM tradicional | Container Docker |
|---|---|---|
| Kernel | Próprio (Guest OS) | Compartilha com host |
| Boot time | 30s – 2 min | < 1s |
| Tamanho típico | 1 – 20 GB | 10 MB – 500 MB |
| Isolamento | Forte (hypervisor) | Médio (namespaces) |
| Densidade no host | Dezenas | Centenas / milhares |
Instalando
Em Linux, instale o Docker Engine oficial (apt/dnf) — evite o pacote da distro, costuma ser velho. Em macOS e Windows, use o Docker Desktop (gratuito para uso pessoal e empresas com menos de 250 funcionários ou US$ 10 mi de receita; pago acima disso). Em Windows, ative WSL2 antes.
# verificar instalação
docker --version
docker run hello-world
# rodar um nginx temporário
docker run --rm -p 8080:80 nginx:alpine
# acesse http://localhost:8080 e Ctrl+C para pararImagem x container x volume
- Imagem: receita imutável, em camadas. Análogo a uma classe.
- Container: instância em execução de uma imagem. Análogo a um objeto.
- Volume: armazenamento persistente fora do container. Container morre, volume fica.
- Rede: subnets virtuais que conectam containers entre si por nome.
Seu primeiro Dockerfile
Dockerfile é um script declarativo que constrói uma imagem. Cada instrução vira uma camada cacheada. A ordem importa: ponha o que muda menos no topo, o que muda mais no fim.
# Node.js 22 LTS slim (~180 MB) — evite "node:22" puro (~1 GB)
FROM node:22-slim
# define diretório de trabalho dentro do container
WORKDIR /app
# copia só os manifestos primeiro — aproveita cache se package.json não mudou
COPY package.json package-lock.json ./
RUN npm ci --only=production
# agora copia o código (muda mais frequentemente)
COPY . .
# documenta a porta; não publica sozinho
EXPOSE 3000
# usuário não-root por padrão é boa prática
USER node
CMD ["node", "server.js"]# build (o ponto no fim é o contexto)
docker build -t minha-api:1.0 .
# rodar mapeando porta
docker run -d --name api -p 3000:3000 minha-api:1.0
# ver logs
docker logs -f api
# parar e limpar
docker stop api && docker rm apiMulti-stage build: imagens 90% menores
Apps com etapa de build (TypeScript, Vite, Java, Go) não precisam carregar o compilador na imagem final. Multi-stage separa “estágio que compila” de “estágio que roda”.
# Estágio 1: build
FROM node:22-slim AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Estágio 2: runtime — só o necessário
FROM node:22-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --only=production && npm cache clean --force
COPY --from=builder /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]Resultado típico: imagem cai de ~1.2 GB para ~180 MB. Menos superfície de ataque, deploy mais rápido, cache de registry mais barato.
docker compose: orquestrando múltiplos serviços
Quase nenhuma aplicação real é um único container. Você tem API + banco + cache + worker. O docker compose declara tudo em um YAML e sobe junto.
# docker-compose.yml
services:
api:
build: .
ports:
- "3000:3000"
environment:
DATABASE_URL: postgres://app:secret@db:5432/app
REDIS_URL: redis://cache:6379
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: app
volumes:
- db-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app"]
interval: 5s
retries: 5
cache:
image: redis:7-alpine
volumes:
db-data:docker compose up -d # sobe tudo em background
docker compose logs -f api # acompanha logs
docker compose down # para tudo (mantém volumes)
docker compose down -v # para tudo e apaga volumesOs 6 erros que travam todo iniciante
1. Esquecer o .dockerignore
Sem .dockerignore o COPY . . manda node_modules, .git, dist/, .env para dentro da imagem. Build fica lento, imagem incha, segredos vazam. Sempre crie:
node_modules
.git
.env
.env.*
dist
build
*.log
coverage2. Commitar segredos em ENV
ENV no Dockerfile vira parte da imagem — qualquer um que baixe a imagem do registry lê o valor. Use --env-file na hora do run, secrets do docker compose, ou um gerenciador (Doppler, AWS Secrets Manager).
3. Rodar como root
Por padrão o processo roda como root dentro do container, e em volumes montados isso vira arquivos com dono errado no host. Imagens oficiais bem feitas (node, python, nginx) já criam um usuário; use USER no Dockerfile.
4. Não usar HEALTHCHECK
Sem healthcheck, o orquestrador (compose, swarm, k8s) considera o container “vivo” no momento em que o processo subiu — mesmo que esteja em loop de erro. Adicione HEALTHCHECK no Dockerfile ou healthcheck no compose para evitar tráfego em container quebrado.
5. Reconstruir do zero a cada deploy
Se package.json não mudou, npm ci não precisa rodar. Ordene as instruções para aproveitar cache: dependências primeiro, código depois. Em CI, use --cache-from apontando para a imagem anterior.
6. Usar tag latest em produção
latest é um ponteiro mutável. Hoje aponta para 1.4.2, amanhã para 1.5.0 com breaking change. Use versão fixa (node:22.11.0-slim) e bumpe deliberadamente.
E quando aprender Kubernetes?
Não antes de ter um docker compose rodando em produção e doer. Kubernetes resolve problema de escala (centenas de containers, múltiplos hosts, rollout sem downtime, auto-healing). Para uma API + banco em uma VPS, é overkill: aumenta complexidade, custo e tempo de manutenção. Comece com compose ou plataformas tipo Fly.io, Railway, Render — vá para k8s quando o problema aparecer de verdade.
Perguntas frequentes
+Docker funciona bem em Windows e macOS?
Sim, via Docker Desktop. Internamente roda uma micro-VM Linux (WSL2 no Windows, virtualização nativa no macOS). Performance de IO em volumes montados do host é pior que em Linux puro — para projetos grandes, vale usar bind mounts seletivos ou desenvolver dentro do container (devcontainers do VS Code).
+Qual a diferença entre docker-compose e docker compose?
docker-compose (com hífen) é a versão Python original (v1), descontinuada em 2023. docker compose (sem hífen) é o plugin oficial em Go embutido no Docker CLI. A sintaxe do YAML é praticamente idêntica.
+Posso usar Docker para front-end?
Pode, mas raramente compensa em desenvolvimento. Para SPAs, hot reload via volume montado tende a ser lento. Faz sentido empacotar para build/CI ou quando o projeto inclui back-end junto. Em produção, servir build estático de uma imagem nginx:alpine é comum e eficiente.
+Onde hospedar imagens Docker de graça?
Docker Hub (limitado a 1 repositório privado no plano free), GitHub Container Registry (gratuito para repos públicos, gratuito até 500 MB para privados em conta free), GitLab Registry. Para produção séria, use o registry do seu provedor cloud (ECR, GCR, ACR) — latência e custos de transferência menores.
+Container guarda dados quando reiniciado?
O filesystem dentro do container sobrevive a restart, mas não a remoção. Para dados que precisam persistir (banco, uploads), use volumes nomeados ou bind mounts — nunca confie no filesystem padrão do container.
Fontes consultadas
- Docker — Get Started (documentação oficial)
- Docker — Dockerfile reference
- Docker Compose specification
- Docker — Multi-stage builds
- OWASP Docker Security Cheat Sheet
Revisão editorial: publicado em . Última revisão em . Conteúdo educativo, sem patrocínio das ferramentas citadas.
Leia também

Como Começar na Programação do Zero em 2026: Guia Definitivo
Roteiro completo para quem quer entrar na programação em 2026: escolha de linguagem, setup de ambiente, lógica de programação, primeiros projetos, comunidades e como evitar armadilhas comuns de iniciantes.

HTML, CSS e JavaScript: O Trio Essencial da Web Moderna
Domine os três pilares do desenvolvimento web: HTML semântico para estrutura, CSS moderno para estilo e layout responsivo, e JavaScript para interatividade, manipulação do DOM e consumo de APIs.

Git e GitHub Básico: Controle de Versão para Quem Coda
Guia prático de Git e GitHub para iniciantes: instalação, commits, branches, merge, rebase, pull requests, resolução de conflitos e fluxos de trabalho profissionais em equipe.