Docker pre PHP vo výrobe: praktický sprievodca nastavením pre podnikové aplikácie
Docker umožňuje, aby aplikácia PHP bežala rovnakým spôsobom na prenosnom počítači, pri testovaní a vo výrobe, a namiesto stresu robí rutinné vydania a návraty. Pridáva tiež pohyblivé časti a neopatrné nastavenie je horšie ako obyčajný server. Táto príručka ukazuje základnú líniu pripravenú na výrobu so skutočnou konfiguráciou a kedy by ste sa nemali obťažovať.
V skratke
- Docker stojí za to, keď chcete rovnaké prostredia, rýchle vrátenie späť a jednoduché začlenenie. Pre jednu malú brožúru na zdieľanom hostingu je to zvyčajne zbytočné.
- Vytvorte nemenný obraz v CI: viacstupňová zostava, iba produkčné závislosti, používateľ bez oprávnenia root, zapnutá OPcache, chyby sa zaznamenávajú a nikdy sa nezobrazujú.
- Uvoľnite pomocou značky obrázka (hash commit Git), po spustení skontrolujte stav a v prípade zlyhania kontroly sa automaticky vráťte k predchádzajúcej značke.
- Kontajnery sú na jedno použitie, údaje nie: uchovávajte databázu a nahrávané súbory vo zväzkoch alebo spravovaných službách a zálohujte ich mimo Docker.
- Najčastejšie chyby pri výrobe: tajomstvá v obraze, zverejnené databázové porty, neobmedzené protokoly a limity php-fpm, ktoré nezodpovedajú pamäti, ktorú máte.
Pri mnohých podnikových aplikáciách skutočnými nákladmi na hosting nie je server, ale ľudia. Nastavenie, ktorému rozumie iba jeden vývojár, nasadenie vykonávané ručne cez FTP a pracovné prostredie, ktoré sa správa inak ako produkčné, sú z dlhodobého hľadiska drahé. Kontajnery to riešia balením aplikácie s jej presnou verziou PHP a rozšíreniami. Prevádzkujeme naše vlastné stránky PHP a klientske systémy na zásobníku založenom na Dockeri a táto príručka popisuje základnú líniu, z ktorej vychádzame.
Kedy sa Docker oplatí a kedy nie
- Stojí za to: niekoľko služieb (web, PHP, databáza, front), viac ako jeden vývojár, potreba opakovateľných vydaní a rýchlych návratov alebo plán prechodu medzi poskytovateľmi.
- Nie je potrebné: jednoduchý obsahový web, ktorý sa na spravovanom hostingu len zriedka mení. Pridaná zložitosť si vyžaduje odplatu.
- Nie je náhradou za dobré operácie: stále potrebujete opravy, zálohy a monitorovanie. Pozrite si nášho sprievodcu zálohovaním a monitorovaním.
Cieľová architektúra
Pevné a jednoduché nastavenie pre aplikáciu PHP na jednom serveri:
- Reverzný proxy a TLS na okraji ( Nginx alebo Caddy na hostiteľovi alebo CDN, ako je Cloudflare, pozrite si nášho sprievodcu nastavením Cloudflare).
- Webový kontajner ( Nginx), ktorý obsluhuje statické súbory a prenáša požiadavky PHP ďalej.
- PHP-FPM kontajner s vaším kódom zabudovaným do obrazu.
- Databáza vo vlastnom kontajneri s trvalým objemom, alebo lepšie riadená databázová služba pre kritické dáta.
- Objemy len pre údaje, ktoré musia prežiť: databázové súbory a nahrané súbory používateľov.
Viacstupňový súbor Dockerfile
Viacstupňová zostava nainštaluje závislosti v jednej fáze a skopíruje iba výsledok do tenkého runtime obrazu. Konečný obrázok nemá žiadny Composer, kompilátory ani testovacie nástroje, čo ho robí menším a útočníkom umožňuje menej použitia:
# ---- 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
Zámerne si vyberte verziu PHP a skontrolujte, či je stále podporovaná. Náš sprievodca inováciou PHP 8 vysvetľuje, ako to naplánovať. Pripnite verzie základných obrázkov a aktualizujte ich podľa plánu, pretože obrázok, ktorý nikdy neprebudujete, hromadí známe zraniteľnosti. Udržujte .dockerignore, ktorý vylučuje .git, .env, testy a lokálne údaje, takže v obraze neskončí nič citlivé.
Produkcia PHP a konfigurácia php-fpm
# 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
Nastavenie opcache.validate_timestamps = 0 poskytuje najlepší výkon pre nemenný obrázok, ale funguje to iba vtedy, ak nikdy neupravujete súbory v spustenom kontajneri: namiesto toho uvoľníte nový obrázok. Veľkosť skupiny z reálnych čísel: zmerajte priemernú pamäť jedného pracovníka PHP pri zaťažení, rozhodnite sa, koľko pamäte môže PHP použiť na serveri, a rozdeľte. Ak pracovník používa 60 MB a vy môžete dať PHP 1 GB, pm.max_children je približne 16. Nastavenie oveľa vyššie spôsobí, že proces výmeny servera alebo proces zabíjania jadra počas špičky prevádzky. Príliš nízka a fronta žiadostí. Skontrolujte protokol php-fpm, či neobsahuje upozornenia „max_children reach“.
Vytvoriť súbor so správnymi predvolenými hodnotami
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:
web obrázok je malý obrázok Nginx so skopírovaným public/ priečinkom a konfiguráciou lokality, ktorý je zabudovaný v rovnakom postupe ako obrázok PHP. Kľúčové body: naviazať publikované porty na 127.0.0.1, nikdy nepublikovať databázu, nastaviť politiky reštartovania, obmedziť pamäť, aby jeden kontajner nemohol odstrániť hostiteľa, a obmedziť veľkosť protokolu. Pamätajte, že porty publikované Docker môžu obísť pravidlá brány firewall hostiteľa, ako vysvetľujeme v príručke Cloudflare. Nikdy nepripájajte zásuvku Docker do kontajnera aplikácie, pretože to dáva tomuto kontajneru kontrolu nad hostiteľom.
Uvoľnenia a návraty
Najlepšou vlastnosťou nastavenia založeného na obrázkoch je, že každé vydanie je značka a vrátenie je „začať predchádzajúcu značku“. Označte obrázky pomocou hash odovzdania Git, nikdy sa nespoliehajte na latest a nechajte skript vydania overiť stav:
#!/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
Zmeny databázy vyžadujú starostlivosť: migrácie zapíšte, aby predchádzajúca verzia kódu stále fungovala s novou schémou (najprv pridajte stĺpce, odstráňte ich v neskoršom vydaní). Práve to robí rýchly návrat bezpečným. Pred každým vydaním, ktoré zmení schému, urobte zálohu databázy.
Stavba a doprava z CI
Zostavte obraz raz v CI a nasaďte presne tento artefakt. Minimálny pracovný postup GitHub Actions:
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 }}"
Spustite svoje testy a statickú analýzu v rovnakom kanáli pred vytvorením obrazu a použite kľúč nasadenia, ktorý dokáže spustiť iba skript vydania. Ak to váš rizikový profil vyžaduje, pridajte skenovanie zraniteľnosti obrázkov.
Protokoly, údaje a bezpečnosť
- Záznamy idú na stdout a stderr, sú rotované Docker a pre čokoľvek dôležité sú odoslané na centrálne miesto, aby prežili kontajner.
- Dáta žijú mimo kontajnera. Zväzok nie je záloha. Použite prístup v našom sprievodcovi zálohovaním: šifrované, mimo lokality, testované na obnovenie.
- Tajomstvá sa nikdy nespracúvajú do obrázkov. Odovzdávajte ich za behu prostredníctvom súborov env alebo správcu tajomstiev a uchovávajte ich mimo Gitu.
- Spustite ako užívateľ typu non-root, používajte súborový systém len na čítanie tam, kde je to možné, a zahoďte to, čo nepotrebujete.
- Udržujte obrázky čerstvé. Pravidelne prestavujte, aby ste získali bezpečnostné opravy v základnom obraze a PHP.
- Použite ovládacie prvky na úrovni aplikácie z nášho kontrolného zoznamu zabezpečenia PHP, pretože kontajnery neopravujú nezabezpečený kód.
Kontrolný zoznam pripravenosti výroby
- Viacstupňový obrázok iba s produkčnými závislosťami, pripnutý základný obrázok, používateľ bez oprávnenia root.
- OPcache povolená, zaznamenané chyby sa nezobrazujú, veľkosť php-fpm z nameranej pamäte.
- Vytvorte súbor s politikami reštartu, zdravotnými kontrolami, limitmi pamäte, rotáciou protokolov a žiadnym verejným databázovým portom.
- Vydania pomocou tagu commit-hash s automatickou kontrolou stavu a návratom späť.
- Zálohy a testované obnovenie databázy a nahrávania.
- Monitorovanie a upozornenia na zdravie, disk, chyby a certifikáty.
Ako môžeme pomôcť
Kontajnerizujeme aplikácie PHP, nastavujeme kanály a vydania CI a prepájame ich s platbami, CRM a správami. Pozrite si našu integračnú službu alebo si rezervujte hovor a my skontrolujeme váš aktuálny proces hosťovania a vydania.
Časté otázky
Je Docker dobrý na spustenie PHP vo výrobe?
Áno, pri dobrom použití. Poskytuje identické prostredia, opakovateľné vydania a rýchle návraty. Potrebuje správnu konfiguráciu: nemenné obrázky, kontroly stavu, limity zdrojov, rotáciu protokolov, správu tajomstiev a zálohy údajov mimo kontajnera.
Mala by databáza bežať v Docker vo výrobe?
Môže to byť pre malé a stredné systémy, ak používa trvalý zväzok, nikdy nie je verejne prístupný a má testované zálohy. Pre kritické údaje mnohé tímy uprednostňujú spravovanú databázovú službu, ktorá sa postará o núdzové prepnutie, aktualizácie a zálohy za vás.
Ako vrátim späť vydanie Docker ?
Označte každý obrázok hashom odovzdania Git a ponechajte predchádzajúcu značku. Ak chcete vrátiť späť, začnite kontajnery s predchádzajúcou značkou. Napíšte migrácie databázy, aby starší kód stále fungoval s novšou schémou.
Koľko pracovníkov php-fpm by som mal nakonfigurovať?
Zmerajte priemernú pamäť jedného pracovníka pri zaťažení, rozhodnite, koľko pamäte môže PHP použiť, a rozdeľte. Nastavenie príliš vysokej hodnoty spôsobí swapovanie, zatiaľ čo príliš nízke spôsobuje požiadavky vo fronte. Pozrite si denník php-fpm, kde nájdete upozornenia max_children.
Aká je najväčšia bezpečnostná chyba Docker s aplikáciami PHP ?
Vloženie tajomstiev do obrazu alebo Git a publikovanie databázových portov na internet. Vyhnite sa tiež spúšťaniu ako root, pripájaniu soketu Docker do kontajnerov a nikdy neaktualizovaniu základného obrazu.
Bezplatný objavovací hovor
Prineste chaotický stack alebo zaseknutú integráciu - Integrono namapuje najmúdrejší prvý krok.
Dostanete seniorský pohľad na rozpočtové pasce, závislosti a na to, či kúpiť, zlepiť alebo postaviť - kým nezačne platená práca. CEO ostáva v okruhu.