O que é Docker e por que ele acabou com o ‘na minha máquina funciona’

Docker é uma ferramenta que coloca dentro de um único pacote o seu código e o ambiente inteiro que ele exige (versão da linguagem, bibliotecas, dependências do sistema, configuração) num pacote chamado imagem. Essa imagem se comporta igual em qualquer computador com Docker instalado, seja o seu, o da equipe ou o de produção, rodando como um container. É por isso que ele acabou com o “na minha máquina funciona”: a máquina passa a ir junto com o código.
$ ls ./neste-artigo
- Imagem, container e Dockerfile sem confusão
- Etapa 1: instalar e rodar o primeiro container
- Etapa 2: subir um serviço pronto sem instalar nada
- Etapa 3: escrever o Dockerfile do seu projeto
- Etapa 4: construir a imagem e rodar o container
- Etapa 5: juntar aplicação e banco com Docker Compose
- Docker no dia a dia: três dúvidas de quem acabou de instalar
- Um Dockerfile no portfólio diz muito sobre você
O problema que ele resolve é velho. Você usa Python 3.12, o servidor tem 3.9. Seu colega no Windows não consegue instalar a biblioteca de PDF que no seu Linux instalou de primeira. O projeto precisa de PostgreSQL 16 e Redis, e cada pessoa nova no time perde um dia configurando tudo. Com Docker, quem chega roda um comando e tem o ambiente inteiro de pé.
Abaixo está o caminho prático, do primeiro comando até um projeto com banco de dados, apontando onde iniciantes costumam travar em cada etapa.
Imagem, container e Dockerfile sem confusão
Três palavras resolvem 90% da confusão inicial:
- Dockerfile: a receita. Um arquivo de texto com as instruções para montar a imagem.
- Imagem: o bolo pronto e congelado. Um pacote somente leitura, feito em camadas, gerado a partir do Dockerfile.
- Container: a fatia servida. Uma instância da imagem em execução. Da mesma imagem você pode rodar dez containers.
E não, container não é uma máquina virtual. A VM emula um computador inteiro com seu próprio sistema operacional, gigabytes de disco e minutos para ligar. O container compartilha o kernel do sistema hospedeiro e isola só os processos, arquivos e rede, e é por isso que liga quase instantaneamente e cabe em poucas dezenas ou centenas de MB. O resumo da arquitetura na documentação do Docker mostra essa arquitetura com o cliente, o daemon e os registros de imagens.

Etapa 1: instalar e rodar o primeiro container
No Windows e no Mac, instale o Docker Desktop. No Windows, ele usa o WSL 2, então ative-o antes. No Linux, instale o Docker Engine pelo repositório oficial da sua distribuição. Depois, no terminal:
docker run hello-worldEsse comando procura a imagem hello-world no seu computador, não encontra, baixa do Docker Hub, cria um container e o executa. Se aparecer a mensagem de boas-vindas, está tudo certo.
Tropeço comum aqui: no Linux, o erro “permission denied” ao acessar o socket do Docker significa que seu usuário não está no grupo docker. No Windows, a mensagem de que o daemon não está rodando quase sempre é o Docker Desktop fechado ou o WSL 2 desativado.
Etapa 2: subir um serviço pronto sem instalar nada
Antes de escrever seu próprio Dockerfile, use imagens oficiais. Precisa de um PostgreSQL para estudar?
docker run --name banco-estudo -e POSTGRES_PASSWORD=senha123 -p 5432:5432 -d postgres:16Em segundos você tem um PostgreSQL 16 ouvindo na porta 5432, sem instalador e sem bagunçar o sistema. Alguns comandos que você vai usar o tempo todo:
| Comando | O que faz |
|---|---|
| docker ps | Lista containers em execução (-a mostra também os parados) |
| docker logs banco-estudo | Mostra a saída do container, primeiro lugar a olhar quando algo falha |
| docker exec -it banco-estudo bash | Abre um terminal dentro do container |
| docker stop banco-estudo | Para o container |
| docker rm banco-estudo | Remove o container parado |
| docker images | Lista as imagens baixadas |
Atenção às portas: o -p 5432:5432 liga a porta da sua máquina (à esquerda) à porta do container (à direita). Se você já tem um PostgreSQL instalado usando a 5432, o comando falha com “port is already allocated”. Troque para -p 5433:5432. E atenção: ao remover o container, os dados vão junto, a menos que você use um volume (etapa 5).
Etapa 3: escrever o Dockerfile do seu projeto
Para uma API simples em Python com Flask:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["flask", "run", "--host=0.0.0.0"]Linha a linha: parte de uma imagem oficial enxuta de Python, define a pasta de trabalho, copia primeiro só a lista de dependências, instala, depois copia o resto do código e define o comando de início.
Detalhe que muda o tempo de build: a ordem das linhas importa. Cada instrução vira uma camada, e o Docker reaproveita camadas que não mudaram. Copiando o requirements.txt antes do código, a instalação de dependências só se repete quando a lista muda, e não a cada vírgula alterada no código. O guia de boas práticas para Dockerfile detalha essa e outras otimizações. Crie também um arquivo .dockerignore com .git, .env, venv e __pycache__, para não mandar lixo (nem senhas) para dentro da imagem.
Etapa 4: construir a imagem e rodar o container
docker build -t minha-api .
docker run -p 5000:5000 minha-apiO ponto no final do build é o contexto, a pasta enviada ao Docker. Abra http://localhost:5000 e a API responde.
O clássico da primeira vez: a aplicação sobe, mas o navegador não conecta. Em 9 de 10 casos, o servidor está ouvindo em 127.0.0.1 dentro do container, que só aceita conexões vindas dele mesmo. Por isso o –host=0.0.0.0 no Flask (e o equivalente em Node, Django ou Rails).

Etapa 5: juntar aplicação e banco com Docker Compose
Projetos reais têm vários serviços. Em vez de vários docker run compridos, descreva tudo num compose.yaml:
services:
api:
build: .
ports:
- "5000:5000"
environment:
DATABASE_URL: postgresql://postgres:senha123@db:5432/postgres
depends_on:
- db
db:
image: postgres:16
environment:
POSTGRES_PASSWORD: senha123
volumes:
- dados:/var/lib/postgresql/data
volumes:
dados:Um docker compose up sobe os dois; docker compose down derruba. Repare que a API acessa o banco pelo nome db, e não por localhost: dentro da rede do Compose, cada serviço é encontrado pelo nome. Esse é o erro número um de quem monta o primeiro Compose. O volume dados garante que o banco sobreviva quando os containers forem recriados.
Docker no dia a dia: três dúvidas de quem acabou de instalar
- Meu disco encheu, o que aconteceu? Imagens, containers parados e camadas antigas se acumulam. O comando docker system prune remove o que não está em uso; com -a, apaga também imagens sem container, então use com calma.
- Alterei o código e nada mudou no container. A imagem é uma foto do momento do build. Rode docker compose up –build ou, em desenvolvimento, monte a pasta do projeto como volume para ver as mudanças na hora.
- Posso colocar a senha do banco no Dockerfile? Não. Tudo que entra na imagem fica gravado nas camadas e pode ser lido por quem tiver a imagem. Use variáveis de ambiente, um arquivo .env fora do controle de versão ou o gerenciador de segredos da plataforma.
Um Dockerfile no portfólio diz muito sobre você
Coloque um Dockerfile e um compose.yaml no próximo projeto de portfólio e escreva no README que basta rodar docker compose up. Para quem avalia, isso mostra que você pensa em quem vai usar seu código depois. É também o primeiro passo para pipelines de deploy e para Kubernetes, temas que você encontra, junto com container, imagem e volume, no glossário de programação. Se a sua máquina sofre com vários containers abertos, o texto sobre o que não pode faltar num notebook seminovo para programar ajuda a dimensionar memória e disco.




