Deploy
The published image is the same one used in dev — one image, three Compose files. Two prod shapes:
- Self-hosted prod (VPS / k8s,
docker-compose.prod.yml): a published image (read-only, hardened, non-rootuid 1000) does a one-shotphp artisan migrate --force, then starts the queue worker, scheduler, and Reverb sidecar against a remote libSQL database (Bunny Database, Turso, or your ownsqld). These are always-on processes on the self-hosted host, not CaaS sidecars (ADR 0009). - CaaS prod (Magic Containers, Cloud Run, Cloudflare): the same image runs the HTTP app + the first-run installer only. No
queue/reverb/schedulercontainers in the CaaS spec. Point Laravel at a self-hosted or vendor endpoint viaQUEUE_CONNECTIONandBROADCAST_CONNECTION(see Environment variables).
TLS terminates upstream; the container serves plain HTTP on :8080.
Three paths cover the rest:
- Magic Containers on Bunny — stateless pods, the
/installfirst-boot flow, and the env wiring Bunny expects. - Compose production —
docker-compose.prod.yml, the migrate sidecar, optional bundledsqld, and the Redis profile. - Secrets and keys —
APP_KEY, Passport PEMs, Bunny Storage S3 env, andINSTALLER_ENABLED.
Nothing is pushed unless you explicitly run build --push with your own registry user. The default docker-compose.build.yml builds linux/amd64 locally and leaves it on the host.