Ambiente de desenvolvimento com Docker e Git: do zero ao deploy
Por que seu código funciona local e quebra em produção? A resposta está no ambiente: Git, Docker e a diferença entre dev e produção.

Antes do Framework — Ep. 04
Você já entende redes e sabe se virar no terminal. Etapa 3: o ambiente onde o código vai rodar — em qualquer máquina.
"Mas na minha máquina funciona."
Se você já disse isso ou vai dizer em algum momento da sua carreira, esse episódio é pra você.
O problema quase nunca é o código. É o ambiente onde ele roda. E entender isso vai economizar horas de debug e muita vergonha em produção.
O problema do ambiente
Imagine dois cenários:
Cenário 1: Você desenvolve no Windows com Node 18. O servidor do cliente roda Ubuntu com Node 20. Sua aplicação usa uma lib que tem comportamento diferente entre as versões. Deploy feito, sistema quebrado. Você passa horas até descobrir que era isso.
Cenário 2: Você e mais dois devs trabalham no mesmo projeto. Um usa Mac, outro Windows, outro Linux. Cada um instalou dependências em ordens diferentes. "Na minha máquina funciona" vira piada interna, mas o projeto nunca roda igual pra todo mundo.
A solução para os dois casos é a mesma: paridade de ambiente. O ambiente de desenvolvimento precisa ser idêntico ao de produção.
Git: versionamento como hábito
Antes de falar de ambiente, uma base que precisa estar sólida: Git.
Não é só "commitar e dar push". É o registro de tudo que aconteceu no projeto.
O fluxo básico
git init # inicia o repositório
git status # mostra o que mudou
git add arquivo.ts # adiciona ao staging
git add . # adiciona tudo (use com cuidado)
git commit -m "feat: adiciona autenticação"
git push origin main # envia para o repositório remoto
Branches: trabalhe sem medo de quebrar tudo
git checkout -b feat/login # cria e entra na branch
git checkout main # volta para a main
git merge feat/login # une a branch na main
git branch -d feat/login # deleta a branch após o merge
A regra de ouro: nunca commite direto na main em projetos reais. A main é o que está em produção.
O que nunca deve ir para o Git
# .gitignore
.env
node_modules/
.DS_Store
dist/
*.log
Credenciais no Git são um dos erros mais comuns de segurança. Robôs varrem o GitHub em segundos atrás de chaves de API e senhas expostas. Crie sempre um .env.exemplo com as chaves vazias para documentar o que é necessário.
Variáveis de ambiente: o segredo que separa um curioso de um dev verdadeiro
Nunca faça isso:
const db = new Client({
host: "db.producao.com",
password: "minha-senha-secreta",
});
Faça isso:
const db = new Client({
host: process.env.DB_HOST,
password: process.env.DB_PASSWORD,
});
E crie um .env local:
DB_HOST=localhost
DB_PASSWORD=senha-local-de-dev
Em produção, essas variáveis são configuradas no servidor ou na plataforma de deploy (Vercel, Railway, etc). O código é o mesmo. O ambiente muda. Isso é paridade.
Docker: empacotando o ambiente junto com a aplicação
Docker resolve o "na minha máquina funciona" de forma definitiva. Em vez de documentar como configurar o ambiente, você escreve a configuração uma vez e ela roda igual em qualquer lugar.
O Dockerfile: a receita da sua aplicação
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
Cada linha é uma instrução. O resultado é uma imagem: um snapshot do ambiente com tudo que a aplicação precisa para rodar.
Docker Compose: orquestrando múltiplos serviços
API sozinha raramente basta. Na prática, você precisa de banco de dados, talvez cache, talvez um serviço de filas. O compose.yml define tudo junto:
services:
app:
build: .
ports:
- "3000:3000"
environment:
- DATABASE_URL=postgres://postgres:senha@db:5432/meuprojeto
depends_on:
db:
condition: service_healthy
db:
image: postgres:16-alpine
environment:
POSTGRES_DB: meuprojeto
POSTGRES_USER: postgres
POSTGRES_PASSWORD: ${DB_PASSWORD}
healthcheck:
test: ["CMD-SHELL", "pg_isready -U postgres"]
interval: 5s
retries: 5
Para subir tudo:
docker compose up # sobe em foreground (você vê os logs)
docker compose up -d # sobe em background
docker compose down # derruba tudo
docker compose logs -f # acompanha os logs em tempo real
O depends_on com healthcheck garante que o banco esteja saudável antes da API tentar se conectar. É um detalhe pequeno que evita crashes na inicialização.
Dev, staging e produção: entendendo os ambientes
A maioria dos projetos sérios tem pelo menos três ambientes:
| Ambiente | Propósito | Quem acessa |
|---|---|---|
| dev | Desenvolvimento local | Você |
| staging | Testes antes de publicar | Time e cliente |
| produção | O sistema real | Usuários finais |
Cada um tem suas próprias variáveis de ambiente, banco de dados separado e configurações diferentes. Você nunca testa em produção. Nunca.
Na prática, com Docker Compose, você pode ter um compose.dev.yml e um compose.prod.yml com configurações específicas para cada contexto.
O checklist antes de qualquer deploy
Antes de mandar código para produção, passe por isso:
-
.envestá no.gitignore - Todas as variáveis necessárias estão documentadas no
.env.exemplo - O Dockerfile está atualizado com as dependências corretas
-
docker compose upsobe sem erros do zero - A branch foi revisada e merged via PR
- O ambiente de staging foi testado
Parece burocrático no começo. Com o tempo vira instinto.
→ Próximo episódio
Você sabe versionar código e garantir paridade de ambiente. O próximo passo é aprender a trabalhar com mais de uma pessoa no mesmo repositório — sem sobrescrever o trabalho de ninguém.
Antes do Framework — Ep. 05: Git em time — branches, Pull Requests e code review na prática
Newsletter
Em breveEm breve você poderá receber novos artigos direto no seu email.