---
title: "Python e Docker: Guia Completo — 2025 | Python Brasil"
url: "https://python.dev.br/blog/python-e-docker/"
markdown_url: "https://python.dev.br/blog/python-e-docker.MD"
description: "Aprenda a containerizar aplicacoes Python com Docker. Dockerfile otimizado, docker-compose, multi-stage builds e boas praticas de producao."
date: "2025-11-08"
author: "Equipe Python Brasil"
---

# Python e Docker: Guia Completo — 2025 | Python Brasil

Aprenda a containerizar aplicacoes Python com Docker. Dockerfile otimizado, docker-compose, multi-stage builds e boas praticas de producao.


Docker — que é escrito em <a href="https://golang.com.br/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', { destination: 'golang.com.br' })">Go</a> — revolucionou a forma como empacotamos e distribuimos aplicacoes. Com containers, voce garante que o ambiente de desenvolvimento e identico ao de producao, eliminando o classico "na minha maquina funciona". Neste guia, a gente vai aprender a containerizar aplicacoes Python do zero, com exemplos otimizados para producao.

## Por Que Usar Docker com Python?

Projetos Python frequentemente dependem de versoes especificas do interpretador, bibliotecas nativas e configuracoes de ambiente. Docker resolve todos esses problemas encapsulando a aplicacao e suas dependencias em um container isolado e reproduzivel.

## Dockerfile Basico para Python

Vamos comecar com uma aplicacao Flask simples. Primeiro, a estrutura do projeto:

```
meu-projeto/
    app.py
    requirements.txt
    Dockerfile
    .dockerignore
```

O arquivo `app.py`:

```python
from flask import Flask, jsonify

app = Flask(__name__)

@app.route("/")
def index():
    return jsonify({"mensagem": "Ola do container Docker!", "status": "ok"})

@app.route("/saude")
def saude():
    return jsonify({"status": "saudavel"})

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=5000)
```

O `requirements.txt`:

```
flask==3.0.0
gunicorn==21.2.0
```

Agora o `Dockerfile`:

```dockerfile
# Imagem base
FROM python:3.12-slim

# Definir diretorio de trabalho
WORKDIR /app

# Copiar e instalar dependencias primeiro (cache de camadas)
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

# Copiar codigo da aplicacao
COPY . .

# Expor a porta
EXPOSE 5000

# Comando para executar
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "app:app"]
```

O `.dockerignore`:

```
__pycache__
*.pyc
.git
.env
venv/
.venv/
*.md
.pytest_cache/
```

## Construindo e Executando

```bash
# Construir a imagem
docker build -t minha-app-python .

# Executar o container
docker run -d -p 5000:5000 --name minha-app minha-app-python

# Verificar logs
docker logs minha-app

# Testar
curl http://localhost:5000/
# {"mensagem": "Ola do container Docker!", "status": "ok"}
```

## Multi-Stage Build para Imagens Menores

Multi-stage builds permitem separar a fase de build da imagem final, reduzindo drasticamente o tamanho:

```dockerfile
# Estagio 1: Build
FROM python:3.12-slim AS builder

WORKDIR /app

# Instalar dependencias de build
RUN apt-get update && apt-get install -y --no-install-recommends gcc

COPY requirements.txt .
RUN pip install --no-cache-dir --prefix=/install -r requirements.txt

# Estagio 2: Producao
FROM python:3.12-slim

WORKDIR /app

# Copiar apenas as dependencias instaladas
COPY --from=builder /install /usr/local

# Criar usuario nao-root
RUN useradd --create-home appuser
USER appuser

COPY --chown=appuser:appuser . .

EXPOSE 5000

CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "4", "app:app"]
```

Essa abordagem pode reduzir a imagem de mais de 400 MB para menos de 150 MB.

## Docker Compose para Ambientes Completos

Na pratica, aplicacoes precisam de banco de dados, cache e outros servicos. O Docker Compose orquestra tudo:

```yaml
# docker-compose.yml
version: "3.9"

services:
  web:
    build: .
    ports:
      - "5000:5000"
    environment:
      - DATABASE_URL=postgresql://user:senha@db:5432/minha_app
      - REDIS_URL=redis://cache:6379/0
    depends_on:
      db:
        condition: service_healthy
      cache:
        condition: service_started
    volumes:
      - .:/app  # Para desenvolvimento
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: user
      POSTGRES_PASSWORD: senha
      POSTGRES_DB: minha_app
    volumes:
      - postgres_data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U user"]
      interval: 5s
      timeout: 5s
      retries: 5

  cache:
    image: redis:7-alpine
    ports:
      - "6379:6379"

volumes:
  postgres_data:
```

Para usar:

```bash
# Subir todos os servicos
docker compose up -d

# Ver logs de todos os servicos
docker compose logs -f

# Parar tudo
docker compose down

# Reconstruir apos mudancas no Dockerfile
docker compose up -d --build
```

## Configuracao para Desenvolvimento vs Producao

Separe as configuracoes usando arquivos compose diferentes:

```yaml
# docker-compose.override.yml (desenvolvimento - aplicado automaticamente)
version: "3.9"

services:
  web:
    command: python app.py  # Modo debug ao inves de gunicorn
    volumes:
      - .:/app
    environment:
      - FLASK_ENV=development
      - FLASK_DEBUG=1
```

```yaml
# docker-compose.prod.yml
version: "3.9"

services:
  web:
    volumes: []  # Sem volume mount em producao
    environment:
      - FLASK_ENV=production
    deploy:
      replicas: 3
      resources:
        limits:
          cpus: "0.5"
          memory: 512M
```

Para producao:

```bash
docker compose -f docker-compose.yml -f docker-compose.prod.yml up -d
```

## Variaveis de Ambiente e Segredos

Nunca coloque senhas diretamente no Dockerfile. Use variaveis de ambiente:

```python
import os

class Config:
    """Configuracao carregada de variaveis de ambiente."""
    DATABASE_URL = os.environ.get("DATABASE_URL", "sqlite:///local.db")
    REDIS_URL = os.environ.get("REDIS_URL", "redis://localhost:6379/0")
    SECRET_KEY = os.environ.get("SECRET_KEY", "chave-dev-insegura")
    DEBUG = os.environ.get("FLASK_DEBUG", "0") == "1"
```

Use um arquivo `.env` para desenvolvimento:

```
# .env (nunca comite este arquivo)
DATABASE_URL=postgresql://user:senha@db:5432/minha_app
SECRET_KEY=minha-chave-super-secreta
FLASK_DEBUG=1
```

## Healthcheck na Aplicacao

Adicione endpoints de saude para monitoramento:

```python
from flask import Flask, jsonify
import psycopg2
import redis

@app.route("/saude")
def healthcheck():
    """Endpoint de healthcheck para Docker e orquestradores."""
    status = {"api": "ok"}

    try:
        r = redis.from_url(app.config["REDIS_URL"])
        r.ping()
        status["redis"] = "ok"
    except Exception:
        status["redis"] = "erro"

    return jsonify(status), 200 if all(v == "ok" for v in status.values()) else 503
```

No Dockerfile:

```dockerfile
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
    CMD curl -f http://localhost:5000/saude || exit 1
```

## Boas Praticas

Ao containerizar aplicacoes Python, siga estas recomendacoes:

- Use imagens `slim` ou `alpine` para reducao de tamanho
- Copie `requirements.txt` antes do codigo para aproveitar cache de camadas
- Nunca execute containers como root em producao
- Use `.dockerignore` para evitar copiar arquivos desnecessarios
- Defina `HEALTHCHECK` para monitoramento automatico
- Use multi-stage builds para separar build de producao
- Congele versoes das dependencias no `requirements.txt`
- Nao armazene dados dentro do container, use volumes

## Conclusao

Docker e uma ferramenta indispensavel para projetos Python modernos. Com Dockerfiles otimizados, multi-stage builds e Docker Compose, voce garante ambientes reproduziveis e deploys confiaveis. Comece containerizando um projeto simples e gradualmente adote praticas mais avancadas como orquestracao com Kubernetes. O investimento em Docker se paga rapidamente na produtividade do time.
