From 799f74f00ad170d50bdd537671a0ded4ce0858a1 Mon Sep 17 00:00:00 2001 From: Michael Schiemer Date: Sun, 26 Oct 2025 23:30:43 +0100 Subject: [PATCH] feat(Production): Mount application code in PHP containers for live deployment - Mount /home/deploy/michaelschiemer/current:/var/www/html:ro in php and queue-worker services - This allows deployment via rsync without requiring Docker image rebuild - Storage volume still mounted as writable overlay for runtime data - Change default DB_DRIVER to 'pgsql' for PostgreSQL Deployment Architecture: - rsync deploys code to /home/deploy/michaelschiemer/releases/{timestamp} - Atomic symlink switch to /home/deploy/michaelschiemer/current - PHP containers mount current/ for immediate code updates - No rebuild needed - code changes are live after symlink switch Benefits: - Faster deployments (no Docker rebuild) - Code changes reflected immediately - Zero-downtime releases - Easy rollback via symlink change --- docker-compose.production.yml | 25 ++++++++++++------- .../Platform/DatabasePlatformInitializer.php | 5 ++-- 2 files changed, 18 insertions(+), 12 deletions(-) diff --git a/docker-compose.production.yml b/docker-compose.production.yml index 231778bb..22416f06 100644 --- a/docker-compose.production.yml +++ b/docker-compose.production.yml @@ -17,12 +17,17 @@ services: # Production restart policy restart: always - # Override volumes - use Let's Encrypt certificates + # Production port mappings for Let's Encrypt + ports: + - "80:80" # HTTP for ACME challenge + - "443:443" # HTTPS for production traffic + + # Override volumes - use Let's Encrypt certificates and mount application code volumes: - certbot-conf:/etc/letsencrypt:ro - certbot-www:/var/www/certbot:ro - # Remove development host mounts for security - # Application code deployed via Docker image build + # Application code via rsync deployment + - /home/deploy/michaelschiemer/current:/var/www/html:ro environment: - APP_ENV=production @@ -110,10 +115,11 @@ services: memory: 512M cpus: '1.0' - # Remove development volumes + # Production volumes volumes: - # Mount entire storage directory as single volume to avoid subdirectory mount issues - # on read-only overlay filesystem + # Mount application code from rsync deployment (read-only) + - /home/deploy/michaelschiemer/current:/var/www/html:ro + # Mount storage directory as writable volume (overlays the read-only code mount) - storage:/var/www/html/storage:rw # Mount .env file from shared directory (production environment variables) - /home/deploy/michaelschiemer/shared/.env.production:/var/www/html/.env:ro @@ -203,10 +209,11 @@ services: # Worker command - executed after entrypoint setup command: ["php", "/var/www/html/worker.php"] - # Remove development volumes + # Production volumes volumes: - # Mount entire storage directory as single volume to avoid subdirectory mount issues - # on read-only overlay filesystem + # Mount application code from rsync deployment (read-only) + - /home/deploy/michaelschiemer/current:/var/www/html:ro + # Mount storage directory as writable volume (overlays the read-only code mount) - storage:/var/www/html/storage:rw # Mount .env file from shared directory (production environment variables) - /home/deploy/michaelschiemer/shared/.env.production:/var/www/html/.env:ro diff --git a/src/Framework/Database/Platform/DatabasePlatformInitializer.php b/src/Framework/Database/Platform/DatabasePlatformInitializer.php index d7f0423b..2fcd0cd3 100644 --- a/src/Framework/Database/Platform/DatabasePlatformInitializer.php +++ b/src/Framework/Database/Platform/DatabasePlatformInitializer.php @@ -14,13 +14,12 @@ final readonly class DatabasePlatformInitializer { public function __construct( private Environment $environment - ) { - } + ) {} #[Initializer] public function __invoke(): DatabasePlatform { - $driver = $this->environment->get('DB_DRIVER', 'mysql'); + $driver = $this->environment->get('DB_DRIVER', 'pgsql'); return match($driver) { 'mysql', 'mysqli' => new MySQLPlatform(),