“Funciona na minha máquina”: por que ainda acontece e como matar de vez

Tem vídeo desse conteúdo no canal Veja o passo a passo completo em vídeo.
Assistir no YouTube →
“Funciona na minha máquina”: por que ainda acontece e como matar de vez

“Mas funciona na minha máquina.” É a frase mais famosa da engenharia de software, e também uma das mais irritantes — porque quase sempre é dita por alguém que está genuinamente confuso. O código roda na máquina dele. Ele viu. Então por que quebra no servidor?

A frase virou piada, mas por trás dela existe um problema de engenharia bem concreto: o ambiente onde você desenvolve é diferente do ambiente onde o código roda de verdade. E essas diferenças, invisíveis no dia a dia, são exatamente onde os bugs se escondem.

De onde vem a diferença

Quando você para para listar, é assustador quantas coisas podem divergir entre a sua máquina e a produção:

  • Versões. Você roda Node 20; o servidor, Node 18. Uma função que existe num não existe no outro.
  • Dependências do sistema. Aquela biblioteca de imagem que você instalou há meses e esqueceu. Ela está na sua máquina; no servidor, não.
  • Variáveis de ambiente. Uma configuração que existe no seu .env local e que ninguém documentou.
  • Sistema operacional. Você no macOS, o servidor no Linux. Detalhes como sensibilidade a maiúsculas em nomes de arquivo mudam o resultado.
  • Dados. Seu banco local tem três registros bonitinhos; produção tem milhões, com casos estranhos que você nunca imaginou.

Cada uma dessas diferenças é uma aposta silenciosa de que “aqui é igual a lá”. E, quanto mais apostas, maior a chance de uma delas te trair.

A ideia central: paridade de ambientes

A solução não é mágica, é um princípio: aproximar o máximo possível o ambiente de desenvolvimento do de produção. Quanto menor a distância entre “aqui” e “lá”, menos lugares o bug tem para se esconder. Você nunca chega à igualdade perfeita, mas cada diferença que você elimina é uma classe inteira de problema que deixa de existir.

Foi por causa dessa dor que os containers ganharam o mundo. Não porque são modernos — porque resolvem exatamente isto.

Como os containers fecham a lacuna

Um container empacota o seu código junto com tudo que ele precisa para rodar: a versão certa da linguagem, as bibliotecas do sistema, as configurações. Esse pacote é o mesmo na sua máquina, na do colega e no servidor. Se roda num lugar, roda em todos — porque, do ponto de vista da aplicação, é literalmente o mesmo ambiente.

# A "receita" do ambiente, versionada junto do código:
FROM node:18-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
CMD ["node", "server.js"]

O detalhe poderoso está nesse arquivo: o ambiente virou código. Ele mora no repositório, passa por revisão, é versionado. “Qual versão do Node a gente usa?” deixa de ser conhecimento tribal na cabeça de alguém e passa a ser uma linha que todo mundo enxerga.

Container não é sobre estar na moda. É sobre transformar “na minha máquina” em “na nossa máquina” — a mesma para todo mundo.

Os serviços de apoio também precisam bater

Igualar a linguagem e as bibliotecas é metade do caminho. A outra metade são as peças ao redor: o banco, o cache, a fila. De nada adianta o seu código rodar idêntico se você desenvolve com PostgreSQL 16 e produção está no 13 — as mesmas diferenças de versão voltam, só que na infraestrutura.

É aqui que uma ferramenta como o docker compose entra: você descreve, num arquivo só, o banco, o cache e o que mais a aplicação precisa, todos nas versões de produção. Um comando sobe o ambiente inteiro, igual para todo mundo do time.

services:
  app:
    build: .
  db:
    image: postgres:13   # a MESMA versão de produção
  cache:
    image: redis:7

O bônus vem de brinde: se o ambiente está descrito como código, a esteira de CI usa exatamente o mesmo. Os testes rodam contra as versões que vão para produção, e aquele bug que “só aparece lá” perde o último esconderijo. Reproduzir deixa de depender da máquina de quem está debugando.

Container não conserta tudo

Sendo justo: containerizar não é uma varinha mágica. Ele iguala o ambiente de execução, mas não iguala os dados. Se o bug só aparece com o volume e a bagunça de produção, rodar o mesmo container localmente com três registros ainda não vai revelá-lo. Para esses casos, vale testar com uma cópia realista da base (devidamente anonimizada) e prestar atenção aos casos-limite que só a escala mostra.

Também não substitui disciplina com configuração: variáveis de ambiente ainda precisam ser documentadas e gerenciadas com cuidado. O container garante que o lugar é igual, não que você lembrou de setar tudo.

O que fica

“Funciona na minha máquina” não é uma desculpa preguiçosa — é o sintoma de ambientes que divergiram. A cura é reduzir essa distância de forma deliberada: fixar versões, versionar o ambiente junto do código, testar com dados que se pareçam com a realidade. Faça isso e a frase mais irritante da engenharia simplesmente para de fazer sentido, porque a sua máquina e a de produção passam a contar a mesma história.

Leia também

Prefere ver em vídeo?

Esse artigo virou um vídeo completo no canal, com diagramas animados e demo ao vivo.

Assistir no YouTube →