PHP com Docker
LidoNesta aula, você aprenderá a usar Docker para desenvolver e executar aplicações PHP, focando na imagem PHP-FPM, no uso de docker-compose para orquestrar serviços, na configuração de volumes para persistência de dados e nas boas práticas para otimizar o ambiente. Ao final, você terá um ambiente de desenvolvimento PHP robusto e replicável.
O Docker revolucionou a forma como desenvolvemos e implantamos aplicações, e com PHP não é diferente. Nesta aula, você vai aprender a configurar um ambiente PHP profissional usando Docker, com foco na imagem PHP-FPM, que é a base para servidores web modernos como Nginx. Vamos explorar como o docker-compose simplifica a orquestração de múltiplos serviços, como volumes garantem a persistência e sincronização de arquivos, e quais boas práticas adotar para manter seu ambiente limpo, seguro e eficiente.
Se você já tem alguma familiaridade com Docker, esta aula vai aprofundar seu conhecimento em um cenário específico de PHP. Se é iniciante, não se preocupe: começaremos com uma visão geral e depois avançaremos para exemplos práticos que você pode aplicar imediatamente. Ao final, você terá um ambiente de desenvolvimento PHP containerizado, pronto para usar.
Imagem PHP-FPM
A imagem oficial do PHP no Docker Hub oferece várias variantes, e uma das mais importantes é a PHP-FPM (FastCGI Process Manager). O PHP-FPM é um daemon que gerencia processos PHP, permitindo que servidores web como Nginx ou Apache processem scripts PHP de forma eficiente. Em vez de embutir o PHP no servidor web, usamos o PHP-FPM como um serviço separado, o que melhora o desempenho e a escalabilidade.
No Docker, a imagem php:8.2-fpm (ou outra versão) já vem com o PHP-FPM configurado e pronto para executar. Mas você pode precisar de extensões adicionais, como pdo_mysql, mysqli, gd, entre outras. A imagem oficial é enxuta, e você deve instalar as extensões necessárias via Dockerfile ou usando um script de instalação. Vamos ver um exemplo de Dockerfile que estende a imagem PHP-FPM e adiciona algumas extensões comuns:
FROM php:8.2-fpm
RUN apt-get update && apt-get install -y \
libzip-dev \
libpng-dev \
libjpeg-dev \
libfreetype6-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql mysqli zip gdNeste Dockerfile, usamos os comandos docker-php-ext-configure e docker-php-ext-install que são fornecidos pela imagem oficial do PHP. Eles simplificam a instalação de extensões. Além disso, instalamos algumas bibliotecas do sistema necessárias para essas extensões. Ao construir uma imagem personalizada, você garante que seu ambiente tenha exatamente as extensões que sua aplicação precisa, sem comprometer o tamanho da imagem.
docker-compose (visão geral)
O docker-compose é uma ferramenta que permite definir e gerenciar múltiplos containers como uma única aplicação. Com um arquivo docker-compose.yml, você pode configurar serviços (como PHP-FPM, Nginx, MySQL), redes, volumes e outras opções de forma declarativa. Isso é fundamental para projetos PHP, pois normalmente precisamos de um servidor web, o PHP-FPM e um banco de dados.
Um exemplo típico de docker-compose.yml para um projeto PHP com Nginx e MySQL seria:
version: '3.8'
services:
php:
build: .
volumes:
- ./src:/var/www/html
networks:
- app-network
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
- ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
networks:
- app-network
db:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: myapp
volumes:
- db_data:/var/lib/mysql
networks:
- app-network
volumes:
db_data:
networks:
app-network:
driver: bridgeNeste arquivo, definimos três serviços: php (build a partir do Dockerfile), nginx (servindo a aplicação) e db (MySQL). O serviço php não expõe portas, pois é interno; o Nginx é quem recebe as requisições e as encaminha para o PHP-FPM via FastCGI. O volume ./src é montado em ambos os serviços para que o código seja compartilhado. O Nginx depende do PHP para funcionar, e o MySQL tem seu próprio volume para persistência de dados.
Volumes
Volumes são o mecanismo do Docker para persistir dados e compartilhar arquivos entre o host e os containers ou entre containers. No contexto PHP, usamos volumes para montar o código-fonte da aplicação dentro do container, permitindo que alterações no host sejam refletidas imediatamente (útil em desenvolvimento). Também usamos volumes para armazenar dados de banco de dados, logs ou arquivos de upload.
Existem dois tipos principais de montagem: bind mounts e named volumes. Um bind mount é quando você especifica um caminho do host, como ./src:/var/www/html. Isso é ótimo para desenvolvimento, pois você edita os arquivos no seu editor e o container vê as mudanças. Um named volume é gerenciado pelo Docker e é ideal para dados que precisam persistir, como o banco de dados. No exemplo anterior, db_data é um named volume.
Em ambientes de produção, você deve ter cuidado com volumes: não monte o código-fonte como bind mount, pois isso pode reduzir a portabilidade e a segurança. Em vez disso, copie o código para a imagem no build. No desenvolvimento, o bind mount é essencial para produtividade.
Boas práticas
Ao usar Docker com PHP, siga estas boas práticas para garantir um ambiente eficiente e seguro:
- Use imagens oficiais e específicas: prefira
php:8.2-fpmem vez de tagslatestpara garantir consistência. - Instale apenas as extensões necessárias: isso reduz o tamanho da imagem e a superfície de ataque.
- Não rode o container como root: crie um usuário com permissões restritas no Dockerfile.
- Use .dockerignore: para evitar copiar arquivos desnecessários (como .git, node_modules) para a imagem.
- Separe ambientes: use arquivos docker-compose diferentes para dev e prod (ex.: docker-compose.override.yml).
- Gerencie variáveis de ambiente: use arquivos .env e referencie no docker-compose.
Um exemplo de Dockerfile com usuário não-root:
FROM php:8.2-fpm
# ... instalação de extensões ...
RUN useradd -m -u 1000 -s /bin/bash developer
USER developer
WORKDIR /var/www/htmlLembre-se de que o Nginx precisa acessar os arquivos, então o usuário do PHP-FPM deve ter permissão de leitura. Em muitos casos, você pode usar o mesmo UID do usuário do host para evitar problemas de permissão.
Referências
- Imagem oficial do PHP no Docker Hub
- Documentação oficial do Docker Compose
- Documentação sobre volumes no Docker
- Manual do PHP-FPM
- Boas práticas de desenvolvimento com Docker
- Documentação oficial do Nginx
Exercícios
- Crie um Dockerfile que estenda a imagem
php:8.1-fpme instale as extensõespdo_mysqleredis. Explique os comandos usados.✓ Resposta:
O comandoFROM php:8.1-fpm RUN apt-get update && apt-get install -y libzip-dev \ && docker-php-ext-install pdo_mysql \ && pecl install redis && docker-php-ext-enable redisdocker-php-ext-installinstala a extensão pdo_mysql. Para redis, usamos o PECL para compilar e instalar, e depois habilitamos comdocker-php-ext-enable. - Escreva um arquivo
docker-compose.ymlque defina os serviçosphp(build local) enginx(imagem nginx:alpine) com um volume compartilhado para o código em./app. O Nginx deve expor a porta 8080.✓ Resposta:version: '3.8' services: php: build: . volumes: - ./app:/var/www/html nginx: image: nginx:alpine ports: - "8080:80" volumes: - ./app:/var/www/html - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - php - Explique a diferença entre bind mount e named volume e dê um exemplo de uso para cada um em um projeto PHP.✓ Resposta: Bind mount é uma montagem de um diretório do host no container, como
./src:/var/www/html. É útil em desenvolvimento para sincronizar código. Named volume é um volume gerenciado pelo Docker, comodb_data, usado para persistir dados do banco de dados, independente do ciclo de vida do container. - Quais são pelo menos três boas práticas ao construir imagens Docker para PHP? Justifique cada uma.✓ Resposta: 1) Usar tags específicas de imagem (ex.: php:8.2-fpm) para reprodutibilidade. 2) Instalar apenas extensões necessárias para reduzir o tamanho e vulnerabilidades. 3) Executar o container como usuário não-root para segurança. 4) Usar .dockerignore para evitar copiar arquivos desnecessários.
- Monte um ambiente docker-compose completo com PHP-FPM, Nginx e MySQL, incluindo volumes para o código e para o banco. Escreva o arquivo docker-compose.yml e explique a função de cada serviço.✓ Resposta:
O serviçoversion: '3.8' services: php: build: . volumes: - ./src:/var/www/html networks: - app-net nginx: image: nginx:alpine ports: - "8080:80" volumes: - ./src:/var/www/html - ./nginx.conf:/etc/nginx/conf.d/default.conf depends_on: - php networks: - app-net db: image: mysql:8.0 environment: MYSQL_ROOT_PASSWORD: root MYSQL_DATABASE: myapp volumes: - db_data:/var/lib/mysql networks: - app-net volumes: db_data: networks: app-net:phpexecuta o PHP-FPM e monta o código. Onginxrecebe as requisições HTTP e as encaminha para o PHP. Odbfornece o MySQL com persistência em volume.
Observações finais
Dominar Docker com PHP é uma habilidade essencial para o desenvolvimento moderno. Nesta aula, você aprendeu a configurar a imagem PHP-FPM, a orquestrar serviços com docker-compose, a usar volumes para persistência e a aplicar boas práticas. Agora, pratique criando um ambiente completo para um projeto real, experimente adicionar serviços como Redis ou Mailhog, e explore como o Docker pode melhorar seu fluxo de trabalho.