Docker para Python em 2026: Guia Completo
Aprenda a configurar Docker para projetos Python em 2026: Dockerfile seguro, docker compose, healthcheck, usuário não-root, Redis, Postgres e deploy.
Introdução
Docker é uma ferramenta que permite empacotar sua aplicação Python junto com todas as dependências em um container isolado. Isso garante que o código funcione da mesma forma no seu computador, no servidor de produção, no CI e na máquina de qualquer colega de equipe.
Em 2026, Docker deixou de ser apenas uma habilidade de DevOps. Ele aparece em vagas Python de backend, dados, IA, QA, plataforma e automação porque facilita testes reproduzíveis, deploy previsível e integração com serviços como PostgreSQL, Redis, workers e observabilidade. Se você quer transformar um projeto de portfólio em algo próximo de produção, saber criar um Dockerfile limpo e um docker-compose.yml honesto é uma das formas mais rápidas de mostrar maturidade técnica.
Neste guia, vamos configurar Docker para projetos Python, criar Dockerfiles otimizados, usar Docker Compose para aplicações com múltiplos serviços e fechar com uma checklist de produção. Se você ainda está no começo, leia também ambientes virtuais em Python antes de containerizar; Docker não substitui organização de dependências, ele empacota essa organização.
Pré-requisitos
Instale o Docker Desktop no seu sistema operacional:
- macOS:
brew install --cask dockerou baixe em docker.com - Windows: baixe o Docker Desktop e habilite o WSL 2
- Linux: instale via gerenciador de pacotes da sua distribuição
Verifique a instalação:
docker --version
docker compose version
Conceitos básicos
- Imagem: template somente leitura que define o ambiente (sistema operacional, Python, dependências)
- Container: instância em execução de uma imagem
- Dockerfile: arquivo de instruções para construir uma imagem
- docker-compose.yml: arquivo que define múltiplos containers e como eles se conectam
- Volume: armazenamento persistente ou pasta montada no container
- Rede: camada que permite um container acessar outro pelo nome do serviço
Uma boa regra mental: o Dockerfile descreve como construir a aplicação; o Compose descreve como rodar essa aplicação junto com dependências locais. Misturar as duas responsabilidades costuma gerar imagens frágeis e difíceis de publicar.
Primeiro Dockerfile para Python
Crie um projeto simples com uma aplicação Flask:
meu-projeto/
app.py
requirements.txt
Dockerfile
O app.py:
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return {'mensagem': 'Olá do Docker!'}
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
O requirements.txt:
flask==3.1.0
gunicorn==23.0.0
Agora o Dockerfile:
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
Cada linha do Dockerfile é uma instrução:
FROM: define a imagem base (Python 3.12 na versão slim, mais leve)WORKDIR: define o diretório de trabalho dentro do containerCOPY requirements.txt .: copia apenas o requirements primeiro (otimiza cache)RUN pip install: instala as dependênciasCOPY . .: copia o restante do códigoEXPOSE: documenta a porta usadaCMD: comando executado quando o container inicia
Construindo e executando
# Construir a imagem
docker build -t meu-projeto .
# Executar o container
docker run -p 5000:5000 meu-projeto
Acesse http://localhost:5000 e verá a resposta JSON da aplicação.
O arquivo .dockerignore
Crie um .dockerignore para evitar copiar arquivos desnecessários:
venv/
__pycache__/
*.pyc
.git/
.env
*.md
.pytest_cache/
Isso reduz o tamanho da imagem e acelera o build.
Evite colocar *.md no .dockerignore se a aplicação usa arquivos Markdown em tempo de execução. Para APIs e aplicações web comuns, excluir documentação é seguro; para sites estáticos, geradores de conteúdo ou pipelines que leem Markdown, ajuste a lista.
Dockerfile seguro para FastAPI
O exemplo mínimo acima funciona, mas projetos reais precisam de alguns cuidados extras: não rodar como root, instalar dependências de forma previsível, expor logs imediatamente e preparar um endpoint de saúde.
Um exemplo para FastAPI:
api-pedidos/
app/
main.py
requirements.txt
Dockerfile
.dockerignore
app/main.py:
from fastapi import FastAPI
app = FastAPI(title="API de pedidos")
@app.get("/saude")
def saude():
return {"status": "ok"}
@app.get("/pedidos/{pedido_id}")
def buscar_pedido(pedido_id: int):
return {"pedido_id": pedido_id, "status": "processando"}
requirements.txt:
fastapi==0.115.6
uvicorn[standard]==0.34.0
Dockerfile:
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN addgroup --system app && adduser --system --ingroup app app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY --chown=app:app . .
USER app
EXPOSE 8000
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD python -c "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8000/saude')"
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000"]
Pontos importantes desse Dockerfile:
PYTHONDONTWRITEBYTECODE=1evita arquivos.pycdentro do container.PYTHONUNBUFFERED=1faz os logs aparecerem em tempo real.addusercria um usuário sem privilégios para rodar a aplicação.COPY requirements.txtantes do código melhora o cache de build.HEALTHCHECKpermite que Docker, CI e orquestradores detectem quando a API não responde.
Se a API usa FastAPI em produção, combine este guia com API com FastAPI, OpenTelemetry com Python e deploy de aplicação Python. Docker resolve empacotamento; observabilidade e deploy ainda precisam ser tratados explicitamente.
Docker Compose para múltiplos serviços
Aplicações reais geralmente precisam de banco de dados, cache e outros serviços. O docker-compose orquestra tudo isso.
Crie o docker-compose.yml:
services:
web:
build: .
ports:
- "5000:5000"
volumes:
- .:/app
environment:
- DATABASE_URL=postgresql://usuario:senha@db:5432/meu_banco
- REDIS_URL=redis://redis:6379/0
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16
environment:
POSTGRES_USER: usuario
POSTGRES_PASSWORD: senha
POSTGRES_DB: meu_banco
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U usuario -d meu_banco"]
interval: 5s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
Esse Compose é suficiente para desenvolver uma API com banco e cache local. Para filas e tarefas assíncronas, o mesmo Redis pode servir como broker de Celery em projetos simples; aprofunde em FastAPI Background Tasks, Celery e Redis e no verbete Celery.
Inicie todos os serviços:
docker compose up -d
Comandos úteis do docker-compose:
# Ver logs
docker compose logs -f web
# Parar tudo
docker compose down
# Reconstruir após mudanças no Dockerfile
docker compose up --build
# Executar comando dentro do container
docker compose exec web python manage.py migrate
Multi-stage build
Para imagens de produção menores, use multi-stage build:
# Estágio 1: Build
FROM python:3.12-slim AS builder
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt
# Estágio 2: Produção
FROM python:3.12-slim
WORKDIR /app
COPY --from=builder /install /usr/local
COPY . .
RUN useradd --create-home appuser
USER appuser
EXPOSE 5000
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"]
Isso cria uma imagem final que contém apenas o necessário para rodar a aplicação, sem ferramentas de build.
Use multi-stage principalmente quando o projeto instala dependências nativas, compila assets ou precisa de ferramentas de build que não devem ficar na imagem final. Para aplicações pequenas com dependências puramente Python, um Dockerfile simples, bem cacheado e não-root já pode ser suficiente.
Dockerfile para Django
Para projetos Django, o Dockerfile precisa de alguns ajustes:
FROM python:3.12-slim
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
WORKDIR /app
RUN apt-get update && apt-get install -y \
libpq-dev \
&& rm -rf /var/lib/apt/lists/*
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
RUN python manage.py collectstatic --noinput
EXPOSE 8000
CMD ["gunicorn", "--bind", "0.0.0.0:8000", "config.wsgi:application"]
As variáveis de ambiente PYTHONDONTWRITEBYTECODE e PYTHONUNBUFFERED são boas práticas para containers Python. A primeira evita arquivos .pyc desnecessários e a segunda garante que os logs apareçam em tempo real.
Variáveis de ambiente e segredos
Nunca coloque senhas diretamente no Dockerfile ou docker-compose.yml. Use arquivos .env:
# .env (não commitar no git!)
DATABASE_URL=postgresql://usuario:senha@db:5432/meu_banco
SECRET_KEY=minha-chave-secreta
DEBUG=False
No docker-compose.yml:
services:
web:
build: .
env_file:
- .env
O .env local deve ficar no .gitignore. Em produção, prefira o gerenciador de segredos da plataforma: variáveis do Cloudflare, Render, Railway, Fly.io, Kubernetes Secret, Docker Swarm secret ou cofre interno. O ponto essencial é não gravar segredo em imagem, repositório, log ou exemplo público.
Testes, dados e CI dentro do container
Docker também ajuda a validar que o projeto roda fora da sua máquina. Um fluxo comum de CI é construir a imagem, subir dependências e rodar testes:
docker compose build
docker compose run --rm web pytest
docker compose run --rm web python -m pip check
Para projetos de dados, rode uma amostra do pipeline dentro do container para garantir que versões de Pandas, conectores e bibliotecas nativas estão corretas. Se a dor principal é qualidade de entrada, leia Pandera com Python e conecte validação de dados ao build: um pipeline que só funciona no notebook ainda não é reproduzível.
Em APIs, rode pelo menos testes unitários, teste de healthcheck e uma chamada HTTP local. Exemplo:
docker compose up -d
curl -fsS http://localhost:8000/saude
docker compose logs --no-color web
docker compose down
Esse tipo de evidência aparece bem em README de portfólio: mostra que você pensou em instalação, teste, logs e operação, não apenas na feature principal.
Boas práticas
- Use imagens
slimpara reduzir tamanho sem herdar as surpresas de compatibilidade do Alpine - Copie
requirements.txtantes do código para aproveitar o cache de layers - Crie um usuário não-root para rodar a aplicação
- Defina
PYTHONDONTWRITEBYTECODE=1ePYTHONUNBUFFERED=1 - Use
.dockerignorepara excluir arquivos desnecessários - Fixe versões das dependências no requirements.txt
- Use health checks no docker-compose para verificar se os serviços estão saudáveis
- Não coloque
.env, chaves ou dumps de produção na imagem - Separe Compose local de configuração real de produção
- Registre logs em stdout/stderr para facilitar coleta por Docker, CI e plataformas de deploy
- Documente comandos de build, teste e execução no README
Erros comuns em Docker com Python
Alguns problemas se repetem em projetos de iniciantes e testes técnicos:
| Erro | Consequência | Como corrigir |
|---|---|---|
Copiar o projeto inteiro antes do pip install | qualquer mudança invalida o cache | copie requirements.txt primeiro |
Rodar como root | risco maior se a aplicação for explorada | crie appuser e use USER appuser |
| Usar volume em produção como no desenvolvimento | código local sobrescreve a imagem | limite volumes ao Compose local |
| Esquecer healthcheck | falhas viram timeout misterioso | crie /saude e teste com curl ou Python |
| Guardar segredo no Dockerfile | vazamento no repositório ou registry | use variáveis e cofre de segredos |
| Não testar o container no CI | deploy quebra fora da máquina local | rode docker compose run --rm web pytest |
Docker no portfólio e em vagas Python
Para vagas júnior e pleno, Docker costuma aparecer como diferencial prático: a pessoa avaliadora consegue clonar o repositório, rodar um comando e ver o projeto funcionando. Isso vale para APIs, automações, pipelines de dados, web scraping, bots internos e aplicações Django.
Um bom README de projeto Python com Docker deve incluir:
- objetivo do projeto;
- tecnologias usadas;
- comando para copiar
.env.example; docker compose up --build;- URL local para testar;
- comando de testes;
- explicação curta de Postgres, Redis, filas ou serviços externos;
- observações de deploy.
Se você está montando evidência para carreira, conecte este guia com projetos de portfólio Python, teste técnico Python e vagas Python. Docker não substitui código limpo, testes e domínio do problema, mas reduz fricção para quem avalia seu trabalho.
Conclusão
Docker simplifica o desenvolvimento e deploy de aplicações Python, eliminando problemas de “funciona na minha máquina”. Com Dockerfiles otimizados, Docker Compose, healthchecks, usuário não-root e testes rodando no container, você pode configurar ambientes complexos com poucos comandos e entregar projetos mais fáceis de revisar.
Docker também é amplamente usado com outras linguagens de backend. Veja conteúdos de Go no golang.com.br para comparar como binários estáticos mudam a estratégia de imagem em serviços compilados.