Laravel Docker Deployment: Sauber deployen mit Docker Compose
Einleitung: Warum Laravel Docker Deployment?
Moderne Laravel-Projekte stoßen schnell auf Probleme wie inkonsistente Umgebungen, langwierige Server-Konfiguration und schwierige Skalierung. Mit Laravel Docker Deployment nutzt du Containerisierung, um lokale und Produktionsumgebungen identisch zu gestalten, Abhängigkeiten klar zu definieren und Deployments zu automatisieren. In diesem Artikel lernst du praxisnah, wie du deine Projektstruktur aufsetzt, maßgeschneiderte Dockerfiles und eine docker-compose.yml erstellst, Performance-Optimierungen umsetzt und eine CI/CD-Pipeline für automatisierte Deployments integrierst.
Voraussetzungen: Was brauchst du für das Laravel Docker Deployment?
Bevor du loslegst, solltest du folgende Tools und Kenntnisse mitbringen:
- Docker (Community Edition) installiert und lauffähig
- Docker Compose für dein Multi-Container-Setup
- Composer zur Verwaltung von PHP-Abhängigkeiten
- Git für Versionskontrolle und Deployment-Skripte
- Laravel-Grundkenntnisse (Routing, Migrationen, .env-Dateien)
- Terminal-/CLI-Erfahrung, um Container zu starten und Logs zu prüfen
- Code-Editor wie VS Code oder PHPStorm für komfortables Arbeiten
Projektstruktur und Dockerfile – So bereitest du deine Laravel-App vor
Projektstruktur im Überblick
Lege im Wurzelverzeichnis deiner Laravel-App folgende Struktur an:
my-laravel-app/
├─ app/ # Applikationscode
├─ bootstrap/ # Framework-Bootstrapping
├─ config/ # Konfigurationsdateien
├─ database/ # Migrationen & Seeds
├─ public/ # Webroot: index.php, Assets
├─ resources/ # Views, SCSS, JS-Ressourcen
├─ routes/ # Route-Definitionen
├─ storage/ # Logs, Caches, Uploads
├─ tests/ # Unit- & Feature-Tests
├─ Dockerfile # PHP-FPM-Container-Build
├─ docker-compose.yml # Multi-Container-Orchestrierung
├─ .env # Umgebungsvariablen
└─ composer.json # PHP-Abhängigkeiten
Damit hast du deine Laravel-Struktur um Docker-Konfigurationsdateien erweitert. So bleibt alles sauber getrennt und sofort einsatzbereit für Container.
Aufbau des Dockerfile
Erstelle im Projekt-Root ein Dockerfile mit folgendem Inhalt:
# 1. Basis-Image mit PHP-FPM
FROM php:8.1-fpm
# 2. Systemabhängigkeiten installieren
RUN apt-get update && apt-get install -y \
libzip-dev zip unzip git \
&& docker-php-ext-install pdo_mysql zip bcmath \
&& pecl install xdebug \
&& docker-php-ext-enable xdebug
# 3. Composer aus dem offiziellen Image übernehmen
COPY --from=composer:2 /usr/bin/composer /usr/bin/composer
# 4. Arbeitsverzeichnis setzen
WORKDIR /var/www/html
# 5. Composer-Install separiert für effektivere Layer-Caches
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
# 6. Anwendungscode kopieren
COPY . .
# 7. Dateiberechtigungen für Storage & Cache
RUN chown -R www-data:www-data storage bootstrap/cache
# 8. Port freigeben & Startbefehl
EXPOSE 9000
CMD ["php-fpm"]
Dieses Dockerfile richtet einen schlanken PHP-FPM-Container ein, installiert Systembibliotheken und PHP-Extensions, bindet Composer direkt ein und optimiert durch frühes composer install den Cache-Aufbau. Die korrekten Berechtigungen stellen sicher, dass Laravel Logs und Caches schreiben kann.
docker-compose.yml konfigurieren: Nginx, PHP-FPM und MySQL zusammenbringen
Jetzt legen wir eine docker-compose.yml an, die deine Laravel-App im Container-Netzwerk betreibt:
version: '3.8'
services:
app:
build:
context: .
dockerfile: Dockerfile
image: laravel_app
container_name: laravel_app
volumes:
- ./:/var/www/html
env_file:
- .env
networks:
- laravel_network
webserver:
image: nginx:alpine
container_name: laravel_nginx
ports:
- "80:80"
volumes:
- ./:/var/www/html:ro
- ./nginx/default.conf:/etc/nginx/conf.d/default.conf:ro
depends_on:
- app
networks:
- laravel_network
db:
image: mysql:8.0
container_name: laravel_db
restart: unless-stopped
volumes:
- dbdata:/var/lib/mysql
environment:
- MYSQL_DATABASE=${DB_DATABASE}
- MYSQL_USER=${DB_USERNAME}
- MYSQL_PASSWORD=${DB_PASSWORD}
- MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
ports:
- "3306:3306"
networks:
- laravel_network
volumes:
dbdata:
networks:
laravel_network:
driver: bridge
Erklärung der wichtigsten Abschnitte:
- version: Definiert die Compose-Datei-Version für neue Features.
- app: Baut den PHP-FPM-Container aus deinem
Dockerfile, bindet den Code und lädt Umgebungsvariablen aus.env. - webserver: Nutzt
nginx:alpine, mappt Port 80 und lädt deine Nginx-Konfiguration (readonly). - db: Startet MySQL 8.0 mit Credentials aus
.env, speichert Daten persistent indbdata. - networks & volumes: Erstellt ein isoliertes Netzwerk und ein Volume für die Datenbank.
Mit diesem Setup startest du alle drei Services gleichzeitig, stellst identische Umgebungen sicher und erleichterst spätere Skalierung.
Umgang mit .env-Dateien und Secrets sicher gestalten
Sensible Umgebungsvariablen und geheime Schlüssel gehören nicht ins Repository. So stellst du Sicherheit und Flexibilität sicher:
-
.env aus Git ausschließen
- Trage
.envin.gitignoreein, versieh dein Repo stattdessen mit einer.env.example. - So haben alle Entwickler die Vorlage, ohne echte Secrets zu riskieren.
- Trage
-
Env-Files im Docker-Umfeld
- Nutze in
docker-compose.ymldie Direktiveenv_file, um Variablen aus einer lokalen Datei zu laden:
services: app: env_file: - .env- Achte darauf, dass
.envauf deinem CI-Server oder im Produktiv-Cluster sicher bereitgestellt wird (z. B. per Secret-Management).
- Nutze in
-
Docker Secrets (für Swarm & Kubernetes)
- Lagere kritische Daten in Docker Secrets aus statt in Umgebungsvariablen:
services: app: secrets: - laravel_env secrets: laravel_env: file: ./secrets/.env.production- Im Container erreichst du sie unter
/run/secrets/laravel_envund bittest Laravel, diese Datei zu parsen.
-
Laravel-Konfiguration cachen
- Nach dem Deployment führst du aus:
php artisan config:cache- So werden Umgebungswerte einmalig geladen und gelten performant im OPCache, ohne dass
.envbei jedem Request gelesen wird.
-
Externe Secret-Manager
- AWS Secrets Manager, HashiCorp Vault oder Azure Key Vault lassen sich per SDK oder CLI anbinden.
- Zieh Secrets bei Container-Start dynamisch, statt sie fest einzubetten.
Mit diesen Maßnahmen verhinderst du versehentliches Auschecken geheimer Schlüssel, behältst volle Kontrolle über Zugriffsrechte und sorgst für einen sauberen, skalierbaren Deployment-Workflow.
Performance optimieren: OPCache und Queue-Worker in Laravel unter Docker
OPCache-Einstellungen anpassen
Um deine Laravel-App performant zu betreiben, aktivierst du OPCache im PHP-Container und passt die Parameter an:
- Lege eine
opcache.iniim Projekt-Root an:
[opcache]
opcache.enable=1
opcache.memory_consumption=128 ; maximaler Speicher in MB
opcache.interned_strings_buffer=8 ; Buffer für interned Strings
opcache.max_accelerated_files=10000 ; Anzahl gecachter Dateien
opcache.validate_timestamps=0 ; setze 1 in Dev, 0 in Prod
opcache.revalidate_freq=60 ; Sekunden bis Re-Validation
opcache.save_comments=1 ; für Annotationen nötig
- Binde die Datei im
Dockerfileein:
# OPCache-Config kopieren
COPY opcache.ini /usr/local/etc/php/conf.d/opcache.ini
- Baue das Image neu und prüfe mit
php -i | grep opcache, ob OPCache aktiv ist. - In Produktiv-Setups stellst du
validate_timestamps=0undrevalidate_freq=0ein, um Dateisystem-Checks zu vermeiden.
Queue-Worker als Docker-Service betreiben
So stellst du sicher, dass deine Jobs zuverlässig laufen und bei Fehlern neu starten:
- Ergänze deine
docker-compose.ymlum einenqueue-Service:
services:
queue:
build:
context: .
dockerfile: Dockerfile
container_name: laravel_queue
command: >
php artisan queue:work
--sleep=3
--tries=3
--timeout=90
restart: unless-stopped
volumes:
- ./:/var/www/html
env_file:
- .env
depends_on:
- db
networks:
- laravel_network
- Erklärungen:
--sleep=3: Wartezeit zwischen leeren Warteschlangen--tries=3: Anzahl maximaler Versuche pro Job--timeout=90: Sekunden, ehe ein Job abgebrochen wirdrestart: unless-stopped: Service restarts bei Fehlern automatisch
- Für größere Lasten empfiehlt sich Laravel Horizon oder ein Supervisor-Daemon im Container.
Mit aktiviertem OPCache und einem resilienten Queue-Worker-Service läuft deine Laravel-App unter Docker deutlich performanter und ausfallsicher.
CI/CD-Pipeline mit GitHub Actions für automatisiertes Laravel Deployment
Wir richten einen GitHub Actions Workflow ein, der beim Push in den main-Branch automatisch Build, Tests und Deployment auf deinem Server startet. Lege dazu die Datei .github/workflows/deploy.yml an:
name: CI/CD Laravel Docker
on:
push:
branches:
- main
jobs:
build-and-test:
runs-on: ubuntu-latest
steps:
- name: Repository klonen
uses: actions/checkout@v3
- name: PHP einrichten
uses: shivammathur/setup-php@v2
with:
php-version: '8.1'
extensions: mbstring, pdo_mysql, bcmath, zip
- name: Composer-Cache wiederverwenden
uses: actions/cache@v3
with:
path: vendor
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: |
${{ runner.os }}-composer-
- name: Abhängigkeiten installieren
run: composer install --no-dev --optimize-autoloader
- name: Tests ausführen
run: php artisan test --parallel
- name: Docker-Image bauen und pushen
uses: docker/build-push-action@v3
with:
context: .
push: true
tags: ${{ secrets.DOCKER_REGISTRY }}/laravel_app:${{ github.sha }}
deploy:
needs: build-and-test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- name: SSH-Verbindung zum Server
uses: appleboy/ssh-action@v0.1.7
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USER }}
key: ${{ secrets.SERVER_SSH_KEY }}
script: |
docker pull ${{ secrets.DOCKER_REGISTRY }}/laravel_app:${{ github.sha }}
docker-compose -f docker-compose.prod.yml up -d --remove-orphans
Erklärungen:
- Wir klonen das Repo und richten PHP in Version 8.1 mit den benötigten Extensions ein.
- Composer-Cache verringert Installationszeiten.
- Nach
composer installlaufen deine Laravel-Tests parallel. - Das Docker-Image wird in deine Registry gepusht – nutze dafür
DOCKER_REGISTRYals Secret. - Im Deploy-Job verbindet sich die Action per SSH mit deinem Server (Credentials als GitHub Secrets) und führt
docker-composeim Produktionsmodus aus.
So baust und verteilst du deine Laravel-App in Docker-Containern automatisiert und sicher – bei jedem Merge in den Hauptzweig.
Best Practices für Laravel Docker Deployment
Um deine Laravel-App unter Docker stabil, performant und sicher zu betreiben, solltest du folgende Empfehlungen befolgen:
-
Multi-Stage-Build einsetzen
Trenne Build- und Runtime-Umgebung, um nur die nötigen Artefakte im finalen Image zu haben und die Größe zu reduzieren. -
Minimal-Basisimages verwenden
Nutze schlanke Varianten wiephp:8.1-fpm-alpineodernginx:alpine, um Angriffsfläche und Image-Größe zu minimieren. -
Non-Root-User & Dateiberechtigungen
Lege im Dockerfile einen unprivilegierten User an (z. B.www-data) und setze mitchown/chmodkorrekte Rechte aufstorageundbootstrap/cache. -
Healthchecks definieren
Füge indocker-compose.ymleinen Healthcheck (z. B.CMD curl --fail http://localhost/health) hinzu, damit Orchestratoren Container-Zustände prüfen können. -
Ressourcenlimits & Restart-Policy
Definiere in Composemem_limit,cpusundrestart: unless-stopped, damit Container sich nach Fehlern selbst neu starten und nicht unbegrenzt Ressourcen verbrauchen. -
Secrets & Umgebungsvariablen sicher verwalten
Lade Konfigurationswerte perenv_file, Docker Secrets oder externe Vault-Systeme, halte deine.envaus dem Git-Repo fern und versioniere nur.env.example. -
Laravel-Konfiguration & Routen cachen
Baue in dein Deployment-Skriptphp artisan config:cache,route:cacheundview:cacheein, um Boot- und Routing-Zeiten deutlich zu verkürzen. -
OPCache & Autoloader optimieren
Aktiviere OPCache mit produktiven Settings (validate_timestamps=0) und verwendecomposer install --optimize-autoloaderfür schnellere Klassenladung. -
Automatische Datenbank-Migrationen
Integrierephp artisan migrate --forcein deine CI/CD-Pipeline oder als Entry-Point, damit Schema-Änderungen konsistent und ohne manuellen Eingriff ausgerollt werden. -
Netzwerk-Isolation & Firewall-Regeln
Platziere App-, Web- und DB-Container in separaten Docker-Netzwerken, beschränke direkte Datenbankzugriffe und definiere klare Firewall-Policies. -
Logging, Monitoring & Sicherheits-Updates
Leite Logs an Systeme wie ELK oder Papertrail weiter, überwache Container mit Prometheus/cAdvisor und scanne Images regelmäßig auf Schwachstellen.
Mit diesen Best Practices stellst du sicher, dass deine Laravel-App in Docker nicht nur performant läuft, sondern auch wartbar, sicher und skalierbar bleibt.
Fehlerbehebung & FAQ zu Laravel Docker Deployment
Häufige Probleme
-
502 Bad Gateway von Nginx
Ursache: PHP-FPM-Container ist nicht erreichbar.
Lösung: Prüfe Logs mitdocker-compose logs -f webserver docker-compose logs -f appund stell sicher, dass
fastcgi_pass app:9000in deiner Nginx-Config stimmt. -
Datenbank-Verbindung schlägt fehl
Ursache: Falsche Credentials oder Netzwerk-Setup.
Lösung:- Kontrolliere
.env-Werte (DB_HOST=db). - Starte
docker-compose up -d dbund teste mit
docker exec -it laravel_db mysql -u root -p${DB_ROOT_PASSWORD} - Kontrolliere
-
Dateiberechtigungen für Storage/Cache
Ursache: Container-User hat keinen Schreibzugriff.
Lösung:# im Dockerfile RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache USER www-data -
.env wird nicht geladen
Ursache:env_filefehlt oder Pfad stimmt nicht.
Lösung: Füge indocker-compose.ymlenv_file: - .envbeim
app-Service hinzu und baue neu. -
Memory exhausted bei Composer
Ursache: Standard-PHP-Limit zu gering.
Lösung: Erhöhe Memory-Limit im Dockerfile:
dockerfile
RUN echo "memory_limit=1G" >> /usr/local/etc/php/conf.d/memory.ini
Häufig gestellte Fragen
- Wie beobachte ich Logs aller Dienste?
Nutze
docker-compose logs -f
um alle Container-Logs in Echtzeit zu sehen.
-
Wie aktualisiere ich das Image ohne Downtime?
Setzedocker-compose up -d --no-deps --build webserver appein und nutze Healthchecks für Zero-Downtime-Rollouts. -
Kann ich Laravel Horizon in Docker betreiben?
Ja. Füge einfach einenhorizon-Service im Compose-File hinzu, ähnlich demqueue-Worker, und setzecommand: php artisan horizon. -
Wie stelle ich Cron-Jobs in Docker bereit?
Nutze einen separatencron-Service mitcommand: crond -fund mounte deinecrontab-Datei per Volume.
Mit diesen Tipps findest du Fehler schnell, löst typische Hürden und behältst den Überblick über dein Laravel-Docker-Deployment.
Fazit: Starte jetzt dein Laravel Docker Deployment – mit Erfolg!
Mit diesem Leitfaden zum Laravel Docker Deployment hast du alle Schritte – von der Projektstruktur über Umgebungsvariablen bis zur CI/CD-Pipeline – praxisnah umgesetzt. Richte deine Container so ein, dass sie sicher, performant und ausfallsicher laufen, automatisiere Builds und Deployments mit GitHub Actions und optimiere OPCache sowie Queue-Worker für echten Produktionsbetrieb. Starte jetzt dein erstes Deployment, teste deine Pipeline und teile deine Erfahrungen oder Fragen in den Kommentaren, damit wir gemeinsam noch besser werden!