One compose file, seven services
nginx, PHP, Vue SSR, MySQL, Redis, Memcached, and the queue now come up from one file. A fresh checkout is three commands.
The site stack is no longer a mix of local PHP, a Node script, and a database that someone else started. One compose file brings up nginx, php, queue, schedule, vue, mysql, redis, and memcached. The PHP image is a local laraboom-php:latest plus redis and memcached extensions, so a slow registry does not block the first run.
Bring-up is three steps. Copy the two env files. Build and start compose. Run composer setup inside the PHP container. Setup writes the app key, waits until MySQL accepts connections, runs migrations, seeds the public content, and links storage.
Why the wait matters
Migrations used to fail on a cold start. MySQL was still initialising. The error looked like bad credentials. The setup script now retries the connection for a bounded time and names the service it is waiting on. A second run is safe. Seeds replace demo rows instead of duplicating them.
The build is staged. Lockfiles install in an early layer. The frontend build has its own stage. Only the output lands in the runtime image. A PHP edit no longer reinstalls Composer packages. Rebuilds dropped from minutes to seconds.
What still has to be healthy
nginx must not route SSR until the vue container is up. Otherwise the first hit is an empty shell. Storage volume uid has to match the PHP user, or uploads fail only after the first admin login. Queue and schedule are separate processes, so a long job cannot delay a cron tick.
The check after a fresh checkout is short. Home HTML comes from Vue SSR. /api/user answers without a token. Redis and Memcached accept a ping from the PHP container. If any of those fail, the compose file is the place to look, not a host routes folder.
