# PHP in containers draaien

> PHP in een container draaien: imagevarianten, productie-php.ini, extensies, geheugengrenzen, logs en updates. Met voorbeelden en het verband met PHP2Shell.

Bron: https://phpsos.de/nl/php/php-in-containern/  
Stand: 25-10-2026  
Aanbieder: PHP SOS, PHP-noodhulp en serverbeveiliging. Directe hulp via WhatsApp: https://wa.me/491736494914?text=Hallo%20PHP%20SOS%2C%20wij%20hebben%20hulp%20nodig%20met%20onze%20PHP-server.%20Bedrijf%3A%20%E2%80%A6%20Website%3A%20%E2%80%A6

**Kort gezegd:** Om PHP in containers te draaien kiest u de passende variant van het officiële image (`fpm`, `apache` of `cli`), activeert u de productie-php.ini, installeert u alleen benodigde extensies en stelt u geheugen- en procesgrenzen in die bij elkaar passen. Containers zijn onveranderlijk: een PHP-beveiligingsupdate zoals die voor PHP2Shell werkt pas wanneer het image opnieuw is gebouwd en elke container opnieuw is gestart. Deze nieuwbouw hoort daarom als vast proces bij elk containerbedrijf.

## Waarom PHP in containers?

Containers verpakken PHP, extensies en configuratie in een image dat op elke server hetzelfde draait. Voor bedrijven betekent dat: minder verrassingen tussen test en productie, snellere herstelling en duidelijke versiestanden. Voor de beveiliging betekent het echter ook een nieuwe plicht: in een container voert niemand automatisch updates door.

Deze pagina behandelt het lopende bedrijf. Hoe u bestaande containers concreet tegen PHP2Shell patcht, staat onder [PHP in Docker-containers patchen](https://phpsos.de/nl/php2shell/docker-container-patchen/).

## De juiste imagevariant kiezen

| Variant | Inhoud | Typische toepassing |
|---|---|---|
| `php:<version>-fpm` | PHP-FPM, heeft een voorgeschakelde webserver nodig | productie met Nginx, Caddy of een ingress |
| `php:<version>-apache` | Apache met mod_php, standaard mpm_prefork | eenvoudige opbouw, oudere toepassingen |
| `php:<version>-cli` | opdrachtregel, bevat als enige variant ook php-cgi | cronjobs, queue-workers, buildstappen |
| `…-alpine` | op Alpine Linux met musl | kleine images, bij sommige extensies aanpassingen nodig |
| `…-bookworm`, `…-trixie` | op de genoemde Debian-versie | vaste basis voor reproduceerbare builds |

Voor nieuwe projecten verdient in de regel de `fpm`-variant met een gescheiden webservercontainer de voorkeur. Bij mod_php ziet het PHP-team in verband met PHP2Shell het hoogste risico; wie het `apache`-image gebruikt, draait precies deze bedrijfsmodus.

## Een productie-image bouwen

Een slank voorbeeld voor een toepassing met MySQL-toegang:

```dockerfile
FROM php:8.4-fpm-alpine

# Productieconfiguratie activeren (volgens de imagedoc dringend aanbevolen)
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Alleen benodigde extensies
RUN docker-php-ext-install -j"$(nproc)" pdo_mysql

# Eigen instellingen
COPY zz-sicherheit.ini "$PHP_INI_DIR/conf.d/"

# De code is van root; de FPM-workers draaien als www-data en kunnen hem alleen lezen
COPY . /var/www/html
```

De hulpscripts van het image nemen het bouwen van extensies over: `docker-php-ext-configure` voor opties, `docker-php-ext-install` om te bouwen, `docker-php-ext-enable` om te activeren, bijvoorbeeld na `pecl install`. Wordt met `docker-php-source` de broncode uitgepakt, dan moet die volgens de doc in dezelfde laag weer worden verwijderd. Het bestand `zz-sicherheit.ini` kan er zo uitzien:

```ini
expose_php = Off
display_errors = Off
log_errors = On
session.use_strict_mode = 1
session.cookie_httponly = 1
```

Twee verdere uitgangspunten maken images robuuster. Ten eerste bevat het uitgeleverde image alleen wat tijdens de uitvoering nodig is; compilers, pakketcaches en testbestanden horen in een eigen buildfase. Ten tweede mag de gebruiker onder wie PHP draait alleen schrijven waar het nodig is, bijvoorbeeld in upload- of cachemappen op gekoppelde volumes. Veel teams draaien de container bovendien met een tegen schrijven beveiligd bestandssysteem. Een binnengesmokkeld PHP-bestand heeft het dan aanzienlijk moeilijker om blijvend te zijn, en elke herstart herstelt de schone staat van het image. Dat vervangt geen onderzoek na een incident, maar verkleint het aanvalsoppervlak merkbaar.

## Processen, geheugen en logs in de container

Drie afstelschroeven bepalen of een PHP-container stabiel draait.

1. **Aantal workers:** `pm.max_children` in de FPM-pool bepaalt hoeveel verzoeken gelijktijdig worden afgehandeld. Elke worker kan tot `memory_limit` in beslag nemen.
2. **Geheugengrens van de container:** Ze begrenst alle processen samen. Als vuistregel geldt: aantal workers maal geheugen per worker plus reserve moet onder de limiet passen, anders beëindigt het systeem processen.
3. **Logs:** Containers schrijven logs naar de standaarduitvoer. In PHP-FPM stuurt `catch_workers_output = yes` uitvoer van de workers naar het hoofdlog; zonder de instelling verdwijnt die volgens de handleiding in het niets.

Nuttig is bovendien `request_terminate_timeout`, dat afzonderlijke verzoeken na een tijdsduur beëindigt wanneer `max_execution_time` niet ingrijpt. Hoe u containers in het cluster beheert, beschrijft [PHP in Kubernetes patchen](https://phpsos.de/nl/server/kubernetes/).

## Containers en beveiliging: wat PHP2Shell heeft getoond

Bij PHP2Shell spelen containers een dubbele rol. Enerzijds zijn ze een hulp: php.net adviseert als overgangsmaatregel bij CVE-2026-109618 `memory_limit=-1` te combineren met een geheugengrens via container of cgroup, bij voorkeur zo dat alleen de getroffen worker wordt beëindigd. `RLIMIT_AS` en `RLIMIT_DATA` zijn daarvoor volgens php.net ongeschikt. Deze maatregel is geen volledige bescherming en vervangt de update niet.

Anderzijds zijn containers een valkuil wanneer images niet opnieuw worden gebouwd. Een image met PHP 8.4.26 blijft kwetsbaar, hoe vaak de container ook opnieuw start. Pas een nieuwbouw naar 8.4.27 of nieuwer en de vervanging van alle draaiende containers dichten het lek. De stand laat zich direct in de draaiende container controleren:

```bash
docker exec <container> php -v
docker exec <container> php-fpm -v
docker exec <container> php -r 'var_dump(ini_get("memory_hard_limit_percent"));'
```

Levert de laatste opdracht `bool(false)` op, dan kent PHP de met de fix-versies ingevoerde directive niet; volgens de handleiding is de versie dan getroffen. Blijvend helpt alleen een automatische nieuwbouw, zoals beschreven onder [CI/CD: PHP-images automatisch opnieuw bouwen](https://phpsos.de/nl/blog/php-images-in-ci-neu-bauen/).

> **Tip:**
> Leg in het Dockerfile de exacte PHP-versie in de tag vast en verhoog haar bewust. Zo is in de code te herleiden wanneer welke versie is uitgerold.

## Hoe helpt PHP SOS concreet?

Bij de [serverhardening voor PHP-webservers](https://phpsos.de/nl/leistungen/server-haertung/) zorgen wij ook voor containers:

- **Images controleren:** Basisimage, PHP-versie, extensies en configuratie van elk image.
- **Configuratie harden:** Productie-ini, slanke extensielijst, passende worker- en geheugengrenzen.
- **Nieuwbouw inrichten:** Een verloop dat images bij nieuwe PHP-releases opnieuw bouwt en uitrolt.
- **Looptijd controleren:** Wij tonen aan dat in elke draaiende container de gecorrigeerde versie draait.


## Veelgestelde vragen

**Welke variant van het PHP-image is de juiste?**  
Voor Nginx of een andere proxy de fpm-variant, voor een eenvoudige opbouw met Apache de apache-variant, voor scripts en cronjobs de cli-variant. Alpine-varianten zijn kleiner, maar gebaseerd op musl in plaats van glibc, wat bij sommige extensies opvalt.

**Wordt PHP in de container automatisch bijgewerkt?**  
Nee. Een draaiende container verandert niet. U moet het image met de nieuwe PHP-versie opnieuw bouwen en de containers opnieuw starten. Pas dan draait de gecorrigeerde versie.

**Hoe verhouden memory_limit en de containerlimiet zich?**  
memory_limit begrenst elk afzonderlijk PHP-verzoek, de containerlimiet de hele container. Beide moeten bij elkaar passen: het aantal workers maal het geheugen per worker moet onder de containerlimiet liggen.

**Heb ik in containers een php.ini nodig?**  
Ja. De officiële images leveren php.ini-development en php.ini-production als sjablonen mee. Voor productie adviseert de imagedocumentatie uitdrukkelijk het productiesjabloon; eigen instellingen komen in conf.d.

## Bronnen

- [Docker Official Image: PHP](https://hub.docker.com/_/php)
- [PHP-handleiding: FPM-configuratie](https://www.php.net/manual/en/install.fpm.configuration.php)
- [php.net: beveiligingsmelding van 21 oktober 2026](https://www.php.net/)
