Desenvolvimento & IA 7 min de leitura

Como Subir uma Aplicação PHP Resiliente em VPS com Docker e CI/CD

Guilherme Nascimento 0 comentários

No nosso artigo recente sobre as quedas da Railway e a grande migração das PaaS, mostramos como depender exclusivamente de plataformas mágicas pode custar caro quando o plano de controle de terceiros entra em pane.

A alternativa definitiva que separa os amadores dos engenheiros seniores é a autonomia da infraestrutura: hospedar sua aplicação em uma VPS própria (Hetzner, DigitalOcean, Linode ou AWS Lightsail) com Docker e esteira automatizada de CI/CD via GitHub Actions.

Uma stack PHP moderna (seja ela Laravel, Symfony ou um microframework em PHP 8.3+) configurada dessa forma oferece o melhor dos dois mundos: custa uma fração do preço das PaaS (a partir de US$ 5/mês), entrega zero downtime e nunca sai do ar por instabilidade de terceiros.

Neste guia prático, você vai aprender a montar uma esteira de produção completa, do Dockerfile multi-stage à automação de deploy contínuo via SSH.

⚡ Arquitetura da Stack Resiliente (TL;DR de 30 Segundos)

Componente Tecnologia Escolhida Função na Arquitetura Benefício de Resiliência
**Infraestrutura** VPS Linux (Ubuntu 24.04 LTS) Hospedagem dedicada dos containers Previsibilidade financeira (US$ 5/mês fixo) e total controle
**Servidor Web** Nginx / Caddy Reverse Proxy e terminação SSL Entrega rápida de estáticos e SSL automático
**Processamento** PHP 8.3-FPM + OPcache Execução isolada das requisições PHP Alta performance com pré-compilação em memória RAM
**Automação CI/CD** GitHub Actions Testes automatizados e deploy contínuo Deploy sem intervenção manual com rollback se o build falhar
**Auto-Recuperação** Docker Healthchecks Monitoramento do container a cada 10s Reinício automático caso o PHP-FPM trave

🧭 Os 4 Pilares da Resiliência PHP em Produção

Subir PHP em produção não é apenas rodar php artisan serve dentro de uma máquina virtual. Uma aplicação resiliente precisa obedecer a quatro regras estruturais:

⚡
Performance

1. OPcache em Produção

O PHP nunca deve reler e interpretar arquivos do disco a cada requisição. O OPcache armazena os bytecodes pré-compilados direto na memória compartilhada.

Impacto: Reduz o consumo de CPU em até 70% e acelera o tempo de resposta em 3x.

🔒
Segurança

2. Usuário Não-Root no Container

Containers rodando como root são uma vulnerabilidade crítica de escape. O processo do PHP-FPM deve rodar sob o usuário padrão www-data.

Segurança: Impede modificação de arquivos de sistema em caso de injeção de código.

🔄
Imutabilidade

3. Imagem Docker Autossuficiente

Nada de rodar composer install no servidor de produção. O build completo das dependências de produção é empacotado na imagem antes do deploy.

Benefício: O deploy na VPS leva segundos e é 100% determinístico.

🩺
Auto-Cura

4. Healthchecks & Restart Policy

O Docker monitora a integridade do serviço. Se um processo sofrer travamento ou vazamento de memória, o container é reiniciado automaticamente.

Política: restart: unless-stopped com verificação HTTP via rota /healthz.

📦 1. O Dockerfile de Produção para PHP 8.3

Veja a receita de um Dockerfile multi-stage enxuto, que instala apenas as extensões necessárias para produção e descarta ferramentas de desenvolvimento:

dockerfile
FROM php:8.3-fpm-alpine AS base

RUN apk add --no-cache 
    curl 
    libpng-dev 
    libzip-dev 
    zip 
    unzip 
    linux-headers 
    && docker-php-ext-install pdo pdo_mysql bcmath opcache zip

COPY --from=composer:2.7 /usr/bin/composer /usr/bin/composer

WORKDIR /var/www/html

RUN echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini 
    && echo "opcache.memory_consumption=256" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini 
    && echo "opcache.max_accelerated_files=20000" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini 
    && echo "opcache.validate_timestamps=0" >> /usr/local/etc/php/conf.d/docker-php-ext-opcache.ini

COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist

COPY . .
RUN composer dump-autoload --optimize --no-dev

RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

USER www-data
EXPOSE 9000
CMD ["php-fpm"]

🐳 2. O docker-compose.yml de Produção com Nginx

Para orquestrar o servidor web Nginx e o PHP-FPM na VPS de forma isolada e com política de reinício automático:

yaml
version: '3.8'

services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
    restart: unless-stopped
    environment:
      APP_ENV: production
      APP_DEBUG: 'false'
    healthcheck:
      test: ["CMD", "cgi-fcgi", "-bind", "-connect", "127.0.0.1:9000"]
      interval: 15s
      timeout: 5s
      retries: 3
    networks:
      - internal-net

  web:
    image: nginx:alpine
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
      - ./:/var/www/html:ro
      - ./certbot/conf:/etc/letsencrypt:ro
    depends_on:
      app:
        condition: service_healthy
    networks:
      - internal-net

networks:
  internal-net:
    driver: bridge

🚀 3. Esteira de CI/CD Completa com GitHub Actions

O segredo para nunca fazer deploy manual por FTP ou SSH inseguro é configurar uma esteira automatizada no GitHub. A cada push na branch main, a esteira roda os testes, compila a imagem Docker e aciona a atualização na sua VPS.

Crie o arquivo .github/workflows/deploy.yml:

yaml
name: Deploy em Produção

on:
  push:
    branches:
      - main

jobs:
  deploy:
    runs-on: ubuntu-latest

    steps:
      - name: Checkout do Código
        uses: actions/checkout@v4

      - name: Executar Deploy na VPS via SSH
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.VPS_HOST }}
          username: ${{ secrets.VPS_USER }}
          key: ${{ secrets.VPS_SSH_KEY }}
          port: 22
          script: |
            cd /var/www/minha-aplicacao
            git pull origin main
            docker compose build --no-cache app
            docker compose up -d --remove-orphans
            docker compose exec -T app php artisan config:cache
            docker compose exec -T app php artisan route:cache
            docker compose exec -T app php artisan view:cache
            docker compose exec -T app php artisan migrate --force
💡Dica Prática

Segredos no GitHub: Cadastre o IP da sua VPS (VPS_HOST), o usuário (VPS_USER) e a chave privada SSH (VPS_SSH_KEY) diretamente em Settings > Secrets and variables > Actions do seu repositório no GitHub para manter suas credenciais seguras.

🛡️ 4 Práticas para Garantir Zero Downtime Real

  1. Desacople o Banco de Dados: Mantenha o MySQL/PostgreSQL em um serviço gerenciado (como AWS RDS, Supabase ou Aiven) ou em uma VPS isolada com rotina diária de backup fora do host de aplicação.
  2. Use o Caddy se Quiser SSL Zero-Config: Se você não quiser configurar o Certbot manualmente no Nginx, o servidor web Caddy gera e renova certificados Let’s Encrypt automaticamente sem precisar de nenhum script cron.
  3. Execute Migrations com Cautela: Sempre crie migrações de banco retrocompatíveis (adicione colunas que aceitem nulo primeiro) para que os containers antigos continuem funcionando enquanto os novos estão subindo.
  4. Monitore Métricas da VPS: Configure um agente leve de monitoramento (como Zabbix ou Prometheus/Grafana) para acompanhar o uso de memória RAM e I/O de disco da sua máquina virtual.

❓ Perguntas Frequentes (FAQ)

Qual o tamanho de VPS ideal para começar com PHP e Docker?
Uma VPS básica com 2 vCPUs e 4 GB de RAM (custa cerca de 5 a 8 euros na Hetzner ou US$ 12 na DigitalOcean) aguenta tranquilamente centenas de requisições por segundo em uma aplicação PHP bem otimizada com OPcache ativo.

O que fazer se o deploy falhar no meio das migrations?
Tenha sempre backups automáticos do banco antes do deploy e configure a esteira do GitHub Actions para emitir alerta imediato no Telegram ou Slack se o step de artisan migrate retornar código de saída diferente de zero.

Gostou deste guia de infraestrutura moderna? Veja mais dicas práticas na nossa seção de DevOps e Servidores e confira os Cheatsheets para comandos de terminal e Docker.

Guilherme Nascimento ✓

Guilherme Nascimento

Especialista & Fundador

Especialista em Infraestrutura, Cloud/DevOps e Cibersegurança | +10 anos de experiência prática

Profissional com mais de uma década atuando no campo de batalha da tecnologia corporativa. Especialista em arquiteturas resilientes, automação com Docker/Kubernetes, Hardening de Active Directory, Linux avançado e observabilidade SRE. Criador do ecossistema Hora Nerd, dedicado a desmistificar a tecnologia para profissionais e estudantes.

Cloud & DevOps Active Directory Hardening Linux SysAdmin Docker & CI/CD Observabilidade SRE

Deixe seu comentário

Seu e-mail não será publicado. Campos obrigatórios estão marcados com *