Stručne: Obraz Docker obsahuje PHP v stave z času svojho zostavenia a zastaráva aj bez zmeny kódu. Kto obrazy zostavuje automaticky nanovo, časovo riadene aj pri bezpečnostných hláseniach, kontroluje verziu PHP v pipeline a nasadzuje podľa digestu, dostane záplaty ako proti PHP2Shell plánovane do produkcie. Zelené zostavenie samo o sebe nie je dôkaz; rozhoduje verzia v bežiacom kontajneri.
Prečo obrazy zastarávajú bez zmeny kódu
V mnohých tímoch sa build pipeline spustí, len keď niekto zmení kód. Pre aplikáciu je to logické. Pre bezpečnosť je to problém, pretože PHP v obraze pochádza zo základného obrazu z tagu posledného zostavenia.
PHP2Shell to urobil viditeľným. Opravené verzie 8.5.12, 8.4.27, 8.3.36 a 8.2.35 vyšli 21. októbra 2026. Projekt, na ktorom v týchto dňoch nikto nepracoval, nedostal nové zostavenie a bežal ďalej so starým PHP, hoci základný obraz bol už dávno aktualizovaný. Ručný spôsob, ako sa z tejto situácie dostať, opisuje Záplatovanie PHP v kontajneroch Docker. Tento článok ukazuje, ako ho automatizovať.
Automatické nové zostavenie obrazov Docker: tri spúšťače
Robustný proces kombinuje viacero spúšťačov, aby ani jeden nemusel nosiť všetko sám.
| Spúšťač | Realizácia | Na čo dbať |
|---|---|---|
| Časový plán | časovo riadený workflow, napr. týždenne | zachytí záplaty aj bez zmeny kódu |
| Nový základný obraz | nástroj, ktorý sleduje základné obrazy a navrhuje zmeny | pôsobí hlavne pri pevných tagoch verzií |
| Bezpečnostné hlásenie | ručné spustenie pipeline prevádzkovým tímom | potrebuje jasne určenú zodpovednú osobu |
V GitHub Actions preberá časový plán udalosť schedule. Podľa dokumentácie GitHub používa syntax cron s piatimi poľami, beží v UTC a len na predvolenej vetve. Plánované behy sa pri vysokej záťaži môžu spustiť s oneskorením a vo verejných repozitároch ich GitHub po 60 dňoch bez aktivity vypne. Najmä to druhé postihuje pokojné projekty, teda práve tie, ktoré automatické nové zostavenie potrebujú najnaliehavejšie.
Pre druhý spúšťač podporuje Dependabot podľa dokumentácie GitHub ekosystém docker a navrhuje nové stavy základných obrazov ako pull request. Poznať treba dve obmedzenia. Po prvé, niekto musí pull request skontrolovať a zlúčiť, inak ostane ležať. Po druhé, pri tagu vetvy ako php:8.3-fpm sa v Dockerfile nič nezmení, keď sa základný obraz zostaví nanovo. Nástroj, ktorý navrhuje textové zmeny, potom nemá čo navrhnúť. Presne preto je navyše potrebné časovo riadené nové zostavenie.
Tretí spúšťač znie banálne, v praxi však často stroskotá na otázke, kto ho spúšťa. Určte, kto sleduje bezpečnostné hlásenia k PHP a kto smie spustiť pipeline, aj cez víkend. Pri PHP2Shell uplynul medzi predbežným oznámením a záplatou len jeden deň.
Pipeline, ktorá zachytí zastarané PHP
Nasledujúci príklad pre GitHub Actions zostavuje obraz týždenne a na požiadanie, kontroluje verziu PHP a skončí chybou, ak je pod opraveným stavom. Registry, názvy a minimálnu verziu prispôsobte.
name: php-image-rebuild
on:
schedule:
- cron: "0 3 * * 1" # v pondelok o 03:00 UTC
workflow_dispatch: {} # ručné spustenie pri bezpečnostných hláseniach
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Image ohne Cache und mit frischem Basis-Image bauen
run: docker build --pull --no-cache -t app:${{ github.run_id }} .
- name: PHP-Version prüfen (Mindeststand des Zweigs 8.3)
run: |
docker run --rm app:${{ github.run_id }} php -v
docker run --rm app:${{ github.run_id }} \
php -r 'exit(version_compare(PHP_VERSION, "8.3.36", ">=") ? 0 : 1);'
Kontrola verzie funguje pri oficiálnych obrazoch PHP, kde číslo verzie udáva skutočný stav. Ak váš obraz používa balíky PHP z distribúcie, číslo zostáva po backporte často rovnaké. Vtedy namiesto čísla skontrolujte changelog balíka na čísla CVE, ako opisuje článok Doloženie čísel CVE v changelogu balíka.
Po kontrole nasledujú v praxi ďalšie tri kroky: preskenovať obraz na známe slabiny, nahrať ho do registra s dátumom a digestom a odovzdať digest nasadeniu. Ktoré tagy a varianty sa hodia ako základ, vysvetľujú Oficiálne obrazy PHP Docker.
Od zostavenia k bežiacemu kontajneru
Najčastejšia chyba v úvahe: pipeline je zelená, takže je všetko zaplátané. V skutočnosti nový obraz len leží v registri. Záplata je účinná, až keď je každý kontajner z nového obrazu vytvorený nanovo.
- Nasadiť podľa digestu: Nasadenie odkazuje na digest nového obrazu, nie na putujúci tag.
- Najprv staging, potom produkcia: Automatické testy na kópii zachytia zlomy spôsobené novými základnými obrazmi.
- Skontrolovať v prevádzke: Po nasadení spustiť
php -vv bežiacom kontajneri a porovnať digest so zostavením. - Obmedziť cestu späť: Starý obraz ostáva krátko dostupný pre návrat, obsahuje však zraniteľné PHP.
V Kubernetes platia na to vlastné pravidlá, napríklad k pull policy; nájdete ich v časti Záplatovanie PHP v Kubernetes.
Typické medzery v reťazci
- Cache zostavenia na runneri: Bez
--pulla--no-cachesa použije starý základný obraz. - Zrkadlo registra: Interná medzipamäť stále dodáva starý stav základného obrazu.
- Viacstupňové zostavenia: Rozhoduje verzia PHP posledného stupňa, kontroluje sa však často len prvý.
- Vedľajšie obrazy: Queue workery, kontajnery cronu a interné nástroje majú vlastné pipeline alebo žiadne.
- Pevne zapísané digesty: Raz zafixovaný digest základného obrazu sa nikdy neaktualizuje, ak ho nesleduje žiadny nástroj.
Nové zostavenie nahrádza PHP, nie dáta. Škodlivý kód, ktorý sa pred záplatou dostal do zväzkov, priečinkov na nahrávanie alebo do databázy, ostáva zachovaný a treba ho skontrolovať osobitne.
Kto zareaguje, keď nové zostavenie zlyhá?
Automatické nové zostavenie je len také dobré, ako reakcia na jeho zlyhanie. Ak kontrola verzie zaúradí alebo build skončí kvôli zmenenému základnému obrazu, musí si to niekto všimnúť. V mnohých tímoch takéto hlásenia končia v schránke, ktorú nikto nečíta, alebo v kanáli, v ktorom sú červené buildy dávno bežnou vecou.
Osvedčilo sa jasné pravidlo: zlyhané bezpečnostné nové zostavenie je tiket so zodpovednou osobou a lehotou, nie upozornenie medzi inými. Navyše si pri každom nasadenom obraze zaznamenajte dátum, digest a overenú verziu PHP. Tento zoznam pri ďalšom hlásení za pár minút odpovie, ktoré aplikácie sú dotknuté, a slúži voči audítorom alebo poisťovateľom ako doklad. Ako z toho vznikne trvalý postup, opisuje Patch management ako proces namiesto hasenia požiarov.
Ako konkrétne pomáha PHP SOS?
- Preveriť pipeline: Pozrieme sa na vaše reťazce zostavenia a nasadenia a ukážeme, kde môže záplata uviaznuť.
- Automatizovať nové zostavenie: Nastavíme časovo riadené buildy, kontrolu verzie a nasadenie podľa digestu.
- Zachytiť všetky obrazy: Každému bežiacemu kontajneru priradíme jeho pipeline, aj vedľajším a starým obrazom.
- Starať sa trvalo: V zmluve o bezpečnostnej údržbe sledujeme bezpečnostné hlásenia a spúšťame nové zostavenia.
Časté otázky
Ako často by sa mal obraz PHP zostavovať nanovo?
Pevné číslo neexistuje. Osvedčilo sa pravidelné časovo riadené zostavenie, napríklad týždenne, plus okamžité zostavenie pri bezpečnostných hláseniach. Rozhodujúce je, aby nová záplata nemusela čakať na ďalšiu zmenu kódu.
Stačí úspešné zostavenie ako doklad?
Nie. Zostavenie dokazuje len to, že existuje nový obraz. Záplata je účinná, až keď sú bežiace kontajnery z tohto obrazu vytvorené nanovo a php -v v nich ukazuje opravenú verziu.
Prečo sa po novom zostavení aj tak objavuje stará verzia PHP?
Častými príčinami sú cache zostavenia, ktorá znovu použije starý základný obraz, zrkadlo registra so starým stavom alebo druhý riadok FROM vo viacstupňovom zostavení. Zostavujte s --pull a --no-cache a skontrolujte každý stupeň.
Môže Dependabot aktualizovať základné obrazy?
Podľa dokumentácie GitHub podporuje Dependabot ekosystém Docker pre aktualizácie verzií a bezpečnostné aktualizácie. Zmeny základných obrazov navrhuje ako pull request. Nové zostavenie pri nezmenenom tagu to nenahrádza.