laravel/sail
Laravel Sail is a Docker-powered local development environment for Laravel that works on macOS, Windows (WSL2), and Linux. With a simple CLI, it lets you start building without any prior Docker experience.
Sail is a Composer dev dependency plus a thin CLI wrapper around Docker Compose; it is not something you wire into application runtime code. The fastest path is to let it generate the local stack, then use sail instead of host PHP/Node tools.
composer require laravel/sail --dev.php artisan sail:install --with=mysql,redis,mailpit (or choose pgsql, mariadb, mongodb, selenium, etc. interactively). This writes compose.yaml on current versions and updates .env host/port values../vendor/bin/sail up -d. Stop it with ./vendor/bin/sail down..env, then sail artisan key:generate, sail artisan migrate --seed, and sail npm install && sail npm run dev. The app is served through the laravel.test service on APP_PORT (default 80).cp .env.example .env, composer install, sail up -d, sail artisan key:generate, sail artisan migrate --seed, sail npm install && sail npm run dev.Look first at the project’s .env (APP_PORT, DB_*, FORWARD_DB_PORT, WWWUSER/WWWGROUP), the generated compose.yaml, and the runtime Dockerfile under vendor/laravel/sail/runtimes/8.x/Dockerfile. The official documentation on laravel.com/docs/sail is the primary reference; the package README is intentionally short. The first high-value use case is eliminating “works on my machine” setup: one command starts PHP, database, cache, and mail services with predictable hostnames.
Treat Sail as the default execution wrapper for local development. Use sail artisan, sail composer, sail php, sail test, sail pest, sail npm, sail node, sail tinker, and sail shell so commands run against the container’s PHP version and extensions rather than the host’s. This is especially important when team members have different host PHP/Node versions.
Common day-to-day patterns:
sail mysql, sail pgsql, sail redis, etc. when the corresponding service is installed. Use sail exec <service> ... or docker compose exec for commands Sail does not wrap directly.sail test or sail pest inside the app container. For browser tests, select the Selenium/Playwright service during sail:install and point Dusk or Pest browser tests at that service hostname. Ensure test environment variables use service names such as mysql or pgsql, not 127.0.0.1.sail artisan queue:work and sail artisan schedule:work in separate terminals. For Horizon, use sail artisan horizon. Keep these out of the main sail up terminal so logs stay readable.sail run ... (available in newer releases) or sail exec for disposable commands that should not leave a shell open. This is useful for migrations, seeders, and administrative Artisan commands.compose.yaml and keep service hostnames in .env.example. Do not commit local .env. When adding a service, prefer updating compose.yaml deliberately rather than re-running sail:install blindly over an existing file.vendor/laravel/sail/runtimes/. If you need OS packages or image-level changes, copy the relevant Dockerfile into the project (for example docker/8.4/Dockerfile), update compose.yaml to build from that context, and commit it. For PHP extensions only, newer Sail supports the PHP_EXTENSIONS build arg; add it to the service build args and rebuild.SAIL_DOCKER_BINARY=podman if the team uses Podman instead of Docker.compose.yaml to production. In CI, use the same PHP version and service containers directly, or run the test suite in a controlled container image; using Sail itself in CI is usually unnecessary overhead.compose.yaml instead of docker-compose.yml. Old scripts, aliases, and CI steps that reference docker-compose.yml may need updating after an upgrade.localhost. Inside the app container, the database host is mysql, pgsql, etc., not 127.0.0.1. The same applies to Redis and mail services. Keep .env and phpunit.xml consistent with service names..env changes require recreation. Compose interpolates environment variables at container creation. After changing ports, database credentials, or Xdebug settings, run sail down and sail up -d rather than assuming a restart picks them up.sail down -v unless you are comfortable losing local data.APP_PORT, FORWARD_DB_PORT, FORWARD_REDIS_PORT, and similar values in .env rather than stopping unrelated services.WWWUSER and WWWGROUP to your host UID/GID in .env if files created inside the container become root-owned. Prefer sail shell over sail root-shell; use root only for deliberate system-level changes.SAIL_XDEBUG_MODE=off by default and enable debug only when needed. If breakpoints do not connect, verify the IDE key, port, and host.docker.internal configuration.PHP_EXTENSIONS requires sail build --no-cache and sail up -d. Pulling a new Sail version may also require rebuilding the app image.vendor/ Dockerfiles. Copy the runtime Dockerfile into your project and point compose.yaml at it. Vendor changes disappear on composer update./mnt/c, or file watching, Composer installs, and test runs will be noticeably slower. Sail’s supported Windows path is WSL2.VITE_PORT is forwarded and the dev server binds to 0.0.0.0. If the browser cannot reach the HMR socket, check the Vite server.hmr host configuration rather than assuming Sail is broken.MAIL_HOST and open the forwarded UI port (commonly 8025) to inspect messages.compose.yaml and the runtime Dockerfile. Re-running sail:install can overwrite customizations; merge changes manually when the project has a customized stack.How can I help you explore Laravel packages today?