
Como o Docker mudou minha relação com 'funciona na minha máquina'
Por anos eu aceitei como normal que o ambiente do desenvolvedor fosse diferente do ambiente de produção. O Docker mudou isso — mas o mais importante foi entender o que o problema representava.
Por muito tempo eu aceitei como parte normal do trabalho que o código funcionasse diferente em ambientes diferentes.
"Funciona na minha máquina" não era piada no time. Era um diagnóstico real que levava a investigações reais. Alguém atualizava uma dependência e quebrava o build de outro. O servidor de staging tinha uma versão diferente do Python. Produção rodava numa versão de Ubuntu que ninguém mais tinha instalada.
O custo disso era constante e invisível. Cada diferença de ambiente era uma possível fonte de bug. Cada deploy era uma variável a mais que precisava ser considerada.
Quando comecei a usar Docker, a primeira coisa que mudou foi mecânica: o ambiente ficou reproduzível. O Dockerfile descrevia exatamente o que o sistema precisava para funcionar — sistema operacional, versão do runtime, dependências, configurações. Qualquer máquina que rodasse aquele Dockerfile teria o mesmo resultado.
Mas a mudança mais importante não foi técnica. Foi conceitual.
Docker me fez perceber que "funciona na minha máquina" era o sintoma de um problema de definição. A máquina do dev, o servidor de staging e produção eram ambientes diferentes tratados como se fossem o mesmo. O Docker forçou uma definição explícita: o ambiente é o container. Se funciona no container aqui, funciona no container em qualquer lugar onde aquele container rodar.
Tem um caminho de aprendizado com Docker que muita gente não percorre completo, e que faz diferença.
O primeiro nível é docker run — você baixa uma imagem, roda um container, consegue ter um banco de dados local sem instalar nada. Isso já resolve parte do problema.
O segundo nível é escrever um Dockerfile — você define seu próprio ambiente, coloca sua aplicação dentro de uma imagem. Agora você controla o que está dentro.
O terceiro nível é docker-compose — você orquestra múltiplos containers juntos. Sua aplicação, o banco de dados, o cache, tudo sobe com um comando. O ambiente completo fica descrito em código, versionado junto com o projeto.
Cada nível resolve um problema diferente. Muita gente fica no primeiro e perde os benefícios dos outros dois.
A parte que mais me surpreendeu foi o que acontece quando você define o ambiente em código.
O docker-compose.yml não é só uma conveniência operacional. Ele é documentação. Quando um dev novo entra no projeto, ele vê exatamente quais serviços o sistema depende, quais portas estão expostas, quais variáveis de ambiente são necessárias. Não existe mais "configure sua máquina local de acordo com a wiki que foi atualizada pela última vez em 2019."
Infraestrutura como código começa no Dockerfile. O conceito de descrever o ambiente de forma declarativa, versionada e reproduzível é o mesmo que vai aparecer mais tarde quando você for olhar para Terraform, Kubernetes, e qualquer ferramenta moderna de infraestrutura.
Tem um ponto onde Docker não é a resposta certa. Overhead de aprendizado em projetos simples. Complexidade adicional quando o time ainda não entende containers. Problemas de performance em alguns cenários específicos no macOS.
Mas a mentalidade que o Docker ensina — definir o ambiente explicitamente, tratar a infraestrutura como código, não aceitar "funciona aqui mas não funciona lá" como fato da vida — essa mentalidade é independente da ferramenta.
Essa semana: se você tem um projeto que ainda usa "instale na sua máquina" como setup, experimente escrever um docker-compose.yml com pelo menos um serviço de dependência (banco de dados, Redis, o que o projeto precisar). Não precisa ser perfeito — só precisa ser explícito.