Skip to main content

spin-laravel-development

Develops, tests, and deploys Laravel applications using Spin and serversideup/php Docker images. Covers Docker Compose configuration, development environment setup, container commands, running Laravel tests (PHPUnit and Pest), SPIN_ENV selection and CI parity, parallel Compose environments, Laravel service configuration (databases, queues, Horizon, Reverb), server provisioning, and deployment workflows. Use when working with Spin, Docker Compose files, serversideup/php images, spin commands, running artisan test, configuring Laravel services in Docker, or deploying Laravel apps to production servers.

Quellinformationen

Repository
serversideup/spin
Letzte Quellaktivität
19. August 2026 um 17:00
Erkannte Sprache von SKILL.md
Englisch
Sterne
1.491
Forks
66

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

Datei-Explorer
7 Dateien

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
spin-laravel-development
description
Develops, tests, and deploys Laravel applications using Spin and serversideup/php Docker images. Covers Docker Compose configuration, development environment setup, container commands, running Laravel tests (PHPUnit and Pest), SPIN_ENV selection and CI parity, parallel Compose environments, Laravel service configuration (databases, queues, Horizon, Reverb), server provisioning, and deployment workflows. Use when working with Spin, Docker Compose files, serversideup/php images, spin commands, running artisan test, configuring Laravel services in Docker, or deploying Laravel apps to production servers.
# Spin Laravel Development ## Table of contents - [Safety guardrails](#safety-guardrails) - [Laravel Boost MCP](#laravel-boost-mcp) - [How Spin works](#how-spin-works) - [Project structure](#project-structure) - [Dockerfile pattern](#dockerfile-pattern) - [Development workflow](#development-workflow) - [Running tests](#running-tests) - [serversideup/php images](#serversideupphp-images) - [Laravel services](#laravel-services) - [Deployment](#deployment) - [Server provisioning](#server-provisioning) - [Common pitfalls](#common-pitfalls) - [Reference files](#reference-files) ## Safety guardrails - **NEVER** run commands that could destroy data without explicitly confirming with the user first. This includes `docker system prune`, `docker volume rm`, dropping databases, removing services, or any destructive operation. - Avoid `spin kill` — it kills **all containers on the machine** (not just this project) and requires interactive confirmation, which hangs in non-interactive contexts. Use `spin stop` or `spin down` for the project's stack. - If Spin fails to run, it is likely because Docker Desktop is not started. Check with `docker info`. If Docker is not running, tell the user to start Docker Desktop and offer to retry before continuing. - Use `spin exec` (running stack) or `spin run` (stopped stack), with `-T` in AI/CI/subprocess contexts — see [Running commands](#running-commands). - Projects start from templates but are free to restructure. Treat the project's own compose files, Dockerfile, and `.env` as the source of truth for service names, versions, ports, and paths — the examples in this skill show typical template defaults, not guarantees. ## Laravel Boost MCP Spin runs PHP inside Docker, not on the host machine. Laravel Boost's MCP server needs a bridge script (`spin-mcp-wait.sh`) that retries until Docker is ready and filters Docker's stdout noise to preserve the JSON-RPC stdio protocol. The required `.env` configuration: ```env BOOST_PHP_EXECUTABLE_PATH="./vendor/bin/spin-mcp-wait.sh ./vendor/bin/spin run -T php php" BOOST_COMPOSER_EXECUTABLE_PATH="./vendor/bin/spin run php composer" BOOST_NPM_EXECUTABLE_PATH="./vendor/bin/spin run node npm" ``` **NEVER use `spin-mcp-wait.sh` to run commands.** It is exclusively for MCP server startup. The script will refuse non-MCP invocations with this error: ``` Error: spin-mcp-wait.sh is only for starting the MCP server. Use 'spin' directly instead. ``` If that error appears, drop `spin-mcp-wait.sh` and invoke `spin` directly: ```bash ./vendor/bin/spin exec -T php php artisan test # Correct ./vendor/bin/spin run -T php php artisan migrate # Correct ./vendor/bin/spin-mcp-wait.sh ./vendor/bin/spin run php # WRONG — never do this ``` ## How Spin works Spin wraps Docker Compose and follows its syntax exactly. The compose-wrapping commands (`up`, `down`, `stop`, `build`, `logs`, `ps`, `pull`, `run`, `exec`) forward any additional flags straight to the wrapped `docker compose` subcommand, so every official Docker Compose option works (see [COMMANDS.md](COMMANDS.md) for per-command exceptions). The core pattern is **Docker Compose overrides**: a base `docker-compose.yml` is merged with an environment-specific override file. Spin sets `COMPOSE_FILE=docker-compose.yml:docker-compose.$SPIN_ENV.yml` automatically. **`SPIN_ENV` defaults to `dev`**, so `spin up` is equivalent to: ```bash COMPOSE_FILE=docker-compose.yml:docker-compose.dev.yml docker compose up ``` Override with `SPIN_ENV=testing spin up` to use `docker-compose.testing.yml` instead. The base file defines shared service structure. Override files add environment-specific settings. Docker merges them intelligently — override values replace or extend base values. (Image versions and service names below are illustrative — mirror the project's actual files.) ```yaml # docker-compose.yml (base — shared across all environments) services: traefik: image: traefik:v3 php: depends_on: - traefik ``` ```yaml # docker-compose.dev.yml (development overrides) services: traefik: ports: - "80:80" - "443:443" volumes: - /var/run/docker.sock:/var/run/docker.sock:ro - ./.infrastructure/conf/traefik/dev/traefik.yml:/traefik.yml:ro php: build: target: development args: USER_ID: ${SPIN_USER_ID} GROUP_ID: ${SPIN_GROUP_ID} volumes: - .:/var/www/html/ labels: - "traefik.enable=true" - "traefik.http.routers.laravel.rule=HostRegexp(`localhost`)" - "traefik.http.routers.laravel.entrypoints=web" - "traefik.http.services.laravel.loadbalancer.server.port=8080" - "traefik.http.services.laravel.loadbalancer.server.scheme=http" node: image: node:24 volumes: - .:/usr/src/app/ working_dir: /usr/src/app/ ``` ```yaml # docker-compose.prod.yml (production overrides — Docker Swarm) services: php: image: ${SPIN_IMAGE_DOCKERFILE} environment: AUTORUN_ENABLED: "true" SSL_MODE: full deploy: replicas: 1 update_config: failure_action: rollback order: start-first labels: - "traefik.http.routers.my-php-app.rule=Host(`${SPIN_APP_DOMAIN}`)" - "traefik.http.routers.my-php-app.tls.certresolver=letsencryptresolver" ``` ## Project structure Typical layout from the Laravel templates (individual projects may differ): ``` docker-compose.yml # Base (shared services) docker-compose.dev.yml # Dev overrides (ports, volumes, build target, labels) docker-compose.prod.yml # Prod overrides (Swarm deploy, TLS, health checks) Dockerfile # Multi-stage: base → development → ci → deploy .env # Read by Docker Compose AND Laravel (dual-use) .spin.yml # Server inventory for provisioning (optional) .infrastructure/ conf/ traefik/dev/ # Dev Traefik config + local certs (committed) traefik/prod/ # Prod Traefik config (committed) volume_data/ sqlite/ # SQLite data (gitignored) redis/ # Redis data (gitignored) ``` The `.infrastructure/` folder is flexible. `conf/` stores committed configuration. `volume_data/` stores gitignored persistent data for any service. This keeps everything portable — moving the project folder moves all data with it. Check the project's `.gitignore` to determine what is tracked. ## Dockerfile pattern Multi-stage build using `serversideup/php` (match the PHP version and variant to the project): ```dockerfile FROM serversideup/php:8.5-fpm-nginx-alpine AS base # Uncomment to add PHP extensions: # USER root # RUN install-php-extensions bcmath gd FROM base AS development ARG USER_ID ARG GROUP_ID USER root RUN docker-php-serversideup-set-id www-data $USER_ID:$GROUP_ID && \ docker-php-serversideup-set-file-permissions --owner $USER_ID:$GROUP_ID USER www-data FROM base AS ci USER root FROM base AS deploy COPY --chown=www-data:www-data . /var/www/html USER www-data ``` Stages: **base** (production image), **development** (matches host UID/GID via `SPIN_USER_ID`/`SPIN_GROUP_ID`), **ci** (root for CI pipelines), **deploy** (copies app code, sets permissions). The dev compose file targets the `development` stage via `build.target`. ## Development workflow This is where 90% of Spin usage happens. ### Starting the environment ```bash spin up --build # Recommended: builds and starts all services (foreground) spin up -d # Detached mode (background) ``` `spin up` runs in the foreground — open a second terminal for other commands. Press `Ctrl+C` to stop. ### Running commands Syntax: `spin <exec|run> [-T] <service> <command>` — the service argument is the **service name** from the project's `docker-compose.yml` (verify there; not every project names its services `php` and `node`). ```bash spin exec php composer install spin exec php php artisan migrate # First "php" = service, second "php" = binary spin run php php artisan make:model Post spin exec node npm install spin exec node npm run dev ``` **`exec` vs `run`**: - **`spin exec`** reuses the live container from an already-running stack. Near-instant. Default for `artisan`, `composer`, `npm`, and ad-hoc commands during development. - **`spin run`** creates a new container each invocation. Use when the stack is not running, or when isolated state / different env vars are needed. **The `-T` flag**: Compose auto-detects TTY, so interactive terminal usage works without `-T`. Add `-T` as a defensive default when invoking from an AI agent, CI pipeline, or wrapper script — auto-detection can misfire in those contexts, causing hangs or ANSI-garbled output: ```bash ./vendor/bin/spin exec -T php php artisan test # AI/CI-safe ./vendor/bin/spin exec php artisan tinker # Interactive — omit -T ``` ### Volume mounting In development, the project directory is mounted at `.:/var/www/html/`, so code changes are reflected instantly — no rebuild needed for code changes. ### When to rebuild Use `spin up --build` when: - Starting a development environment (recommended as default habit) - After Dockerfile changes (adding PHP extensions, changing base image) - After modifying build-related compose settings Code-only changes never need a rebuild — volume mounts handle it. ### `.env` dual-use The `.env` file is read by **both** Docker Compose (for variable substitution like `${SPIN_APP_DOMAIN}`) and Laravel inside the container (since the project is volume-mounted). Example: ```env DB_HOST=mysql DB_DATABASE=laravel SPIN_APP_DOMAIN=laravel.dev.test ``` ### Which compose file to edit | Change type | File | |---|---| | Shared service definitions (image, depends_on) | `docker-compose.yml` | | Dev-only (ports, volume mounts, build target, Traefik labels) | `docker-compose.dev.yml` | | Prod-only (deploy config, Swarm labels, named volumes, TLS) | `docker-compose.prod.yml` | ### Essential commands | Command | What it does | |---------|-------------| | `spin up` | Start all services (`docker compose up`) | | `spin up --build` | Start and rebuild | | `spin stop` | Stop containers without removing them | | `spin down` | Stop and remove containers | | `spin run <svc> <cmd>` | One-off command in new container | | `spin exec <svc> <cmd>` | Command in running container | | `spin logs` | View container logs | | `spin ps` | List running containers | | `spin build` | Build images without starting | See [COMMANDS.md](COMMANDS.md) for the complete command reference. ## Running tests Prefer the **already-running dev stack** — it's faster than spinning up a parallel CI stack: ```bash ./vendor/bin/spin exec -T php php artisan test ./vendor/bin/spin exec -T php php artisan test --filter=ExampleTest ./vendor/bin/spin exec -T php composer test # If the project exposes a composer test script ``` `php artisan test` works for both PHPUnit and Pest. Inspect the project's `phpunit.xml` before choosing a stack: if tests are self-contained (sqlite `:memory:`, `array`/`sync` drivers), the dev stack is plenty; otherwise it usually still works. Reach for `SPIN_ENV=ci` only when CI parity is explicitly needed. See [TESTING.md](TESTING.md) for the stack decision tree, the full CI-parity workflow, parallel Compose environments, and the override-network gotcha. ## serversideup/php images Choose the right variant: | Variant | Use case | |---------|---------| | `fpm-nginx` | Most Laravel apps (PHP-FPM + NGINX) | | `fpm-apache` | Apps needing `.htaccess` support | | `frankenphp` | Laravel Octane with FrankenPHP | | `cli` | Artisan commands, queue workers, schedulers | Tag pattern: `serversideup/php:<php-version>-<variant>[-alpine]` Example: `serversideup/php:8.5-fpm-nginx-alpine` Key environment variables for production: ```yaml environment: AUTORUN_ENABLED: "true" # Enable Laravel automations (migrations, caching) PHP_OPCACHE_ENABLE: "1" # Enable OPcache SSL_MODE: "full" # SSL termination mode HEALTHCHECK_PATH: "/up" # Laravel's built-in health route ``` See [DOCKER-IMAGES.md](DOCKER-IMAGES.md) for the full image configuration reference. ## Laravel services In Docker, services connect via **container name as hostname**. This is critical when generating `.env` files: ```env DB_HOST=mysql # NOT localhost REDIS_HOST=redis # NOT 127.0.0.1 MAIL_HOST=mailpit ``` Available services: MySQL, PostgreSQL, MariaDB, SQLite, Redis, Laravel Queues, Horizon, Reverb, Task Scheduler, Octane, Vite, Mailpit, Meilisearch. Avoid special characters in database passwords — use long (20+) alphanumeric passwords instead. See [LARAVEL-SERVICES.md](LARAVEL-SERVICES.md) for complete Docker Compose configurations and `.env` settings for each service. ## Deployment Two strategies: ### `spin deploy` (solo developers) Builds locally, pushes via SSH tunnel, deploys to Docker Swarm — all in one command: ```bash spin deploy production ``` Requires a provisioned server (`spin provision`) and `.spin.yml` configuration. ### GitHub Actions (teams) Use open source actions for CI/CD: - [`serversideup/docker-build-action`](https://github.com/marketplace/actions/docker-build-action) — Build and publish Docker images - [`serversideup/docker-swarm-deploy-github-action`](https://github.com/marketplace/actions/docker-swarm-deploy-github-action) — Deploy to Docker Swarm See [DEPLOYMENT.md](DEPLOYMENT.md) for detailed deployment workflows. ## Server provisioning `spin provision` uses Ansible to configure servers for Docker Swarm: ```bash spin provision # Provision all servers in .spin.yml spin provision production # Provision only production ``` Server requirements: Ubuntu 22.04+ LTS, x86_64, ports 22/80/443 open, fresh install. The `.spin.yml` file defines users, providers, servers, and environments. Supports Hetzner, DigitalOcean, Vultr, or any host with SSH access. ## Common pitfalls | Problem | Solution | |---------|---------|
Auf GitHub ansehen
Diese SKILL.md ist sehr gross, daher zeigt SkillsMP hier nur den ersten Abschnitt. Auf GitHub ansehen