0Pricing
PHP Academy · Lektion

Eine PHP-Anwendung containerisieren

Eine produktionsreife PHP-Dockerfile schreiben

Eine PHP-Anwendung containerisieren ist eine kostenlose PHP Academy-Lektion auf CoddyKit. Dies ist Lektion 1 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des PHP Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.

Warum PHP containerisieren

PHP reproduzierbar auszuliefern bedeutet, die exakte Interpreter-Version, Erweiterungen und Betriebssystembibliotheken zusammen mit Ihrem Code festzuschreiben. Ein Docker-Image stellt jeder Umgebung – Laptop, CI und Produktion – dasselbe php -v und dasselbe Set von ext-* bereit.

In dieser Lektion erstellen wir ein produktionsbereites Image: PHP-FPM, nur die benötigten Erweiterungen, abgestimmte Konfigurationen, einen Nicht-Root-Benutzer und einen Health Check.

FPM- oder Apache-Basis

Die offiziellen PHP-Images gibt es in verschiedenen Varianten. Für eine Produktions-Webanwendung hinter nginx/traefik bevorzugen Sie php:8.3-fpm-alpine (klein) oder php:8.3-fpm (Debian, glibc – weniger Überraschungen bei nativen Bibliotheken).

  • cli – Worker, Queues, Cron
  • fpm – FastCGI-Prozessmanager, zusammen mit nginx
  • apache – mitgeliefertes Apache, praktisch, aber schwerer

Fixieren Sie die Minor-Version. Verwenden Sie in der Produktion niemals :latest.

# Base image choice in your Dockerfile
FROM php:8.3-fpm-alpine AS base

# Why alpine? ~30MB base vs ~140MB Debian.
# Tradeoff: musl libc, occasional native-extension friction.

Erweiterungen installieren

Verwenden Sie in diesen Images niemals apt install php-xxx – nutzen Sie die mitgelieferten Helfer docker-php-ext-install, docker-php-ext-configure und pecl. Das Skript install-php-extensions von mlocati ist die de-facto-Abkürzung und lädt die passenden Entwicklungs-Header für Sie herunter.

FROM php:8.3-fpm-alpine

# Grab the helper that resolves build deps automatically
ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/

RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions \
        pdo_mysql \
        opcache \
        intl \
        zip \
        redis \
        bcmath

Composer im Image

Kopieren Sie die Composer-Binärdatei aus ihrem offiziellen Image, statt einen Installer zu curlen. Führen Sie für die Produktion composer install mit --no-dev und --optimize-autoloader aus und kopieren Sie zuerst ausschließlich composer.json/composer.lock, damit die Abhängigkeitsschicht unabhängig von Änderungen am Quellcode im Cache bleiben kann.

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer

WORKDIR /app

# Cache-friendly: deps layer invalidates only when lock changes
COPY composer.json composer.lock ./
RUN composer install \
        --no-dev \
        --no-scripts \
        --no-autoloader \
        --prefer-dist

COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative

php.ini abstimmen

Das Basis-Image liefert die Vorlagen php.ini-production und php.ini-development mit. Aktivieren Sie die Produktionsvorlage und legen Sie anschließend Ihre eigenen Überschreibungen in conf.d ab – dieses Verzeichnis wird zuletzt zusammengeführt und setzt sich daher durch.

Wichtige Werte für die Produktion: opcache.enable=1, opcache.validate_timestamps=0 (unveränderlicher Code im Image) und ein sinnvoll gesetztes memory_limit.

# Activate production ini
RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"

# Custom overrides win because conf.d loads last
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/zz-app.ini

Die OPcache-Override-Datei

Das ist der größte einzelne Vorteil für die Produktion. Mit validate_timestamps=0 prüft PHP bei jeder Anfrage keine Dateien per stat – das bedeutet allerdings, dass Sie das Image zum Ausliefern von Änderungen ZWINGEND neu erstellen müssen (was für unveränderliche Container genau das gewünschte Verhalten ist).

; docker/php/zz-app.ini
memory_limit = 256M
expose_php = Off

opcache.enable = 1
opcache.enable_cli = 0
opcache.memory_consumption = 256
opcache.interned_strings_buffer = 16
opcache.max_accelerated_files = 20000
opcache.validate_timestamps = 0
opcache.preload = /app/preload.php
opcache.preload_user = www-data

Als Nicht-Root ausführen

Das Image definiert bereits www-data. FPM als Root auszuführen, vergrößert die Angriffsfläche ohne Not. Setzen Sie den Eigentümer beschreibbarer Pfade (Cache, Logs) und wechseln Sie mit USER vor CMD zu diesem Benutzer.

Bindet der FPM-Masterprozess weiterhin privilegierte Ports? Nein – FPM lauscht auf 9000 (nicht privilegiert), daher ist die Ausführung als Nicht-Root unkompliziert.

# Make runtime-writable dirs owned by the runtime user
RUN chown -R www-data:www-data /app/var /app/storage 2>/dev/null || true

USER www-data

EXPOSE 9000
CMD ["php-fpm"]

Health Checks

Orchestratoren benötigen ein Signal, dass FPM tatsächlich aktiv ist, nicht nur, dass der Prozess existiert. cgi-fcgi kann den FPM-Endpunkt /status oder /ping anpingen. Aktivieren Sie zuerst pm.status_path und ping.path im FPM-Pool.

# In www.conf pool config:
;   ping.path = /ping
;   ping.response = pong

# Dockerfile HEALTHCHECK using cgi-fcgi
RUN install-php-extensions @composer >/dev/null 2>&1 || true

HEALTHCHECK --interval=10s --timeout=3s --retries=3 \
  CMD SCRIPT_NAME=/ping SCRIPT_FILENAME=/ping REQUEST_METHOD=GET \
      cgi-fcgi -bind -connect 127.0.0.1:9000 || exit 1

Dockerfile zusammensetzen

Hier ist ein konsistentes Dockerfile für die Produktion mit einer einzigen Stage. In der nächsten Lektion teilen wir es in mehrere Stages auf, um Build-Tools zu entfernen. Beachten Sie die Reihenfolge: Abhängigkeiten → Konfiguration → Quellcode → Autoload → Benutzerwechsel.

FROM php:8.3-fpm-alpine

ADD https://github.com/mlocati/docker-php-extension-installer/releases/latest/download/install-php-extensions /usr/local/bin/
RUN chmod +x /usr/local/bin/install-php-extensions && \
    install-php-extensions pdo_mysql opcache intl zip redis

COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
WORKDIR /app

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"
COPY docker/php/zz-app.ini $PHP_INI_DIR/conf.d/

COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --no-autoloader --prefer-dist
COPY . .
RUN composer dump-autoload --optimize --classmap-authoritative && \
    chown -R www-data:www-data /app/var

USER www-data
EXPOSE 9000
CMD ["php-fpm"]

Build überprüfen

Überprüfen Sie nach dem Build kurz, was tatsächlich im Image gelandet ist: die PHP-Version, die geladenen Erweiterungen und dass die OPcache-Validierung deaktiviert ist. Ein kurzes CLI-Skript bestätigt die Laufzeitbedingungen, von denen Ihre Anwendung abhängt.

<?php
// Run inside the container: php verify.php
echo 'PHP ' . PHP_VERSION . PHP_EOL;

$required = ['pdo_mysql', 'opcache', 'intl', 'zip'];
foreach ($required as $ext) {
    printf("%-12s %s\n", $ext, extension_loaded($ext) ? 'OK' : 'MISSING');
}

var_dump((bool) ini_get('opcache.enable'));
?>

Build-Kontext sauber halten

Eine .dockerignore hält den Build-Kontext klein und verhindert, dass Secrets und ein aufgeblähtes vendor-Verzeichnis ins Image gelangen und den Cache ungültig machen. Schließen Sie vendor, VCS, Umgebungsdateien und lokale Tools aus.

# .dockerignore
.git
.gitignore
vendor/
node_modules/
.env
.env.*
tests/
*.md
docker-compose*.yml
storage/logs/*
var/cache/*

Kurzprüfung

Warum setzt man opcache.validate_timestamps=0 in einem Produktions-Image?

Zusammenfassung

Sie haben ein PHP-FPM-Produktions-Image erstellt: mit dem festgelegten Basis-Image 8.3-fpm-alpine, ausschließlich den benötigten Erweiterungen über das Installationsskript, Composer und zwischengespeicherten Abhängigkeiten in einer eigenen Layer, der aktivierten Produktionsversion von php.ini mit einer OPcache-Überschreibung, dem Wechsel zu www-data und einem FPM-Healthcheck.

Wichtige Gewohnheiten: Versionen festlegen, die Abhängigkeiten-Layer cachen, als Nicht-Root-Benutzer ausführen, die Zeitstempelvalidierung deaktivieren und den Build-Kontext mit .dockerignore schlank halten.

Häufig gestellte Fragen

Ist die Lektion „Eine PHP-Anwendung containerisieren“ kostenlos?

Ja — der vollständige Text von „Eine PHP-Anwendung containerisieren“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des PHP Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der PHP Academy-Kurs umfasst insgesamt 4 Lektionen.

Was lerne ich in „Eine PHP-Anwendung containerisieren“?

Eine produktionsreife PHP-Dockerfile schreiben Du übst PHP Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um PHP Academy zu starten?

Keine Vorkenntnisse erforderlich. PHP Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 1 von 4.

Wie lange dauert die Lektion „Eine PHP-Anwendung containerisieren“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser PHP Academy-Lektion Code schreiben und ausführen?

Ja. Jede PHP Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. Eine PHP-Anwendung containerisieren
  2. Multi-Stage-Builds und Optimierung
  3. Docker Compose für lokale Stacks
  4. CI/CD mit GitHub Actions
← Zurück zu PHP Academy