Em resumo: Para operar PHP em contentores, escolha a variante adequada da imagem oficial (fpm, apache ou cli), ative o php.ini de produção, instale apenas as extensões necessárias e defina limites de memória e de processos que sejam coerentes entre si. Os contentores são imutáveis: uma atualização de segurança do PHP, como a do PHP2Shell, só produz efeito quando a imagem é reconstruída e cada contentor reiniciado. Esta reconstrução pertence, por isso, como processo fixo, a qualquer operação com contentores.
Porquê PHP em contentores?
Os contentores empacotam o PHP, as extensões e a configuração numa imagem que corre da mesma forma em qualquer servidor. Para as empresas, isto significa: menos surpresas entre teste e produção, recuperação mais rápida e estados de versão claros. Para a segurança significa, porém, também um novo dever: ninguém aplica automaticamente atualizações dentro de um contentor.
Esta página trata da operação corrente. Como aplicar concretamente o patch do PHP2Shell a contentores existentes está em Aplicar o patch do PHP em contentores Docker.
Escolher a variante de imagem certa
| Variante | Conteúdo | Utilização típica |
|---|---|---|
php:<version>-fpm |
PHP-FPM, precisa de um servidor web à frente | produção com Nginx, Caddy ou um ingress |
php:<version>-apache |
Apache com mod_php, por predefinição mpm_prefork | estruturas simples, aplicações mais antigas |
php:<version>-cli |
linha de comandos, é a única variante que contém também o php-cgi | cronjobs, queue workers, passos de build |
…-alpine |
em Alpine Linux com musl | imagens pequenas, em algumas extensões são necessários ajustes |
…-bookworm, …-trixie |
na versão Debian indicada | base fixa para builds reproduzíveis |
Para projetos novos recomenda-se, em regra, a variante fpm com um contentor de servidor web separado. No mod_php, a equipa do PHP vê, no contexto do PHP2Shell, o risco mais elevado; quem usa a imagem apache opera precisamente esse modo de operação.
Construir uma imagem de produção
Um exemplo enxuto para uma aplicação com acesso MySQL:
FROM php:8.4-fpm-alpine
# Ativar a configuração de produção (muito recomendado pela documentação da imagem)
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
# Apenas as extensões necessárias
RUN docker-php-ext-install -j"$(nproc)" pdo_mysql
# Definições próprias
COPY zz-sicherheit.ini "$PHP_INI_DIR/conf.d/"
# O código pertence ao root; os workers FPM correm como www-data e só o podem ler
COPY . /var/www/html
Os scripts auxiliares da imagem tratam da construção das extensões: docker-php-ext-configure para opções, docker-php-ext-install para construir, docker-php-ext-enable para ativar, por exemplo após pecl install. Se o código-fonte for extraído com docker-php-source, deve, segundo a documentação, ser apagado de novo na mesma camada. O ficheiro zz-sicherheit.ini poderia ter este aspeto:
expose_php = Off
display_errors = Off
log_errors = On
session.use_strict_mode = 1
session.cookie_httponly = 1
Dois outros princípios tornam as imagens mais robustas. Primeiro, a imagem entregue contém apenas o que é preciso em tempo de execução; compiladores, caches de pacotes e ficheiros de teste pertencem a uma fase de build própria. Segundo, o utilizador com que o PHP corre só pode escrever onde é necessário, por exemplo em diretórios de uploads ou de cache em volumes montados. Muitas equipas operam além disso o contentor com o sistema de ficheiros protegido contra escrita. Um ficheiro PHP introduzido tem então muito mais dificuldade em permanecer, e cada reinício repõe o estado limpo da imagem. Isto não substitui uma investigação após um incidente, mas reduz sensivelmente a superfície de ataque.
Processos, memória e registos no contentor
Três parâmetros determinam se um contentor PHP corre de forma estável.
- Número de workers: o
pm.max_childrenno pool FPM define quantos pedidos são tratados em simultâneo. Cada worker pode ocupar até aomemory_limit. - Limite de memória do contentor: limita todos os processos em conjunto. Como regra aproximada: o número de workers vezes a memória por worker, mais uma reserva, tem de caber abaixo do limite, caso contrário o sistema termina processos.
- Registos: os contentores escrevem registos na saída padrão. No PHP-FPM,
catch_workers_output = yesencaminha as saídas dos workers para o registo principal; sem esta definição perdem-se, segundo o manual, no vazio.
É ainda útil o request_terminate_timeout, que termina pedidos individuais após um período, quando o max_execution_time não atua. Como operar contentores no cluster descreve-o Aplicar o patch do PHP no Kubernetes.
Contentores e segurança: o que o PHP2Shell mostrou
No PHP2Shell, os contentores desempenham um papel duplo. Por um lado, são uma ajuda: o php.net recomenda, como medida provisória para a CVE-2026-109618, combinar memory_limit=-1 com um limite de memória por contentor ou cgroup, idealmente de modo a que apenas o worker afetado seja terminado. RLIMIT_AS e RLIMIT_DATA não são adequados para isso, segundo o php.net. Esta medida não é uma proteção completa e não substitui a atualização.
Por outro lado, os contentores são uma armadilha quando as imagens não são reconstruídas. Uma imagem com o PHP 8.4.26 continua vulnerável, por mais vezes que o contentor reinicie. Só uma reconstrução para o 8.4.27 ou posterior e a substituição de todos os contentores em execução fecham a vulnerabilidade. O estado pode ser verificado diretamente no contentor em execução:
docker exec <container> php -v
docker exec <container> php-fpm -v
docker exec <container> php -r 'var_dump(ini_get("memory_hard_limit_percent"));'
Se o último comando devolver bool(false), o PHP não conhece a diretiva introduzida com as versões corrigidas; segundo o manual, a versão está então afetada. A longo prazo, só ajuda uma reconstrução automática, como descrito em CI/CD: reconstruir imagens PHP automaticamente.
Defina no Dockerfile a versão exata do PHP na tag e aumente-a de forma deliberada. Assim, fica rastreável no código quando foi distribuída cada versão.
Como ajuda concretamente o PHP SOS?
No hardening de servidores web PHP, tratamos também dos contentores:
- Verificar imagens: imagem base, versão do PHP, extensões e configuração de cada imagem.
- Reforçar a configuração: ini de produção, lista de extensões enxuta, limites de workers e de memória adequados.
- Configurar a reconstrução: um processo que reconstrói e distribui as imagens a cada nova versão do PHP.
- Controlar o tempo de execução: comprovamos que em cada contentor em execução corre a versão corrigida.
Perguntas frequentes
Que variante da imagem PHP é a certa?
Para o Nginx ou outro proxy, a variante fpm; para uma estrutura simples com Apache, a variante apache; para scripts e cronjobs, a variante cli. As variantes Alpine são mais pequenas, mas assentam em musl em vez de glibc, o que se nota em algumas extensões.
O PHP em contentores é atualizado automaticamente?
Não. Um contentor em execução não muda. Tem de reconstruir a imagem com a nova versão do PHP e reiniciar os contentores. Só então corre a versão corrigida.
Como se relacionam o memory_limit e o limite do contentor?
O memory_limit limita cada pedido PHP individual, o limite do contentor limita o contentor inteiro. Ambos têm de ser coerentes: o número de workers vezes a memória por worker deve ficar abaixo do limite do contentor.
Preciso de um php.ini em contentores?
Sim. As imagens oficiais trazem o php.ini-development e o php.ini-production como modelos. Para produção, a documentação da imagem recomenda expressamente o modelo de produção; as definições próprias vão para o conf.d.