# Eksploatacja PHP w kontenerach

> PHP w kontenerze: warianty obrazów, produkcyjne php.ini, rozszerzenia, limity pamięci, logi i aktualizacje. Z przykładami i związkiem z PHP2Shell.

Źródło: https://phpsos.de/pl/php/php-in-containern/  
Stan: 25.10.2026  
Dostawca: PHP SOS, Pomoc awaryjna PHP i bezpieczeństwo serwerów. Natychmiastowa pomoc przez WhatsApp: https://wa.me/491736494914?text=Dzie%C5%84%20dobry%2C%20PHP%20SOS%2C%20potrzebujemy%20pomocy%20z%20naszym%20serwerem%20PHP.%20Firma%3A%20%E2%80%A6%20Strona%20internetowa%3A%20%E2%80%A6

**Krótko:** Aby uruchamiać PHP w kontenerach, wybierają Państwo odpowiedni wariant oficjalnego obrazu (`fpm`, `apache` lub `cli`), aktywują produkcyjne php.ini, instalują tylko potrzebne rozszerzenia i ustawiają limity pamięci i procesów, które do siebie pasują. Kontenery są niezmienne: aktualizacja bezpieczeństwa PHP, taka jak ta dotycząca PHP2Shell, działa dopiero wtedy, gdy obraz zostanie zbudowany od nowa, a każdy kontener zrestartowany. Ta przebudowa należy więc jako stały proces do każdej eksploatacji kontenerów.

## Dlaczego PHP w kontenerach?

Kontenery pakują PHP, rozszerzenia i konfigurację w obraz, który działa tak samo na każdym serwerze. Dla firm oznacza to: mniej niespodzianek między testem a produkcją, szybsze odtwarzanie i jasne stany wersji. Dla bezpieczeństwa oznacza to jednak także nowy obowiązek: w kontenerze nikt nie instaluje aktualizacji automatycznie.

Ta strona omawia bieżącą eksploatację. Jak konkretnie załatać istniejące kontenery przeciw PHP2Shell, opisuje artykuł [Poprawianie PHP w kontenerach Dockera](https://phpsos.de/pl/php2shell/docker-container-patchen/).

## Wybór właściwego wariantu obrazu

| Wariant | Zawartość | Typowe zastosowanie |
|---|---|---|
| `php:<version>-fpm` | PHP-FPM, wymaga serwera WWW z przodu | produkcja z Nginx, Caddy lub ingressem |
| `php:<version>-apache` | Apache z mod_php, domyślnie mpm_prefork | proste układy, starsze aplikacje |
| `php:<version>-cli` | wiersz poleceń, jako jedyny wariant zawiera też php-cgi | zadania cron, workery kolejek, kroki budowania |
| `…-alpine` | na Alpine Linux z musl | małe obrazy, przy niektórych rozszerzeniach potrzebne dostosowania |
| `…-bookworm`, `…-trixie` | na podanej wersji Debiana | stała baza dla powtarzalnych buildów |

Dla nowych projektów zwykle zaleca się wariant `fpm` z osobnym kontenerem serwera WWW. Przy mod_php zespół PHP widzi w związku z PHP2Shell najwyższe ryzyko; kto używa obrazu `apache`, prowadzi właśnie ten tryb pracy.

## Budowanie obrazu produkcyjnego

Odchudzony przykład aplikacji z dostępem do MySQL:

```dockerfile
FROM php:8.4-fpm-alpine

# Aktywować konfigurację produkcyjną (według dokumentacji obrazu gorąco zalecane)
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Tylko potrzebne rozszerzenia
RUN docker-php-ext-install -j"$(nproc)" pdo_mysql

# Własne ustawienia
COPY zz-sicherheit.ini "$PHP_INI_DIR/conf.d/"

# Kod należy do roota; workery FPM działają jako www-data i mogą go tylko czytać
COPY . /var/www/html
```

Skrypty pomocnicze obrazu przejmują budowanie rozszerzeń: `docker-php-ext-configure` dla opcji, `docker-php-ext-install` do budowania, `docker-php-ext-enable` do aktywacji, na przykład po `pecl install`. Jeśli za pomocą `docker-php-source` rozpakowuje się kod źródłowy, według dokumentacji należy go usunąć w tej samej warstwie. Plik `zz-sicherheit.ini` mógłby wyglądać tak:

```ini
expose_php = Off
display_errors = Off
log_errors = On
session.use_strict_mode = 1
session.cookie_httponly = 1
```

Dwie dalsze zasady czynią obrazy odporniejszymi. Po pierwsze, dostarczany obraz zawiera tylko to, co potrzebne w czasie działania; kompilatory, pamięci podręczne pakietów i pliki testowe należą do osobnego etapu budowania. Po drugie, użytkownik, pod którym działa PHP, może zapisywać tylko tam, gdzie to konieczne, na przykład w katalogach przesyłanych plików lub cache na podłączonych woluminach. Wiele zespołów dodatkowo prowadzi kontener z systemem plików chronionym przed zapisem. Wprowadzonemu plikowi PHP jest wtedy wyraźnie trudniej pozostać na stałe, a każdy restart przywraca czysty stan obrazu. Nie zastępuje to badania po incydencie, ale wyraźnie zmniejsza powierzchnię ataku.

## Procesy, pamięć i logi w kontenerze

Trzy pokrętła decydują o tym, czy kontener PHP działa stabilnie.

1. **Liczba workerów:** `pm.max_children` w puli FPM określa, ile żądań obsługiwanych jest jednocześnie. Każdy worker może zająć do `memory_limit`.
2. **Limit pamięci kontenera:** Ogranicza wszystkie procesy razem. Zgrubna reguła: liczba workerów razy pamięć na workera plus rezerwa musi mieścić się poniżej limitu, w przeciwnym razie system kończy procesy.
3. **Logi:** Kontenery zapisują logi na standardowe wyjście. W PHP-FPM `catch_workers_output = yes` kieruje wyjście workerów do logu głównego; bez tego ustawienia według podręcznika ginie ono w próżni.

Pomocne jest ponadto `request_terminate_timeout`, które kończy pojedyncze żądania po określonym czasie, gdy `max_execution_time` nie działa. Jak prowadzić kontenery w klastrze, opisuje artykuł [Poprawianie PHP w Kubernetes](https://phpsos.de/pl/server/kubernetes/).

## Kontenery a bezpieczeństwo: czego nauczyło PHP2Shell

W PHP2Shell kontenery odgrywają podwójną rolę. Z jednej strony są pomocą: php.net zaleca jako środek przejściowy dla CVE-2026-109618 połączenie `memory_limit=-1` z limitem pamięci przez kontener lub cgroup, najlepiej tak, aby kończony był tylko dotknięty worker. `RLIMIT_AS` i `RLIMIT_DATA` są do tego według php.net nieodpowiednie. Ten środek nie jest pełną ochroną i nie zastępuje aktualizacji.

Z drugiej strony kontenery są pułapką, jeśli obrazy nie są budowane od nowa. Obraz z PHP 8.4.26 pozostaje podatny, bez względu na to, jak często kontener jest restartowany. Dopiero przebudowa na 8.4.27 lub nowszą i wymiana wszystkich działających kontenerów zamykają lukę. Stan można skontrolować bezpośrednio w działającym kontenerze:

```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"));'
```

Jeśli ostatnie polecenie zwraca `bool(false)`, PHP nie zna dyrektywy wprowadzonej w wersjach z poprawką; według podręcznika wersja jest wtedy dotknięta. Trwale pomaga tylko automatyczna przebudowa, jak opisano w artykule [CI/CD: automatyczna przebudowa obrazów PHP](https://phpsos.de/pl/blog/php-images-in-ci-neu-bauen/).

> **Wskazówka:**
> Proszę ustalić w Dockerfile dokładną wersję PHP w tagu i podnosić ją świadomie. Dzięki temu w kodzie widać, kiedy jaka wersja została wdrożona.

## Jak konkretnie pomaga PHP SOS?

W ramach [utwardzania serwerów WWW z PHP](https://phpsos.de/pl/leistungen/server-haertung/) zajmujemy się także kontenerami:

- **Sprawdzenie obrazów:** Obraz bazowy, wersja PHP, rozszerzenia i konfiguracja każdego obrazu.
- **Utwardzenie konfiguracji:** Produkcyjne ini, odchudzona lista rozszerzeń, odpowiednie limity workerów i pamięci.
- **Ustawienie przebudowy:** Proces, który buduje od nowa i wdraża obrazy przy nowych wydaniach PHP.
- **Kontrola środowiska uruchomieniowego:** Dowodzimy, że w każdym działającym kontenerze działa poprawiona wersja.


## Częste pytania

**Który wariant obrazu PHP jest właściwy?**  
Dla Nginx lub innego proxy wariant fpm, dla prostej budowy z Apache wariant apache, dla skryptów i zadań cron wariant cli. Warianty Alpine są mniejsze, ale opierają się na musl zamiast glibc, co przy niektórych rozszerzeniach bywa zauważalne.

**Czy PHP w kontenerze jest aktualizowane automatycznie?**  
Nie. Działający kontener się nie zmienia. Trzeba zbudować obraz od nowa z nową wersją PHP i zrestartować kontenery. Dopiero wtedy działa poprawiona wersja.

**Jak mają się do siebie memory_limit i limit kontenera?**  
memory_limit ogranicza każde pojedyncze żądanie PHP, a limit kontenera cały kontener. Oba muszą do siebie pasować: liczba workerów razy pamięć na workera powinna być poniżej limitu kontenera.

**Czy w kontenerach potrzebuję php.ini?**  
Tak. Oficjalne obrazy dostarczają php.ini-development i php.ini-production jako szablony. Dla produkcji dokumentacja obrazu wyraźnie zaleca szablon produkcyjny; własne ustawienia trafiają do conf.d.

## Źródła

- [Docker Official Image: PHP](https://hub.docker.com/_/php)
- [Podręcznik PHP: konfiguracja FPM](https://www.php.net/manual/en/install.fpm.configuration.php)
- [php.net: komunikat o bezpieczeństwie z 21.10.2026](https://www.php.net/)
