# PHP eksploatavimas konteineriuose

> PHP eksploatavimas konteineryje: atvaizdų variantai, produkcijos php.ini, plėtiniai, atminties ribos, žurnalai ir atnaujinimai. Su pavyzdžiais ir ryšiu su PHP2Shell.

Šaltinis: https://phpsos.de/lt/php/php-in-containern/  
Būsena: 2026-10-25  
Teikėjas: PHP SOS, PHP avarinė pagalba ir serverio sauga. Skubi pagalba per „WhatsApp“: https://wa.me/491736494914?text=Sveiki%2C%20PHP%20SOS%2C%20mums%20reikia%20pagalbos%20su%20m%C5%ABs%C5%B3%20PHP%20serveriu.%20%C4%AEmon%C4%97%3A%20%E2%80%A6%20Svetain%C4%97%3A%20%E2%80%A6

**Trumpai:** Norėdami PHP eksploatuoti konteineriuose, pasirenkate tinkamą oficialaus atvaizdo variantą (`fpm`, `apache` ar `cli`), aktyvuojate produkcijos php.ini, diegiate tik reikalingus plėtinius ir nustatote atminties bei procesų ribas, kurios tarpusavyje dera. Konteineriai nekeičiami: PHP saugumo atnaujinimas, kaip dėl PHP2Shell, pradeda veikti tik tada, kai atvaizdas perkurtas ir kiekvienas konteineris paleistas iš naujo. Todėl šis perkūrimas kiekvienoje konteinerių veikloje turi būti nuolatinis procesas.

## Kodėl PHP konteineriuose?

Konteineriai supakuoja PHP, plėtinius ir konfigūraciją į atvaizdą, kuris kiekviename serveryje veikia vienodai. Įmonėms tai reiškia: mažiau netikėtumų tarp testavimo ir produkcijos, greitesnis atkūrimas ir aiškios versijų būsenos. Saugumui tai reiškia ir naują pareigą: konteineryje niekas atnaujinimų automatiškai neįdiegia.

Šis puslapis aprašo einamąją eksploataciją. Kaip esamus konteinerius konkrečiai pataisyti nuo PHP2Shell, aprašyta puslapyje [PHP pataisymas Docker konteineriuose](https://phpsos.de/lt/php2shell/docker-container-patchen/).

## Tinkamo atvaizdo varianto pasirinkimas

| Variantas | Turinys | Tipinis naudojimas |
|---|---|---|
| `php:<version>-fpm` | PHP-FPM, reikalingas prieš jį esantis žiniatinklio serveris | produkcija su Nginx, Caddy ar Ingress |
| `php:<version>-apache` | Apache su mod_php, pagal numatymą mpm_prefork | paprastos sandaros, senesnės programos |
| `php:<version>-cli` | komandinė eilutė, vienintelis variantas, turintis ir php-cgi | cron užduotys, eilių darbiniai procesai, build žingsniai |
| `…-alpine` | ant Alpine Linux su musl | maži atvaizdai, kai kuriems plėtiniams reikia pritaikymų |
| `…-bookworm`, `…-trixie` | ant nurodytos Debian versijos | tvirtas pagrindas atkuriamiems build |

Naujiems projektams paprastai rekomenduojamas `fpm` variantas su atskiru žiniatinklio serverio konteineriu. Esant mod_php, PHP komanda dėl PHP2Shell mato didžiausią riziką; kas naudoja `apache` atvaizdą, eksploatuoja būtent šį veikimo režimą.

## Produkcijos atvaizdo kūrimas

Lieknas pavyzdys programai su prieiga prie MySQL:

```dockerfile
FROM php:8.4-fpm-alpine

# Aktyvuoti produkcijos konfigūraciją (pagal atvaizdo dokumentaciją primygtinai rekomenduojama)
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Tik reikalingi plėtiniai
RUN docker-php-ext-install -j"$(nproc)" pdo_mysql

# Savi nustatymai
COPY zz-sicherheit.ini "$PHP_INI_DIR/conf.d/"

# Kodas priklauso root; FPM darbiniai procesai veikia kaip www-data ir gali jį tik skaityti
COPY . /var/www/html
```

Atvaizdo pagalbiniai skriptai perima plėtinių kompiliavimą: `docker-php-ext-configure` parinktims, `docker-php-ext-install` kompiliavimui, `docker-php-ext-enable` aktyvavimui, pavyzdžiui, po `pecl install`. Jei su `docker-php-source` išpakuojamas pirminis kodas, pasak dokumentacijos, jį reikėtų ištrinti tame pačiame sluoksnyje. Failas `zz-sicherheit.ini` galėtų atrodyti taip:

```ini
expose_php = Off
display_errors = Off
log_errors = On
session.use_strict_mode = 1
session.cookie_httponly = 1
```

Dar du principai daro atvaizdus patvaresnius. Pirma, pateikiamame atvaizde yra tik tai, ko reikia vykdymo metu; kompiliatorius, paketų talpyklos ir testų failai priklauso atskirai build pakopai. Antra, naudotojas, su kuriuo veikia PHP, rašyti turi tik ten, kur būtina, pavyzdžiui, įkėlimų ar talpyklos kataloguose prijungtuose tomuose (volumes). Daug komandų konteinerį papildomai eksploatuoja su tik skaitoma failų sistema. Įterptam PHP failui tuomet gerokai sunkiau išlikti, o kiekvienas paleidimas iš naujo atkuria švarią atvaizdo būseną. Tai neatstoja tyrimo po incidento, bet pastebimai sumažina atakos paviršių.

## Procesai, atmintis ir žurnalai konteineryje

Trys reguliavimo varžtai lemia, ar PHP konteineris veikia stabiliai.

1. **Darbinių procesų skaičius:** `pm.max_children` FPM baseine nustato, kiek užklausų apdorojama vienu metu. Kiekvienas darbinis procesas gali užimti iki `memory_limit`.
2. **Konteinerio atminties riba:** ji riboja visus procesus kartu. Apytikslė taisyklė: darbinių procesų skaičius, padaugintas iš atminties vienam darbiniam procesui, plius rezervas turi tilpti po riba, antraip sistema nutraukia procesus.
3. **Žurnalai:** konteineriai žurnalus rašo į standartinę išvestį. PHP-FPM `catch_workers_output = yes` darbinių procesų išvestis nukreipia į pagrindinį žurnalą; be šio nustatymo, pasak vadovo, jos dingsta tuštumoje.

Be to, naudingas `request_terminate_timeout`, kuris atskiras užklausas nutraukia po laiko tarpo, kai `max_execution_time` neveikia. Kaip konteinerius eksploatuoti klasteryje, aprašo [PHP pataisymas Kubernetes](https://phpsos.de/lt/server/kubernetes/).

## Konteineriai ir saugumas: ką parodė PHP2Shell

Esant PHP2Shell, konteineriai vaidina dvigubą vaidmenį. Viena vertus, jie yra pagalba: php.net kaip pereinamąją priemonę dėl CVE-2026-109618 rekomenduoja `memory_limit=-1` derinti su atminties riba per konteinerį ar cgroup, geriausia taip, kad būtų nutraukiamas tik paveiktas darbinis procesas. `RLIMIT_AS` ir `RLIMIT_DATA` tam, pasak php.net, netinka. Ši priemonė nėra visiška apsauga ir neatstoja atnaujinimo.

Kita vertus, konteineriai yra spąstai, jei atvaizdai neperkuriami. Atvaizdas su PHP 8.4.26 lieka pažeidžiamas, kad ir kiek kartų konteineris būtų paleistas iš naujo. Tik perkūrimas iki 8.4.27 ar naujesnės versijos ir visų veikiančių konteinerių pakeitimas uždaro spragą. Būseną galima patikrinti tiesiai veikiančiame konteineryje:

```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"));'
```

Jei paskutinė komanda grąžina `bool(false)`, PHP nepažįsta su ištaisytomis versijomis įvestos direktyvos; pasak vadovo, tuomet versija yra paveikta. Ilgalaikiai padeda tik automatinis perkūrimas, kaip aprašyta [CI/CD: automatinis PHP atvaizdų perkūrimas](https://phpsos.de/lt/blog/php-images-in-ci-neu-bauen/).

> **Patarimas:**
> Dockerfile nustatykite tikslią PHP versiją žymėje ir didinkite ją sąmoningai. Taip kode galima atsekti, kada kuri versija buvo išdiegta.

## Kaip PHP SOS padeda konkrečiai?

Per [PHP žiniatinklio serverių sutvirtinimą](https://phpsos.de/lt/leistungen/server-haertung/) rūpinamės ir konteineriais:

- **Patikrinti atvaizdus:** kiekvieno atvaizdo bazinis atvaizdas, PHP versija, plėtiniai ir konfigūracija.
- **Sutvirtinti konfigūraciją:** produkcijos ini, lieknas plėtinių sąrašas, tinkamos darbinių procesų ir atminties ribos.
- **Įrengti perkūrimą:** eiga, kuri atvaizdus perkuria ir išdiegia išleidus naujus PHP leidimus.
- **Kontroliuoti vykdymo aplinką:** įrodome, kad kiekviename veikiančiame konteineryje veikia ištaisyta versija.


## Dažni klausimai

**Kuris PHP atvaizdo variantas teisingas?**  
Nginx ar kitam tarpiniam serveriui fpm variantas, paprastai sandarai su Apache apache variantas, skriptams ir cron užduotims cli variantas. Alpine variantai mažesni, bet remiasi musl vietoj glibc, o tai kai kuriems plėtiniams būna pastebima.

**Ar PHP konteineryje atnaujinamas automatiškai?**  
Ne. Veikiantis konteineris nesikeičia. Atvaizdą su nauja PHP versija turite perkurti ir konteinerius paleisti iš naujo. Tik tada veikia ištaisyta versija.

**Kaip elgiasi memory_limit ir konteinerio riba?**  
memory_limit riboja kiekvieną atskirą PHP užklausą, konteinerio riba visą konteinerį. Abi turi derėti: darbinių procesų (worker) skaičius, padaugintas iš atminties vienam darbiniam procesui, turėtų būti mažesnis už konteinerio ribą.

**Ar konteineriuose man reikia php.ini?**  
Taip. Oficialūs atvaizdai kaip šablonus pateikia php.ini-development ir php.ini-production. Produkcijai atvaizdų dokumentacija aiškiai rekomenduoja produkcijos šabloną; savi nustatymai dedami į conf.d.

## Šaltiniai

- [Docker Official Image: PHP](https://hub.docker.com/_/php)
- [PHP vadovas: FPM konfigūracija](https://www.php.net/manual/en/install.fpm.configuration.php)
- [php.net: 2026-10-21 saugumo pranešimas](https://www.php.net/)
