Docker Compose service configurations for Laravel with Spin.
php artisan boost:add-skill serversideup/spin
Save this content to: .claude/skills/spin-laravel-development-laravel-services/SKILL.md
# Laravel Services
Docker Compose service configurations for Laravel with Spin.
Service names, exposed ports, and `*.dev.test` domains below are the Spin template defaults — always verify against the project's actual compose files, since projects can rename or restructure any of this.
## Table of contents
- [Connection pattern](#connection-pattern)
- [MySQL](#mysql)
- [PostgreSQL](#postgresql)
- [MariaDB](#mariadb)
- [SQLite](#sqlite)
- [Redis](#redis)
- [Laravel Queues](#laravel-queues)
- [Laravel Horizon](#laravel-horizon)
- [Laravel Reverb](#laravel-reverb)
- [Laravel Task Scheduler](#laravel-task-scheduler)
- [Laravel Octane](#laravel-octane)
- [Vite](#vite)
- [Mailpit](#mailpit)
- [Meilisearch](#meilisearch)
---
## Connection pattern
In Docker, services connect via **service name as hostname** (as defined in the project's compose file):
```env
DB_HOST=mysql # NOT localhost, NOT 127.0.0.1
REDIS_HOST=redis
MAIL_HOST=mailpit
```
Avoid special characters in passwords — use long (20+) alphanumeric strings.
Database credentials are only created on **first container initialization**. To reset, remove the volume and re-run `spin up`.
---
## MySQL
`.env` configuration:
```env
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=laravelpassword
```
Templates typically expose it on `localhost:3306` in development for GUI database clients — check the dev override file.
---
## PostgreSQL
`.env` configuration:
```env
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=laravelpassword
```
Templates typically expose it on `localhost:5432` in development — check the dev override file.
---
## MariaDB
Drop-in replacement for MySQL. Uses the same `DB_CONNECTION=mysql`.
```env
DB_CONNECTION=mysql
DB_HOST=mariadb
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=laravelpassword
```
---
## SQLite
Spin stores the SQLite database in `.infrastructure/volume_data/sqlite/` to allow volume mounting without overwriting Laravel files.
```env
DB_CONNECTION=sqlite
DB_DATABASE=/var/www/html/.infrastructure/volume_data/sqlite/database.sqlite
```
The path uses the **container path** (`/var/www/html/`), not the host path.
---
## Redis
```env
REDIS_HOST=redis
REDIS_PASSWORD=redispassword
```
Installing Laravel Horizon automatically includes Redis.
---
## Laravel Queues
Dedicated queue worker service. Default command:
```bash
php artisan queue:work --tries=3
```
Runs as a separate Docker service alongside the main PHP service.
---
## Laravel Horizon
Dashboard and queue manager for Redis queues. Default command:
```bash
php artisan horizon
```
Access the dashboard at `http://<app-url>/horizon`.
Automatically installs Redis when selected.
---
## Laravel Reverb
WebSocket server for real-time features. Default command:
```bash
php artisan reverb:start
```
Development URL: `wss://reverb.dev.test`
Production requires a **separate DNS entry** from your app domain. Example: if your app is at `app.example.com`, set up `socket.example.com` pointing to the same server, and configure:
```env
REVERB_HOST=socket.example.com
```
---
## Laravel Task Scheduler
Runs scheduled tasks every minute. Default command:
```bash
php artisan schedule:work
```
---
## Laravel Octane
High-performance application server using FrankenPHP. Default command:
```bash
php artisan octane:start --server=frankenphp --port=8080
```
Requires the `frankenphp` image variant (see [DOCKER-IMAGES.md](DOCKER-IMAGES.md)).
---
## Vite
Development asset server with HMR over HTTPS.
Development URL: `https://vite.dev.test`
Default `vite.config.js` for Spin:
```js
import fs from 'fs';
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
server: {
host: '0.0.0.0',
hmr: {
host: 'vite.dev.test',
clientPort: 443,
},
https: {
key: fs.readFileSync('/usr/src/app/.infrastructure/conf/traefik/dev/certificates/local-dev-key.pem'),
cert: fs.readFileSync('/usr/src/app/.infrastructure/conf/traefik/dev/certificates/local-dev.pem'),
},
},
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});
```
Run with `spin run node yarn dev` (substitute the project's package manager and service name).
For production HTTPS asset loading, add to `AppServiceProvider::register()`:
```php
if ($this->app->environment('production') || $this->app->environment('dev')) {
URL::forceScheme('https');
}
```
---
## Mailpit
Local email testing (development only).
URL: `https://mailpit.dev.test`
```env
MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=
```
The Mailpit container may take ~15 seconds to start. If you see a 404 immediately after `spin up`, wait and retry.
---
## Meilisearch
Full-text search engine. Integrates with Laravel Scout.
Development UI: `https://meilisearch.dev.test`
```env
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://meilisearch:7700
MEILISEARCH_KEY=developmentkey1234567890
```
For production, set a secure key (20+ alphanumeric characters). Avoid running the Meilisearch UI in production unless properly secured.
Docker Compose service configurations for Laravel with Spin.
Service names, exposed ports, and *.dev.test domains below are the Spin template defaults — always verify against the project's actual compose files, since projects can rename or restructure any of this.
In Docker, services connect via service name as hostname (as defined in the project's compose file):
DB_HOST=mysql # NOT localhost, NOT 127.0.0.1
REDIS_HOST=redis
MAIL_HOST=mailpit
Avoid special characters in passwords — use long (20+) alphanumeric strings.
Database credentials are only created on first container initialization. To reset, remove the volume and re-run spin up.
.env configuration:
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=laravelpassword
Templates typically expose it on localhost:3306 in development for GUI database clients — check the dev override file.
.env configuration:
DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=laravelpassword
Templates typically expose it on localhost:5432 in development — check the dev override file.
Drop-in replacement for MySQL. Uses the same DB_CONNECTION=mysql.
DB_CONNECTION=mysql
DB_HOST=mariadb
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laraveluser
DB_PASSWORD=laravelpassword
Spin stores the SQLite database in .infrastructure/volume_data/sqlite/ to allow volume mounting without overwriting Laravel files.
DB_CONNECTION=sqlite
DB_DATABASE=/var/www/html/.infrastructure/volume_data/sqlite/database.sqlite
The path uses the container path (/var/www/html/), not the host path.
REDIS_HOST=redis
REDIS_PASSWORD=redispassword
Installing Laravel Horizon automatically includes Redis.
Dedicated queue worker service. Default command:
php artisan queue:work --tries=3
Runs as a separate Docker service alongside the main PHP service.
Dashboard and queue manager for Redis queues. Default command:
php artisan horizon
Access the dashboard at http://<app-url>/horizon.
Automatically installs Redis when selected.
WebSocket server for real-time features. Default command:
php artisan reverb:start
Development URL: wss://reverb.dev.test
Production requires a separate DNS entry from your app domain. Example: if your app is at app.example.com, set up socket.example.com pointing to the same server, and configure:
REVERB_HOST=socket.example.com
Runs scheduled tasks every minute. Default command:
php artisan schedule:work
High-performance application server using FrankenPHP. Default command:
php artisan octane:start --server=frankenphp --port=8080
Requires the frankenphp image variant (see DOCKER-IMAGES.md).
Development asset server with HMR over HTTPS.
Development URL: https://vite.dev.test
Default vite.config.js for Spin:
import fs from 'fs';
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
export default defineConfig({
server: {
host: '0.0.0.0',
hmr: {
host: 'vite.dev.test',
clientPort: 443,
},
https: {
key: fs.readFileSync('/usr/src/app/.infrastructure/conf/traefik/dev/certificates/local-dev-key.pem'),
cert: fs.readFileSync('/usr/src/app/.infrastructure/conf/traefik/dev/certificates/local-dev.pem'),
},
},
plugins: [
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});
Run with spin run node yarn dev (substitute the project's package manager and service name).
For production HTTPS asset loading, add to AppServiceProvider::register():
if ($this->app->environment('production') || $this->app->environment('dev')) {
URL::forceScheme('https');
}
Local email testing (development only).
URL: https://mailpit.dev.test
MAIL_MAILER=smtp
MAIL_HOST=mailpit
MAIL_PORT=1025
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=
The Mailpit container may take ~15 seconds to start. If you see a 404 immediately after spin up, wait and retry.
Full-text search engine. Integrates with Laravel Scout.
Development UI: https://meilisearch.dev.test
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://meilisearch:7700
MEILISEARCH_KEY=developmentkey1234567890
For production, set a secure key (20+ alphanumeric characters). Avoid running the Meilisearch UI in production unless properly secured.
How can I help you explore Laravel packages today?