# Docker Deployment Guide This guide describes the recommended, repeatable way to run the Fotospiel platform in Docker for production or high-fidelity staging environments. It pairs a multi-stage build (PHP-FPM + asset pipeline) with a Compose stack that includes Nginx, worker processes, Redis, and MySQL. ## 1. Prerequisites - Docker Engine 24+ and Docker Compose v2. - A `.env` file for the application (see step 4). - Optional: an external MySQL/Redis if you do not want to run the bundled containers. ## 2. Build the application image ```bash docker compose build app ``` The build performs the following steps: 1. Installs Node dependencies and runs `npm run build` to produce production assets. 2. Installs PHP dependencies with Composer (`--no-dev --no-scripts`). 3. Creates a PHP 8.3 FPM image with required extensions (GD, intl, Redis, etc.). 4. Stores the compiled application under `/opt/app`; the runtime entrypoint syncs it into the shared volume when a container starts. ## 3. Configure environment Copy the sample Docker environment file and edit the secrets: ```bash cp docker/.env.docker docker/.env.docker.local ``` Set (at minimum): - `APP_KEY` — generate with `docker compose run --rm app php artisan key:generate --show`. - Database credentials (`DB_*`). The provided MySQL service defaults to `fotospiel/secret`. - `STORAGE_ALERT_EMAIL` — recipient for upload failure alerts (optional). Point `docker-compose.yml` to the file you created by either renaming it to `docker/.env.docker` or adjusting the `env_file` entries. ## 4. Boot the stack ```bash docker compose up -d ``` Services started: - `app`: PHP-FPM container serving the Laravel application. - `web`: Nginx proxy forwarding requests to PHP-FPM on port `8080` by default (`APP_HTTP_PORT`). - `queue` & `media-storage-worker`: queue consumers (default + media archival). - `scheduler`: runs `php artisan schedule:work`. - `horizon` (optional, disabled unless `--profile horizon` is supplied). - `redis` & `mysql`. ### Migrations & seeds Run once after the first boot or when deploying new schema changes: ```bash docker compose exec app php artisan migrate --force docker compose exec app php artisan db:seed --class=MediaStorageTargetSeeder --force ``` If you already have data, skip the seeder or seed only new records. ## 5. Queue & Horizon management Worker entrypoints live in `docs/queue-supervisor/`. The Compose services mount the same application volume so code stays in sync. Adjust concurrency by scaling services: ```bash docker compose up -d --scale queue=2 --scale media-storage-worker=2 ``` To enable Horizon (dashboard, smart balancing): ```bash docker compose --profile horizon up -d horizon ``` The dashboard becomes available at `/horizon` and is protected by the Filament super-admin auth guard. ## 6. Persistent data & volumes - `app-code` — contains the synced application, including the `storage` directory and generated assets. - `mysql-data` — MySQL data files. - `redis-data` — Redis persistence (disabled by default; change the Redis command if you want AOF snapshots). Back up the volumes before upgrades to maintain tenant media and database state. ## 7. Updating the stack 1. `git pull` the repository (or deploy your release branch). 2. `docker compose build app`. 3. `docker compose up -d`. 4. Run migrations + seeders if required. 5. Check logs: `docker compose logs -f app queue media-storage-worker`. Because the app image keeps the authoritative copy of the code, each container restart rsyncs fresh sources into the shared volume ensuring reliable updates without lingering artefacts. ## 8. Production hardening - Terminate TLS with a dedicated reverse proxy (Traefik, Caddy, AWS ALB, etc.) in front of the `web` container. - Point `APP_URL` to your public domain and enable trusted proxies. - Externalize MySQL/Redis to managed services for better resilience. - Configure backups for the `storage` directories and database dumps. - Hook into your observability stack (e.g., ship container logs to Loki or ELK). With the provided configuration you can bootstrap a consistent Docker-based deployment across environments while keeping queue workers, migrations, and asset builds manageable. Adjust service definitions as needed for staging vs. production.