Lyhyesti: Docker-kuvassa on PHP rakennushetken tilassa, ja se vanhenee ilman koodimuutostakin. Jos kuvat rakennetaan automaattisesti uudelleen, ajastetusti ja tietoturvailmoitusten yhteydessä, PHP-versio tarkistetaan putkessa ja kuva otetaan käyttöön digestillä, korjaukset kuten PHP2Shell-korjaus saadaan suunnitellusti tuotantoon. Vihreä build yksin ei ole todiste; ratkaisevaa on käynnissä olevan kontin versio.
Miksi kuvat vanhenevat ilman koodimuutosta
Monissa tiimeissä build-putki käynnistyy vain, kun joku muuttaa koodia. Sovelluksen kannalta se on looginen. Tietoturvan kannalta se on ongelma, koska kuvan PHP tulee peruskuvasta viimeisen buildin päivältä.
PHP2Shell teki tämän näkyväksi. Korjatut versiot 8.5.12, 8.4.27, 8.3.36 ja 8.2.35 julkaistiin 21. lokakuuta 2026. Projekti, jonka parissa kukaan ei näinä päivinä työskennellyt, ei saanut uutta buildia ja toimi vanhalla PHP:llä, vaikka peruskuva oli jo päivitetty. Manuaalisen tien tästä tilanteesta kuvaa PHP:n korjaus Docker-konteissa. Tämä artikkeli näyttää, miten sen automatisoitte.
Docker-kuvien automaattinen uudelleenrakennus: kolme käynnistäjää
Kestävä prosessi yhdistää useita käynnistäjiä, jotta mikään ei joudu kantamaan yksin.
| Käynnistäjä | Toteutus | Huomioitavaa |
|---|---|---|
| Aikataulu | ajastettu työnkulku, esim. viikoittain | hakee korjaukset ilman koodimuutostakin |
| Uusi peruskuva | työkalu, joka seuraa peruskuvia ja ehdottaa muutoksia | toimii lähinnä kiinteillä versiotageilla |
| Tietoturvailmoitus | käyttötiimi käynnistää putken käsin | tarvitsee selvän vastuuhenkilön |
GitHub Actionsissa aikataulusta vastaa tapahtuma schedule. GitHubin dokumentaation mukaan se käyttää viisikenttäistä cron-syntaksia, toimii UTC-ajassa ja vain oletushaarassa. Ajastetut ajot voivat käynnistyä viiveellä suuren kuormituksen aikana, ja julkisissa repositorioissa GitHub poistaa ne käytöstä 60 päivän jälkeen, jos aktiviteettia ei ole. Juuri tämä osuu hiljaisiin projekteihin, eli juuri niihin, jotka tarvitsevat automaattista uudelleenrakennusta kipeimmin.
Toisen käynnistäjän osalta Dependabot tukee GitHubin dokumentaation mukaan docker-ekosysteemiä ja ehdottaa peruskuvien uusia tiloja pull requestina. Kaksi rajoitusta kannattaa tuntea. Ensinnäkin jonkun on tarkistettava ja yhdistettävä pull request, muuten se jää makaamaan. Toiseksi haaratagin, kuten php:8.3-fpm, kohdalla Dockerfilessä ei muutu mitään, kun peruskuva rakennetaan uudelleen. Tekstimuutoksia ehdottavalla työkalulla ei silloin ole mitään ehdotettavaa. Juuri siksi tarvitaan lisäksi ajastettu uudelleenrakennus.
Kolmas käynnistäjä kuulostaa arkiselta, mutta käytännössä kaatuu usein kysymykseen siitä, kuka sen laukaisee. Sopikaa, kuka seuraa PHP:n tietoturvailmoituksia ja kuka saa käynnistää putken, myös viikonloppuna. PHP2Shellissä ennakkoilmoituksen ja korjauksen välissä oli vain yksi päivä.
Putki, joka pysäyttää vanhentuneen PHP:n
Seuraava GitHub Actions -esimerkki rakentaa kuvan viikoittain ja napin painalluksella, tarkistaa PHP-version ja keskeyttää, jos se on korjattua tilaa alempana. Rekisterin, nimet ja vähimmäisversion mukautatte itse.
name: php-image-rebuild
on:
schedule:
- cron: "0 3 * * 1" # maanantaisin 03:00 UTC
workflow_dispatch: {} # manuaalinen käynnistys tietoturvailmoitusten yhteydessä
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);'
Versiotarkistus toimii virallisilla PHP-kuvilla, joissa versionumero ilmoittaa todellisen tilan. Jos kuvanne käyttää jakelun PHP-paketteja, numero pysyy backportin jälkeen usein samana. Silloin tarkistatte numeron sijaan paketin muutoslokin CVE-numeroiden varalta, kuten artikkelissa CVE-numeroiden todistaminen paketin muutoslokista kuvataan.
Tarkistuksen jälkeen käytännössä seuraa kolme muuta vaihetta: kuvan skannaus tunnettujen haavoittuvuuksien varalta, sen vieminen rekisteriin päivämäärän ja digestin kanssa sekä digestin välittäminen käyttöönotolle. Mitkä tagit ja variantit sopivat pohjaksi, selittää Viralliset PHP Docker -kuvat.
Buildista käynnissä olevaan konttiin
Yleisin ajatusvirhe: putki on vihreä, joten kaikki on korjattu. Todellisuudessa uusi kuva on vain rekisterissä. Korjaus tulee voimaan vasta, kun jokainen kontti on luotu uudelleen uudesta kuvasta.
- Ottakaa käyttöön digestillä: Käyttöönotto viittaa uuden kuvan digestiin, ei siirtyvään tagiin.
- Ensin staging, sitten tuotanto: Automaattiset testit kopiolla havaitsevat uusista peruskuvista aiheutuvat rikkoutumiset.
- Tarkistakaa käytössä: Ajakaa käyttöönoton jälkeen
php -vkäynnissä olevassa kontissa ja verratkaa digestiä buildiin. - Rajatkaa paluutie: Vanha kuva pysyy lyhyen paluutien varalta saatavilla, mutta sisältää haavoittuvan PHP:n.
Kubernetesissa pätevät omat sääntönsä, esimerkiksi pull-käytännöstä; ne ovat sivulla PHP:n korjaus Kubernetesissa.
Tyypillisiä aukkoja ketjussa
- Build-välimuisti runnerilla: Ilman
--pull- ja--no-cache-valintoja vanha peruskuva käytetään uudelleen. - Rekisteripeili: Sisäinen välimuisti toimittaa yhä peruskuvan vanhaa tilaa.
- Monivaiheiset buildit: Viimeisen vaiheen PHP-versio on ratkaiseva, mutta usein tarkistetaan vain ensimmäinen.
- Sivukuvat: Jonotyöläisillä, cron-konteilla ja sisäisillä työkaluilla on omat putkensa tai ei ollenkaan.
- Kiinteästi kirjatut digestit: Kerran lukittua peruskuvan digestiä ei koskaan päivitetä, jos mikään työkalu ei seuraa sitä.
Uudelleenrakennus korvaa PHP:n, ei dataa. Haittakoodi, joka on ennen korjausta päätynyt volyymeihin, upload-kansioihin tai tietokantaan, säilyy ja se on tarkistettava erikseen.
Kuka reagoi, jos uudelleenrakennus epäonnistuu?
Automaattinen uudelleenrakennus on yhtä hyvä kuin reaktio sen epäonnistumiseen. Jos versiotarkistus hälyttää tai build keskeytyy muuttuneen peruskuvan vuoksi, jonkun on huomattava se. Monissa tiimeissä tällaiset ilmoitukset päätyvät postilaatikkoon, jota kukaan ei lue, tai kanavaan, jossa punaiset buildit ovat jo arkea.
Hyväksi on osoittautunut selvä sääntö: epäonnistunut tietoturvarakennus on tiketti, jolla on vastuuhenkilö ja määräaika, ei yksi huomautus muiden joukossa. Kirjatkaa lisäksi jokaisesta käyttöön otetusta kuvasta päivämäärä, digest ja tarkistettu PHP-versio. Tämä luettelo vastaa seuraavan ilmoituksen yhteydessä minuuteissa kysymykseen siitä, mitkä sovellukset ovat kyseessä, ja toimii todisteena tarkastajille tai vakuutusyhtiöille. Miten tästä syntyy pysyvä toimintatapa, kuvaa Korjausten hallinta prosessina palokunnan sijaan.
Miten PHP SOS auttaa konkreettisesti?
- Putkien tarkistus: Käymme läpi build- ja käyttöönotto-ketjunne ja näytämme, missä korjaus voi jäädä jumiin.
- Uudelleenrakennuksen automatisointi: Otamme käyttöön ajastetut buildit, versiotarkistuksen ja käyttöönoton digestillä.
- Kaikkien kuvien kartoitus: Yhdistämme jokaisen käynnissä olevan kontin putkeensa, myös sivu- ja vanhat kuvat.
- Pysyvä tuki: Tietoturvahuoltosopimuksessa seuraamme tietoturvailmoituksia ja käynnistämme uudelleenrakennukset.
Usein kysytyt kysymykset
Kuinka usein PHP-kuva pitäisi rakentaa uudelleen?
Kiinteää lukua ei ole. Hyväksi on osoittautunut säännöllinen ajastettu build, esimerkiksi viikoittain, sekä välitön build tietoturvailmoitusten yhteydessä. Ratkaisevaa on, ettei uusi korjaus joudu odottamaan seuraavaa koodimuutosta.
Riittääkö onnistunut build todisteeksi?
Ei. Build todistaa vain, että uusi kuva on olemassa. Vasta kun käynnissä olevat kontit on luotu tästä kuvasta uudelleen ja php -v näyttää niissä korjatun version, korjaus on voimassa.
Miksi uudelleenrakennuksen jälkeenkin näkyy vanha PHP-versio?
Tavallisia syitä ovat build-välimuisti, joka käyttää uudelleen vanhaa peruskuvaa, rekisteripeili vanhalla tilalla tai toinen FROM-rivi monivaiheisessa buildissa. Rakentakaa valinnoilla --pull ja --no-cache ja tarkistakaa jokainen vaihe.
Voiko Dependabot päivittää peruskuvia?
GitHubin dokumentaation mukaan Dependabot tukee Docker-ekosysteemiä versio- ja tietoturvapäivityksissä. Se ehdottaa peruskuvien muutoksia pull requestina. Se ei korvaa uudelleenrakennusta, kun tagi pysyy samana.