Docker/Artigo

    Docker Compose em produção: configuração correta

    Para produção, um docker-compose.yml precisa de: restart: always (para subir automaticamente após reinicialização do servidor), healthchecks (para depends_on funcionar de verdade), logging com rotação (para não encher o disco), limites de recursos (para isolar falhas) e variáveis sensíveis em arquivo .env separado — nunca hard-coded no Compose.

    Template base para produção

    Estrutura mínima de um serviço de produção com todas as configurações essenciais:

    yaml
    services:
      app:
        image: minha-app:1.2.3          # versão fixa, nunca :latest em prod
        restart: always
        env_file: .env                  # variáveis sensíveis fora do compose
        ports:
          - "127.0.0.1:3000:3000"       # bind apenas no localhost, NGINX expõe externamente
        depends_on:
          db:
            condition: service_healthy  # aguarda o banco estar pronto
        deploy:
          resources:
            limits:
              memory: 512M
              cpus: '1.0'
        logging:
          driver: json-file
          options:
            max-size: "10m"
            max-file: "3"
        healthcheck:
          test: ["CMD", "curl", "-f", "http://localhost:3000/health"]
          interval: 30s
          timeout: 5s
          retries: 3
          start_period: 10s
    
      db:
        image: postgres:16
        restart: always
        env_file: .env
        volumes:
          - pg_data:/var/lib/postgresql/data
        deploy:
          resources:
            limits:
              memory: 1G
        logging:
          driver: json-file
          options:
            max-size: "10m"
            max-file: "3"
        healthcheck:
          test: ["CMD-SHELL", "pg_isready -U $POSTGRES_USER -d $POSTGRES_DB"]
          interval: 10s
          timeout: 5s
          retries: 5
    
    volumes:
      pg_data:

    restart: always vs unless-stopped

    Escolha a política de restart correta para cada tipo de serviço:

    Dica
    restart: always — reinicia sempre, inclusive após docker stop + docker start. Ideal para serviços de longa duração que devem sobreviver a reinicializações do host. restart: unless-stopped — igual ao always, mas não reinicia se você parou manualmente. Útil durante manutenção. restart: on-failure — reinicia apenas em saída com erro (código ≠ 0). Ideal para jobs e workers. restart: no (padrão) — nunca reinicia. Use apenas em desenvolvimento.

    Arquivo .env e segredos

    Variáveis sensíveis (senhas, API keys) nunca devem aparecer no docker-compose.yml — use arquivo .env:

    bash
    # .env (nunca commite no git — adicione ao .gitignore)
    POSTGRES_USER=appuser
    POSTGRES_PASSWORD=senha_super_segura_aqui
    POSTGRES_DB=producao
    SECRET_KEY=chave_jwt_256_bits_aqui
    
    # No docker-compose.yml, referencie:
    # env_file: .env
    
    # Ou por variável individual:
    # environment:
    #   POSTGRES_USER: ${POSTGRES_USER}
    
    # Verificar quais variáveis estão sendo resolvidas:
    docker compose config
    Atenção
    Adicione .env ao .gitignore imediatamente. Se você commitar senhas por engano, rotacione-as — remover do histórico do Git é complexo e a senha pode já ter vazado.

    Versões fixas de imagem em produção

    Nunca use :latest em produção — uma atualização automática pode quebrar seu serviço silenciosamente:

    bash
    # Ruim — :latest pode mudar a qualquer momento
    image: postgres:latest
    
    # Bom — versão major/minor fixa, patch automático
    image: postgres:16
    
    # Melhor — versão completamente fixa com digest (imutável)
    image: postgres:16.3
    Dica
    Para atualizar imagens controladamente: docker compose pull → docker compose up -d. Isso baixa as novas imagens antes de subir, minimizando downtime.

    Estratégia de deploy sem downtime

    Para deploys com downtime mínimo usando Compose puro (sem Swarm/Kubernetes):

    bash
    # Pull da nova imagem enquanto a versão atual ainda está rodando
    docker compose pull app
    
    # Recria apenas o serviço atualizado (outros serviços continuam)
    docker compose up -d --no-deps app
    
    # Verificar se o healthcheck passou antes de considerar o deploy OK
    docker compose ps
    docker inspect app_container_1 | grep -A5 '"Health"'
    Dica
    Com --no-deps, apenas o serviço especificado é recriado — outros serviços (banco, cache, workers) continuam rodando sem interrupção.

    $ runstack deploy --plan starter

    Não quer configurar manualmente?

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

    Perguntas frequentes