Docker for PHP élesben: gyakorlati beállítási útmutató üzleti alkalmazásokhoz
Docker a PHP alkalmazásokat ugyanúgy futtatja laptopon, tesztelésben és élesben, és a kiadások és visszaállítások rutinszerűvé teszik a stressz helyett. Mozgó alkatrészeket is ad hozzá, és a gondatlan beállítás rosszabb, mint egy sima szerver. Ez az útmutató bemutatja a gyártásra kész kiindulási helyzetet valós konfigurációval, és azt, hogy mikor nem kell bajlódnia.
Röviden
- Docker megéri, ha azonos környezetre, gyors visszaállításra és egyszerű beépítésre vágyik. Egyetlen kis brosúraoldal esetében a megosztott tárhelyről általában szükségtelen.
- Készítsen változatlan képet a CI-ben: többlépcsős összeállítás, csak éles függőségek, nem root felhasználó, OPcache bekapcsolva, hibák naplózva és soha nem jelennek meg.
- Képcímke által történő kiadás (a Git commit hash), ellenőrizze az állapotot az indítás után, és automatikusan visszalépjen az előző címkére, ha az ellenőrzés sikertelen.
- A tárolók eldobhatók, az adatok nem: tartsa meg az adatbázist és a feltöltéseket kötetekben vagy felügyelt szolgáltatásokban, és készítsen biztonsági másolatot Docker kívül.
- A leggyakoribb gyártási hibák: titkok a képben, közzétett adatbázis-portok, korlátlan naplók és php-fpm korlátok, amelyek nem egyeznek a memóriával.
Sok üzleti alkalmazás esetében a hosting valódi költségét nem a szerver, hanem az emberek jelentik. Hosszú távon költségesek az olyan beállítások, amelyeket csak egy fejlesztő ért, a kézi FTP-n keresztül történő telepítés és az élestől eltérően viselkedő átmeneti környezet. A konténerek ezt úgy oldják meg, hogy becsomagolják az alkalmazást a pontos PHP verzióval és bővítményekkel. Saját PHP webhelyeinket és kliensrendszereinket Docker-alapú veremben futtatjuk, és ez az útmutató leírja, hogy miből indulunk ki.
Mikor éri meg Docker, és mikor nem
- Megéri: több szolgáltatás (web, PHP, adatbázis, sor), több fejlesztő, megismételhető kiadások és gyors visszaállítások igénye, vagy a szolgáltatók közötti váltás terve.
- Nem szükséges: egy egyszerű tartalmi webhely, amely ritkán változik felügyelt tárhely esetén. A megnövelt komplexitás megtérülést igényel.
- Nem helyettesíti a jó műveleteket: továbbra is szükség van javításra, biztonsági mentésre és felügyeletre. Tekintse meg biztonsági mentési és megfigyelési útmutatónkat.
A cél architektúra
Szilárd, egyszerű beállítás egy PHP alkalmazáshoz egy szerveren:
- Fordított proxy és TLS a szélén ( Nginx vagy Caddy a gazdagépen, vagy CDN, például Cloudflare, lásd Cloudflare beállítási útmutatónkat).
- Webtároló ( Nginx), amely statikus fájlokat szolgál ki, és PHP kéréseket továbbít.
- PHP-FPM tároló a kódjával, a képbe beépítve.
- Adatbázis a saját tárolójában állandó kötettel, vagy jobb esetben egy felügyelt adatbázis-szolgáltatás a kritikus adatokhoz.
- Csak olyan adatok kötetei, amelyeknek életben kell maradniuk: adatbázisfájlok és felhasználói feltöltések.
Többlépcsős Dockerfile
A többlépcsős összeállítás egy szakaszban telepíti a függőségeket, és csak az eredményt másolja át egy vékony futásidejű képfájlba. A végső kép nem tartalmaz Composer, fordítókat vagy teszteszközöket, ami kisebbé teszi, és kevesebbet használhatnak a támadók:
# ---- stage 1: PHP dependencies ----
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --prefer-dist --no-interaction --optimize-autoloader
# ---- stage 2: runtime ----
FROM php:8.3-fpm-alpine
RUN apk add --no-cache icu-libs libzip \
&& apk add --no-cache --virtual .build icu-dev libzip-dev $PHPIZE_DEPS \
&& docker-php-ext-install -j"$(nproc)" pdo_mysql intl zip opcache \
&& apk del .build
COPY docker/php.ini /usr/local/etc/php/conf.d/zz-app.ini
COPY docker/www.conf /usr/local/etc/php-fpm.d/zz-www.conf
WORKDIR /var/www/app
COPY --from=vendor /app/vendor ./vendor
COPY --chown=www-data:www-data . .
USER www-data
EXPOSE 9000
Szándékosan válassza ki a PHP verziót, és ellenőrizze, hogy továbbra is támogatott-e. A PHP 8 frissítési útmutatónk elmagyarázza, hogyan kell ezt megtervezni. Rögzítse az alapképek verzióit, és ütemezetten frissítse őket, mivel a soha újra nem épített képfájlok ismert sebezhetőségeket halmoznak fel. Tartson egy .dockerignore amely kizárja .git, .env, teszteket és helyi adatokat, így semmi érzékeny nem kerül a képbe.
Gyártási PHP és php-fpm konfiguráció
# docker/php.ini
expose_php = 0
display_errors = 0
log_errors = 1
memory_limit = 256M
upload_max_filesize = 10M
post_max_size = 12M
opcache.enable = 1
opcache.memory_consumption = 128
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0 ; the code in an image never changes while it runs
# docker/www.conf
[www]
pm = dynamic
pm.max_children = 12
pm.start_servers = 3
pm.min_spare_servers = 2
pm.max_spare_servers = 5
pm.max_requests = 500
request_terminate_timeout = 30s
catch_workers_output = yes
decorate_workers_output = no
opcache.validate_timestamps = 0 beállítása biztosítja a legjobb teljesítményt egy megváltoztathatatlan kép esetén, de ez csak akkor működik, ha soha nem szerkeszt fájlokat egy futó tárolóban: helyette új képet ad ki. Mérje meg a készletet valós számokból: mérje meg egy PHP munkás átlagos memóriáját terhelés alatt, döntse el, mennyi memóriát használhat PHP a szerveren, és ossza el. Ha egy dolgozó 60 MB-ot használ, és 1 GB-ot tudsz adni PHP, akkor pm.max_children körülbelül 16. Ha sokkal magasabbra állítod, akkor a forgalom kiugrása során a szerver csere vagy a kernel leállítása következik be. Túl alacsony, és a kérések sorba állnak. Ellenőrizze a php-fpm naplóban a "max_children reach" figyelmeztetéseket.
Egy Compose fájl a megfelelő alapértelmezett értékekkel
x-logging: &default-logging
driver: json-file
options: { max-size: "10m", max-file: "5" } # logs cannot fill the disk
services:
web:
image: ghcr.io/your-org/app-web:${TAG}
ports: ["127.0.0.1:8080:80"] # only the local reverse proxy can reach it
depends_on: [php]
restart: unless-stopped
logging: *default-logging
healthcheck:
test: ["CMD", "wget", "-q", "--spider", "http://127.0.0.1/health.php"]
interval: 15s
timeout: 3s
retries: 3
php:
image: ghcr.io/your-org/app:${TAG}
env_file: .env # secrets stay on the server, not in the image
restart: unless-stopped
read_only: true
tmpfs: [/tmp]
mem_limit: 512m
volumes: [uploads:/var/www/app/storage/uploads]
logging: *default-logging
db:
image: mysql:8.4
env_file: .env.db
restart: unless-stopped
volumes: [db_data:/var/lib/mysql] # no "ports:" - the database is not public
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1"]
interval: 15s
retries: 5
logging: *default-logging
volumes:
uploads:
db_data:
A web egy kis Nginx kép, amelybe be van másolva public/ mappája és a webhely konfigurációja, és ugyanabban a folyamatban van beépítve, mint a PHP kép. Főbb pontok: kösse össze a közzétett portokat 127.0.0.1 hez, soha ne tegye közzé az adatbázist, állítson be újraindítási házirendeket, korlátozza a memóriát, hogy egyetlen tároló ne tudja levenni a gazdagépet, és korlátozza a naplóméretet. Ne feledje, hogy Docker által közzétett portok megkerülhetik a gazdagép tűzfalszabályait, amint azt a Cloudflare útmutatóban is elmagyarázzuk. Soha ne szerelje be a Docker foglalatot egy alkalmazástárolóba, mert ez biztosítja a tároló vezérlését a gazdagép felett.
Kiadások és visszaállítások
A képalapú beállítás legjobb tulajdonsága, hogy minden kiadás egy címke, a visszaállítás pedig az "előző címke indítása". Jelölje meg a képeket a Git commit hash-sel, soha ne hagyatkozzon a latest, és állítsa be a kiadási szkriptet az állapot ellenőrzésére:
#!/usr/bin/env bash
# /srv/app/release.sh <git-sha>
set -euo pipefail
TAG="${1:?usage: release.sh <git-sha>}"
cd /srv/app
PREV="$(cat .current_tag 2>/dev/null || true)"
export TAG
docker compose pull php web
docker compose up -d --no-deps php web
for i in $(seq 1 30); do
if curl -fsS http://127.0.0.1:8080/health.php > /dev/null; then
echo "$TAG" > .current_tag
echo "healthy: $TAG"; exit 0
fi
sleep 2
done
echo "unhealthy after release, rolling back to ${PREV:-none}" >&2
if [ -n "$PREV" ]; then TAG="$PREV" docker compose up -d --no-deps php web; fi
exit 1
Az adatbázis-módosítások körültekintést igényelnek: írjon migrációt, hogy a kód előző verziója továbbra is működjön az új sémával (először adjon hozzá oszlopokat, majd távolítsa el őket egy későbbi kiadásban). Ez az, ami biztonságossá teszi a gyors visszaállítást. Készítsen adatbázis biztonsági másolatot minden olyan kiadás előtt, amely módosítja a sémát.
Építés és szállítás a CI-től
Egyszer készítse el a képet a CI-ben, és telepítse pontosan azt a műterméket. Egy minimális GitHub Actions munkafolyamat:
name: build-and-release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v6
with:
context: .
push: true
tags: ghcr.io/your-org/app:${{ github.sha }}
- name: Release over SSH
env:
DEPLOY_KEY: ${{ secrets.DEPLOY_KEY }}
run: |
install -m 600 /dev/null key && echo "$DEPLOY_KEY" > key
ssh -i key -o StrictHostKeyChecking=accept-new deploy@your-server "/srv/app/release.sh ${{ github.sha }}"
Futtassa le a teszteket és a statikus elemzést ugyanabban a folyamatban a lemezkép felépítése előtt, és használjon olyan telepítési kulcsot, amely csak a kiadási parancsfájlt tudja futtatni. Adjon hozzá egy kép sebezhetőségi vizsgálatát, ha kockázati profilja ezt megköveteli.
Naplók, adatok és biztonság
- A naplók az stdout és az stderr mappába kerülnek, Docker forgatja őket, és minden fontos dolog esetén egy központi helyre szállítják, hogy túléljék a tárolót.
- Az adatok a tárolón kívül élnek. A kötet nem tartalék. Használja a biztonsági mentési útmutatónkban található megközelítést: titkosított, külső, visszaállítással tesztelt.
- A titkok soha nem sülnek bele képekbe. Futás közben vigye át őket env-fájlokon vagy egy titokkezelőn keresztül, és tartsa távol őket a Gittől.
- Futtasson nem root felhasználóként, használjon csak olvasható fájlrendszert, ahol lehetséges, és dobja el azt, amire nincs szüksége.
- Tartsa frissen a képeket. Rendszeresen építse újra, hogy az alapkép és PHP biztonsági javításait vegye fel.
- Alkalmazza a PHP biztonsági ellenőrzőlistánk alkalmazásszintű vezérlőit, mivel a tárolók nem javítják a nem biztonságos kódot.
Gyártási készenléti ellenőrző lista
- Többlépcsős kép csak éles függőséggel, rögzített alapkép, nem root felhasználó.
- OPcache engedélyezve, a naplózott hibák nem jelennek meg, php-fpm méret a mért memóriából.
- Fájl létrehozása újraindítási házirendekkel, állapotellenőrzéssel, memóriakorlátokkal, naplóforgatással és nyilvános adatbázis-port nélkül.
- Kiadások commit-hash címkével, automatikus állapotellenőrzéssel és visszaállítással.
- Biztonsági mentések és tesztelt visszaállítás az adatbázishoz és a feltöltéshez.
- Monitoring és riasztások állapotról, lemezről, hibákról és tanúsítványokról.
Hogyan segíthetünk
Konténerbe helyezzük PHP alkalmazásokat, beállítjuk a CI-folyamatokat és kiadásokat, és összekapcsoljuk őket a fizetésekkel, a CRM-mel és az üzenetkezeléssel. Tekintse meg integrációs szolgáltatásunkat, vagy foglaljon telefonhívást, és felülvizsgáljuk a jelenlegi tárhely- és kiadási folyamatát.
Gyakori kérdések
Docker alkalmas PHP éles futtatására?
Igen, ha jól használják. Azonos környezeteket, megismételhető kiadásokat és gyors visszaállításokat biztosít. Megfelelő konfigurációt igényel: változtathatatlan képek, állapotellenőrzések, erőforráskorlátok, naplózás, titkok kezelése és a tárolón kívüli adatok biztonsági mentése.
Az adatbázisnak Docker kell futnia éles környezetben?
Kis és közepes rendszerek esetén is használható, ha állandó kötetet használ, soha nem teszik közzé nyilvánosan, és tesztelték a biztonsági másolatokat. A kritikus adatokhoz sok csapat a felügyelt adatbázis-szolgáltatást részesíti előnyben, amely kezeli a feladatátvételt, a frissítéseket és a biztonsági mentéseket.
Hogyan állíthatok vissza egy Docker kiadást?
Minden képhez jelölje meg a Git commit hash-t, és tartsa meg az előző címkét. A visszaállításhoz indítsa el a tárolókat az előző címkével. Írjon adatbázis-áttelepítéseket, hogy a régebbi kód továbbra is működjön az újabb sémával.
Hány php-fpm dolgozót kell beállítani?
Mérje meg egy dolgozó átlagos memóriáját terhelés alatt, döntse el, mennyi memóriát használhat PHP, és ossza fel. A túl magas érték cserét, míg a túl alacsony érték sorban állást okoz. Nézze meg a php-fpm naplót a max_children figyelmeztetésekért.
Mi a legnagyobb Docker biztonsági hiba a PHP alkalmazásokkal?
Titkok elhelyezése a képben vagy a Gitben és az adatbázis-portok közzététele az interneten. Kerülje továbbá a root felhasználóként való futtatást, a Docker foglalat konténerekbe való beszerelését és az alapkép frissítését.
Ingyenes felfedező hívás
Hozzon kaotikus stacket vagy elakadt integrációt - az Integrono feltérképezi a legokosabb első lépést.
Senior rálátást kap a költségvetési csapdákra, a függőségekre és arra, hogy vásároljon, ragasszon vagy építsen - mielőtt a fizetett munka elindul. A CEO a körben marad.