Ukratko: Docker image sadrži PHP u stanju trenutka izgradnje i zastarijeva i bez izmjene koda. Tko image-e automatski ponovno gradi, vremenski upravljano i kod sigurnosnih objava, provjerava PHP verziju u pipelineu i isporučuje putem digesta, zakrpe poput one protiv PHP2Shella u produkciju donosi planirano. Zelena izgradnja sama nije dokaz; vrijedi verzija u aktivnom kontejneru.
Zašto image-i zastarijevaju bez izmjene koda
U mnogim timovima build pipeline starta samo kad netko izmijeni kod. Za aplikaciju je to logično. Za sigurnost je to problem, jer PHP u image-u potječe iz osnovnog image-a na dan zadnje izgradnje.
PHP2Shell je to učinio vidljivim. Ispravljene verzije 8.5.12, 8.4.27, 8.3.36 i 8.2.35 objavljene su 21. listopada 2026. Projekt na kojem tih dana nitko nije radio nije dobio novu izgradnju i nastavio je raditi sa starim PHP-om, iako je osnovni image odavno ažuriran. Ručni put iz te situacije opisuje članak Zakrpati PHP u Docker kontejnerima. Ovaj prilog pokazuje kako ga automatizirati.
Automatski ponovno graditi Docker image-e: tri okidača
Robustan postupak kombinira više okidača kako nijedan ne bi morao nositi sam.
| Okidač | Provedba | Na što paziti |
|---|---|---|
| Vremenski plan | vremenski upravljan workflow, npr. tjedno | preuzima zakrpe i bez izmjene koda |
| Novi osnovni image | alat koji nadzire osnovne image-e i predlaže izmjene | djeluje uglavnom kod čvrstih tagova verzija |
| Sigurnosna objava | ručno pokretanje pipelinea od strane operativnog tima | treba jasnu odgovornu osobu |
Kod GitHub Actionsa vremenski plan preuzima događaj schedule. Prema GitHub dokumentaciji koristi cron sintaksu s pet polja, radi u UTC-u i samo na zadanoj grani. Planirana izvođenja mogu kasniti pri velikom opterećenju, a u javnim repozitorijima GitHub ih nakon 60 dana bez aktivnosti isključuje. Upravo potonje pogađa mirne projekte, dakle baš one kojima je automatska ponovna izgradnja najpotrebnija.
Za drugi okidač Dependabot prema GitHub dokumentaciji podržava ekosustav docker i nova stanja osnovnih image-a predlaže kao pull request. Treba znati dva ograničenja. Prvo, netko mora pregledati i spojiti pull request, inače ostaje ležati. Drugo, kod taga grane poput php:8.3-fpm u Dockerfileu se ništa ne mijenja kad se osnovni image iznova izgradi. Alat koji predlaže tekstualne izmjene tada nema što predložiti. Upravo zato je uz njega potrebna i vremenski upravljana ponovna izgradnja.
Treći okidač zvuči banalno, ali u praksi često zapne na pitanju tko ga pokreće. Odredite tko prati sigurnosne objave o PHP-u i tko smije pokrenuti pipeline, i vikendom. Kod PHP2Shella između prethodne najave i zakrpe prošao je samo jedan dan.
Pipeline koji hvata zastarjeli PHP
Sljedeći primjer za GitHub Actions gradi image tjedno i na zahtjev, provjerava PHP verziju i prekida ako je ispod ispravljenog stanja. Registry, nazive i minimalnu verziju prilagodite.
name: php-image-rebuild
on:
schedule:
- cron: "0 3 * * 1" # ponedjeljkom u 03:00 UTC
workflow_dispatch: {} # ručno pokretanje kod sigurnosnih objava
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);'
Provjera verzije radi kod službenih PHP image-a, čiji broj verzije prikazuje stvarno stanje. Ako Vaš image koristi PHP pakete distribucije, broj nakon backporta često ostaje isti. Tada umjesto broja provjerite changelog paketa na CVE brojeve, kako opisuje članak Dokazati CVE brojeve u changelogu paketa.
Nakon provjere u praksi slijede još tri koraka: skenirati image na poznate ranjivosti, gurnuti ga u registry s datumom i digestom te digest predati isporuci. Koji tagovi i varijante prikladno služe kao osnova, objašnjava članak Službeni PHP Docker image-i.
Od izgradnje do aktivnog kontejnera
Najčešća pogreška u razmišljanju: pipeline je zelen, dakle sve je zakrpano. Zapravo novi image samo leži u registryju. Zakrpa stupa na snagu tek kad je svaki kontejner iz novog image-a ponovno stvoren.
- Isporučivati putem digesta: Isporuka upućuje na digest novog image-a, a ne na tag koji se pomiče.
- Najprije staging, zatim produkcija: Automatski testovi na kopiji hvataju lomove zbog novih osnovnih image-a.
- Provjeriti u pogonu: Nakon isporuke izvršiti
php -vu aktivnom kontejneru i usporediti digest s izgradnjom. - Ograničiti povratni put: Stari image ostaje dostupan za kratak povratak, ali sadrži ranjivi PHP.
U Kubernetesu za to vrijede posebna pravila, primjerice o pull politici; nalaze se u članku Zakrpati PHP u Kubernetesu.
Tipične praznine u lancu
- Build cache na runneru: Bez
--pulli--no-cacheponovno se koristi stari osnovni image. - Zrcalo registryja: Interni međuspremnik još isporučuje staro stanje osnovnog image-a.
- Višestupanjske izgradnje: Vrijedi PHP verzija zadnje faze, a često se provjerava samo prva.
- Sporedni image-i: Queue workeri, cron kontejneri i interni alati imaju vlastite pipelineove ili nikakve.
- Čvrsto upisani digesti: Jednom učvršćeni digest osnovnog image-a nikad se ne ažurira ako ga nijedan alat ne nadzire.
Ponovna izgradnja zamjenjuje PHP, a ne podatke. Zlonamjerni kod koji je prije zakrpe dospio u volumene, direktorije za prijenose ili bazu podataka ostaje i treba ga provjeriti zasebno.
Tko reagira kad ponovna izgradnja ne uspije?
Automatska ponovna izgradnja vrijedi koliko i reakcija na njezin neuspjeh. Ako provjera verzije alarmira ili izgradnja pukne zbog izmijenjenog osnovnog image-a, netko to mora primijetiti. U mnogim timovima takve poruke završe u sandučiću koji nitko ne čita ili u kanalu u kojem su crvene izgradnje odavno svakodnevica.
Dokazalo se jasno pravilo: neuspjela sigurnosna ponovna izgradnja je tiket s odgovornom osobom i rokom, a ne obavijest među mnogima. Uz to za svaki isporučeni image zabilježite datum, digest i provjerenu PHP verziju. Taj popis kod sljedeće objave u nekoliko minuta odgovara koje su aplikacije pogođene, a prema revizorima ili osigurateljima služi kao dokaz. Kako iz toga nastaje trajan postupak, opisuje članak Upravljanje zakrpama kao proces umjesto gašenja požara.
Kako PHP SOS konkretno pomaže?
- Provjeriti pipelineove: Pregledavamo Vaše lance izgradnje i isporuke i pokazujemo gdje zakrpa može zapeti.
- Automatizirati ponovnu izgradnju: Postavljamo vremenski upravljane izgradnje, provjeru verzije i isporuku putem digesta.
- Obuhvatiti sve image-e: Svakom aktivnom kontejneru pridružujemo njegov pipeline, i sporednim i starim image-ima.
- Brinuti trajno: U sigurnosnom ugovoru o održavanju pratimo sigurnosne objave i pokrećemo ponovne izgradnje.
Česta pitanja
Koliko često treba ponovno graditi PHP image?
Fiksnog broja nema. Dokazala se redovita vremenski upravljana izgradnja, primjerice tjedna, uz trenutnu izgradnju kod sigurnosnih objava. Odlučujuće je da nova zakrpa ne mora čekati sljedeću izmjenu koda.
Je li uspješna izgradnja dovoljna kao dokaz?
Ne. Izgradnja dokazuje samo da postoji novi image. Tek kad su aktivni kontejneri iz tog image-a ponovno stvoreni, a php -v u njima prikazuje ispravljenu verziju, zakrpa djeluje.
Zašto se nakon ponovne izgradnje ipak pojavljuje stara PHP verzija?
Česti su uzroci build cache koji ponovno koristi stari osnovni image, zrcalo registryja sa starim stanjem ili drugi redak FROM u višestupanjskoj izgradnji. Gradite s --pull i --no-cache te provjerite svaku fazu.
Može li Dependabot ažurirati osnovne image-e?
Prema GitHub dokumentaciji Dependabot podržava ekosustav Docker za ažuriranja verzija i sigurnosna ažuriranja. Izmjene osnovnih image-a predlaže kao pull request. Ponovnu izgradnju uz nepromijenjeni tag to ne zamjenjuje.