Deploy de app Python na VPS com Docker

    Deploy de aplicação Python com Docker elimina o problema clássico de "funciona na minha máquina" — o container carrega exatamente a versão do Python, as dependências e as variáveis de ambiente necessárias. O processo é o mesmo para Flask, FastAPI, Django, scripts de automação ou bots.

    Dockerfile Python: boas práticas

    A ordem das instruções no Dockerfile importa para o cache de build — copie requirements.txt antes do código para evitar reinstalar dependências a cada mudança de código:

    dockerfile
    # Dockerfile
    FROM python:3.12-slim
    
    # Variáveis que melhoram comportamento do Python em containers
    ENV PYTHONDONTWRITEBYTECODE=1 \
        PYTHONUNBUFFERED=1 \
        PIP_NO_CACHE_DIR=1 \
        PIP_DISABLE_PIP_VERSION_CHECK=1
    
    WORKDIR /app
    
    # Dependências do sistema (somente o necessário)
    RUN apt-get update && apt-get install -y --no-install-recommends \
        curl \
        && rm -rf /var/lib/apt/lists/*
    
    # Requirements antes do código (cache de camada)
    COPY requirements.txt .
    RUN pip install -r requirements.txt
    
    # Código da aplicação
    COPY . .
    
    # Usuário não-root
    RUN useradd --create-home appuser
    USER appuser
    
    EXPOSE 8000
    CMD ["python", "-m", "uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]
    Dica
    PYTHONUNBUFFERED=1 faz o Python imprimir logs imediatamente sem buffer — essencial em containers para ver o output em tempo real com docker logs. PYTHONDONTWRITEBYTECODE=1 evita criar arquivos .pyc na imagem.

    requirements.txt: fixar versões

    Fixar versões exatas no requirements.txt garante builds reproduzíveis — sem surpresas com breaking changes de atualizações automáticas:

    bash
    # Gerar requirements.txt a partir do ambiente atual
    pip freeze > requirements.txt
    
    # Ou usar pip-tools para gestão mais precisa
    pip install pip-tools
    
    # Criar requirements.in com dependências diretas
    # requirements.in:
    # fastapi
    # sqlalchemy
    # python-dotenv
    
    # Gerar requirements.txt com versões pinadas (incluindo transitive deps)
    pip-compile requirements.in
    
    # Atualizar dependências (quando necessário)
    pip-compile --upgrade requirements.in
    
    # Instalar exatamente as versões especificadas
    pip install -r requirements.txt
    Dica
    pip freeze captura TODAS as dependências instaladas (incluindo transitivas). pip-tools gera um requirements.txt mais limpo e controlado, separando dependências diretas (requirements.in) das transitivas.

    docker-compose.yml para aplicação Python

    Configuração padrão para web app Python com banco de dados:

    yaml
    services:
      web:
        build: .
        restart: always
        env_file: .env
        ports: []                    # não expor diretamente — usar Nginx
        depends_on:
          db:
            condition: service_healthy
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:8000/health"]
          interval: 30s
          timeout: 10s
          retries: 3
        logging:
          driver: json-file
          options:
            max-size: "10m"
            max-file: "3"
        networks:
          - app_net
    
      db:
        image: postgres:16-alpine
        restart: always
        environment:
          POSTGRES_USER: ${DB_USER}
          POSTGRES_PASSWORD: ${DB_PASS}
          POSTGRES_DB: ${DB_NAME}
        volumes:
          - db_data:/var/lib/postgresql/data
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U ${DB_USER}"]
          interval: 10s
          retries: 5
        networks:
          - app_net
    
    volumes:
      db_data:
    
    networks:
      app_net:

    Virtual environments vs Docker: quando usar cada um

    Em VPS com Docker, o container já é o isolamento — não é necessário venv dentro do container. Mas em VPS sem Docker, venv é essencial:

    bash
    # SEM Docker (venv no host):
    # Criar venv
    python3 -m venv /opt/minha-app/venv
    
    # Ativar e instalar dependências
    source /opt/minha-app/venv/bin/activate
    pip install -r requirements.txt
    
    # Rodar com systemd (sem ativar o venv manualmente)
    # /etc/systemd/system/minha-app.service:
    # [Service]
    # ExecStart=/opt/minha-app/venv/bin/python -m uvicorn main:app
    # WorkingDirectory=/opt/minha-app
    
    # COM Docker (sem venv — o container já isola):
    # No Dockerfile, instale diretamente no sistema Python do container
    # pip install -r requirements.txt (sem venv)
    Dica
    Venv dentro de container Docker adiciona complexidade sem benefício — o container já provê o isolamento. Use venv apenas quando rodar Python diretamente no host (sem Docker).

    Debug: entrar no container e inspecionar

    Comandos para diagnosticar problemas em containers Python:

    bash
    # Entrar no container em execução
    docker compose exec web bash   # ou sh para Alpine
    docker compose exec web python  # console Python interativo
    
    # Inspecionar variáveis de ambiente dentro do container
    docker compose exec web env | grep -E "DB_|SECRET|ENV"
    
    # Rodar script Python avulso no container
    docker compose exec web python scripts/seed_database.py
    
    # Ver logs de erros do Python
    docker compose logs web --tail=50 | grep -i "error|exception|traceback"
    
    # Verificar dependências instaladas
    docker compose exec web pip list
    docker compose exec web pip show fastapi

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

    Não quer configurar manualmente? Implante o VPS em menos de 3 minutos com a Runstack. Infraestrutura da OPEN DATACENTER, com servidores no Brasil.

    Perguntas frequentes