Why is Laravel Sail meant for local development rather than production, and how would you choose between Sail, Herd and a custom Docker setup for a team?
answer
- artisan serve under supervisor
- dev tooling: Xdebug, PCOV, Node, compilers
- code bind-mounted, weak default passwords
- Herd: native PHP and nginx per machine
- custom Docker: parity with container production
basics
~20 sSail's image is a development box: artisan serve runs PHP's built-in development server, Xdebug and build tools are installed, code is bind-mounted and credentials are throwaway. Pick Sail for repo-pinned setups, Herd for native speed, custom Docker for production parity.
solid answer
~40 sSail's `laravel.test` container is built for comfort, not for serving users. Supervisor runs `php artisan serve`, PHP's built-in **development server**, not PHP-FPM or Octane; the image carries Xdebug, PCOV, Node and build tools; your source is **bind-mounted** from the laptop; and the defaults are local — `DB_PASSWORD=password`, an empty MySQL root password allowed, ports published. Production wants a lean image with code and caches built in, a production server, no debug tooling and real secrets. Locally: **Sail** when PHP and services should be pinned in the repository across macOS, Linux and WSL2 — the fix for a team on mixed PHP versions; **Herd** when macOS or Windows developers want fast native PHP and nginx, accepting per-machine setup; a **custom Docker setup** when production runs containers and dev–prod parity justifies maintaining your own images.
go deeper
Recall that Sail is for local development and that Herd and custom Docker setups are the main alternatives.
Explain what makes Sail's image a development image: artisan serve, bind-mounted code, debug tooling and local credentials.
Compare Sail, Herd and a custom Docker setup for a real team, and align the local runtime with production's PHP and serving model.
Choose the team's local-environment strategy against deployment targets, onboarding cost and parity, and plan when to move from Sail to owned images.
## What the Sail image is optimised for Sail's runtime images are designed to make a laptop productive, and the choices show: - **The web server.** Supervisor starts `php artisan serve --host=0.0.0.0 --port=80`, which launches PHP's **built-in web server** — the one that announces itself as the *PHP Development Server*. `sail:install` enables `PHP_CLI_SERVER_WORKERS=4` so a few requests can run at once, but it remains a development server, not PHP-FPM behind a production web server or an Octane application server. - **Tooling baked in.** The Ubuntu-based image installs `php8.x-dev`, Xdebug, PCOV, Node and npm, database clients, `git`, `ffmpeg` and more — useful for debugging, coverage and asset builds, and a large attack surface in production. - **Code from your disk.** `compose.yaml` bind-mounts the project directory into `/var/www/html`, so edits appear instantly. Production images should contain the code, the `vendor/` directory and built assets, immutable and versioned. - **Throwaway credentials.** `sail:install` writes `DB_USERNAME=sail` and `DB_PASSWORD=password`; the MySQL service allows an empty root password and connections from any host; database and mail ports are published to the host for convenience. - **Debug hooks.** `SAIL_XDEBUG_MODE` and `sail debug` exist to attach a step debugger. None of that is a flaw — it is the job description. The mistake is treating the same image as a deployment artifact. ## What production needs instead | Concern | Sail (local) | Production image | |---|---|---| | Web server | `artisan serve` (PHP's development server) | PHP-FPM behind a web server, or Octane | | Code | bind-mounted from the laptop | copied in at build time, versioned | | Tooling | Xdebug, PCOV, Node, compilers | only runtime extensions | | Caches | usually not built | config, routes, views and events cached at deploy | | Credentials | `password`, empty root password allowed | secrets from the platform, least privilege | | Services | database, Redis and mail catcher beside the app | managed or separately operated services | Whether the orchestration around that image should be Compose at all is a separate question, owned by the Compose production-limits material. ## Choosing a local environment **Sail** fits when: - developers use a mix of macOS, Linux and Windows with WSL2; - the team has drifted onto different PHP versions and needs one pinned in the repository; - the app needs several services (MySQL, Redis, Meilisearch, Mailpit) that should start with one command; - onboarding should be `git clone`, `composer require`/`install`, `sail up`. The costs are Docker's: memory and CPU for the containers, file-sharing overhead on some hosts, and a prefix on every command. **Herd** fits when developers are on macOS or Windows and want speed and simplicity: it is a native application that installs PHP and nginx on the machine, serves projects from a parked directory on `.test` domains, and needs no containers. Databases and other services come from its Pro edition or separate installs. Its configuration lives on each developer's machine rather than in the repository, so version drift across a team has to be managed by convention. **A custom Docker setup** fits when production already runs containers and parity is worth the maintenance: a multi-stage Dockerfile whose production stage is what ships, with a development stage that adds Xdebug and mounts the code. It is the most work and the most faithful. Teams often start with Sail and graduate to this — `sail:publish` is one way to begin owning the Dockerfiles. ## Applying it to the mixed-PHP team 1. If production runs PHP 8.4, set Sail's runtime to 8.4 in `compose.yaml` so every developer runs what ships. 2. Keep CI on the same version, so tests, local runs and production agree. 3. Revisit the choice when deployment changes: if production moves to containers, a custom image shared by dev and CI may replace Sail. ## Common mistakes - Deploying the Sail image, or copying its `compose.yaml` to a server. - Assuming a bug cannot exist in production because it does not reproduce under Sail's development server. - Choosing Herd for a team whose members are on Linux, where it is not available.
- A bug appears in production but never under Sail. What differences in the Sail setup would you check first?The serving model — PHP's development server versus PHP-FPM or Octane — and anything that follows from it, such as request concurrency and long-lived state; the PHP version and extensions in the runtime versus production; cached config and routes, which Sail usually does not build; and environment values, since Sail's `.env` points at local services with local credentials.
- When is Herd a better choice than Sail for a Laravel team?When developers are on macOS or Windows, want the lowest-friction native setup, and the app needs little beyond PHP and a database. Herd serves projects without containers, so it is fast and light. The trade-off is that each machine's PHP setup lives outside the repository, so keeping versions aligned relies on convention.
Sail is a test kitchen: every burner, thermometer and gadget within reach and the doors open for tasting. A restaurant line is built differently — fewer tools, locked-down stations, food prepared ahead — because it serves strangers at volume, not a cook experimenting.
saying these in an interview costs you the question
- Sail's container is production-ready because it already runs in Docker.
- artisan serve inside Sail runs PHP-FPM behind nginx.
- The Sail image contains the application code, so bind mounts are optional.
- Herd and Sail both pin the PHP version in the repository.
- Anything that works under Sail is guaranteed to behave the same in production.