Kit docs
Deployment
PHP ^8.513 pages
Docs for v0.2.1, from GitHub.
Pages in these docs
Kit ships a Dockerfile for a production image: Laravel Octane on
FrankenPHP, running as a non-root user on port 8000. CI builds it and
boots it with production settings on every push, so a change that breaks the image fails before it
reaches you.
You do not have to use it. Kit is a Laravel application and deploys anywhere Laravel does, including Laravel Cloud and Forge. Most of this page applies either way, since you still need the same processes, environment and release step.
What runs
| Process | Command | Why |
|---|---|---|
| Web | the image’s default | Serves the API |
| Queue worker | php artisan queue:work | Sends emails and webhook deliveries |
| Scheduler | php artisan schedule:work | Prunes webhook events daily |
All three run from the same image:
docker build -t my-api .
docker run -p 8000:8000 --env-file .env.production my-apidocker run --env-file .env.production my-api php artisan queue:workdocker run --env-file .env.production my-api php artisan schedule:workForget the worker and nobody receives a verification email or a webhook. Nothing errors either, which makes it an easy one to miss.
The image
Dependencies are installed without dev packages, from the same composer.lock Vet audited in CI,
with a classmap-authoritative autoloader. docker/php.ini tunes OPcache for production and turns
off timestamp checks, since the code never changes inside a running container. Logs go to stderr
for your platform to collect, and the health check hits /up every 30 seconds.
On start, docker/entrypoint.sh runs php artisan optimize, which caches config, routes and
events from the environment the container was given, and then starts Octane. Pass a command, as
the worker does, and it runs that instead.
These variables tune Octane:
| Variable | Default | Effect |
|---|---|---|
PORT | 8000 | The port to listen on |
OCTANE_WORKERS | auto | PHP workers; auto leaves the count to Octane |
OCTANE_MAX_REQUESTS | 500 | Requests a worker serves before it is replaced |
Environment
Production refuses to boot without the settings that depend on your deployment. At minimum:
APP_ENV=productionAPP_KEY=base64:...APP_DEBUG=falseAPP_URL=https://api.example.com
SECURITY_FORCE_HTTPS=trueTRUSTED_HOSTS=api.example.comCORS_ALLOWED_ORIGINS=https://app.example.com
DB_CONNECTION=pgsqlDB_HOST=...DB_DATABASE=...DB_USERNAME=...DB_PASSWORD=...
QUEUE_CONNECTION=databaseMAIL_MAILER=smtpThe image has the MySQL and PostgreSQL drivers as well as SQLite. Security explains each check, and Configuration lists every variable.
Put TLS in front of the container, at a load balancer or proxy, and forward X-Forwarded-Proto.
Check TRUSTED_PROXIES against your network too, because the default trusts whatever connects
directly.
Releasing
Run migrations as a release step, once, before the new containers take traffic:
docker run --env-file .env.production my-api php artisan migrate --forceThen replace the web, worker and scheduler containers. Workers in particular have to be restarted on every release, or they carry on running the old code.
Writing code that is safe under Octane
Octane keeps the application in memory between requests. That is where its speed comes from, and it is also how state leaks from one request into the next. Three rules keep that from happening:
- Keep request state out of singletons and static properties. Use
scoped()bindings, which Octane resets for each request; api-toolbox binds its request ID and trace context that way. - Resolve request state when the request is served, not in a closure that captured the application
at boot. Octane serves each request from a sandboxed copy of the application, so use
Container::getInstance()or the helpers inside such a closure, not a$this->appcaptured in a service provider. - Dev packages are not in the image. Config that refers to one, as
config/scribe.phpdoes, must return early when the package is missing, or the image fails to boot. CI catches this.
php artisan serve does not run Octane, so a leak will not show up locally. When you change
anything that holds state, build and run the image.