Docker e PHP: conteinerização de aplicações em nível avançado
A conteinerização de aplicações PHP com Docker há muito deixou de ser apenas uma ferramenta conveniente para desenvolvimento. Em nível avançado, é a chave para criar ambientes escaláveis, seguros e reproduzíveis. Neste artigo, abordaremos técnicas que ajudarão você a passar da execução básica de um contêiner PHP para a orquestração profissional: multi-stage build, otimização de imagens, trabalho com Docker Compose para arquitetura de microsserviços e cache avançado.
1. Multi-stage build: imagem final mínima
Um dos principais problemas das imagens Docker padrão é o tamanho. A imagem base php:8.2-apache pesa mais de 400 MB e, com a instalação de extensões, chega a 600+. Para produção, isso é inaceitável: uma imagem grande carrega mais lentamente, ocupa espaço no registry e aumenta a superfície de ataque.
O multi-stage build permite dividir o processo em etapas: uma para compilação e instalação de dependências (com conjunto completo de ferramentas), e outra para o runtime mínimo. A imagem final contém apenas os artefatos compilados e as bibliotecas necessárias.
Exemplo de Dockerfile para uma aplicação Laravel:
# Etapa 1: Compilação e instalação de dependênciasFROM composer:latest AS vendorWORKDIR /appCOPY composer.json composer.lock ./RUN composer install --no-dev --optimize-autoloader --no-interaction
# Etapa 2: Compilação de recursos Node (se houver frontend)FROM node:18-alpine AS frontendWORKDIR /appCOPY package.json package-lock.json ./RUN npm ci --productionCOPY resources/ ./resources/RUN npm run production
# Etapa 3: Imagem PHP finalFROM php:8.2-fpm-alpine AS productionRUN docker-php-ext-install pdo_mysql opcacheCOPY --from=vendor /app/vendor /var/www/html/vendorCOPY --from=frontend /app/public/build /var/www/html/public/buildCOPY . /var/www/html
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cacheEXPOSE 9000CMD ["php-fpm"]Essa abordagem reduz o tamanho da imagem de 500+ MB para ~120 MB. composer:latest e node:18-alpine são usados apenas nas etapas de build e não entram na camada final.
2. Otimização do cache de camadas do Docker
Cada instrução no Dockerfile cria uma camada. Para acelerar rebuilds, é necessário posicionar as camadas que raramente mudam o mais cedo possível. Para um projeto PHP, isso significa:
- Copiar
composer.jsonecomposer.lockantes de copiar o código. - Executar
composer installantes de copiar os fontes. - Copiar o código por último.
Exemplo de ordem otimizada de instruções:
FROM php:8.2-fpm-alpine AS baseWORKDIR /var/www/html
# Instalamos dependências do sistema uma vezRUN apk add --no-cache $PHPIZE_DEPS \ && docker-php-ext-install pdo_mysql opcache bcmath
# Copiamos apenas os arquivos de dependênciasCOPY composer.json composer.lock ./RUN composer install --no-dev --no-interaction --no-scripts --prefer-dist
# Copiamos o restante do códigoCOPY . .
# Geramos autoload e otimizamosRUN composer dump-autoload --optimizeDica: use .dockerignore para excluir vendor, .git, node_modules e outros arquivos temporários do contexto de build. Isso acelera a transferência do contexto para o daemon do Docker.
3. Docker Compose para arquitetura de microsserviços
Aplicações PHP modernas raramente consistem em um único serviço. Uma arquitetura típica inclui PHP-FPM, Nginx, Redis, fila de tarefas (RabbitMQ/Beanstalkd) e banco de dados. O Docker Compose permite descrever toda a infraestrutura em um único docker-compose.yml.
Exemplo de configuração para um microsserviço em PHP:
version: '3.8'services: app: build: context: . target: production