Skip to content

Laravel Sail alternative

Laravel Sail is the official per-project Docker Compose setup: a docker-compose.yml in the repo, a container per service, and ./vendor/bin/sail in front of every command. It works, and it is the right answer when a team wants the environment described inside the project.

The friction shows up when you have several projects open. Each one is a full stack, so five repos means five copies of PHP, five databases and five Redis instances, plus a port to remember for each. Lerd takes the shared-infrastructure route instead: one nginx, one PHP-FPM per version, one instance of each service, across every site, as rootless Podman containers under your own user. Every project gets a .test domain and a trusted certificate with nothing committed to the repo.

bash
curl -fsSL https://lerd.sh/install.sh | bash
cd ~/code/myapp
lerd link

https://myapp.test, no port, no sail up.

The one-command migration

Sail is the only tool with an automated importer in Lerd, because a Sail stack has a predictable shape. From the project root:

bash
lerd sail import

It reads the Compose file, remaps any ports that would clash with Lerd's running services, starts only the data services (so a slow or broken app image build never blocks you), waits for the database, dumps it, imports it into Lerd's MySQL or PostgreSQL, mirrors S3 and MinIO files into Lerd's storage, then stops Sail again.

You rarely have to remember the command: running lerd link on a project with laravel/sail in its composer.json offers the import before setup.

The flags, the credential handling and the .env.before_lerd behaviour are all covered in Importing from Laravel Sail.

Every Sail habit, and the Lerd equivalent

What you did with SailThe same thing in Lerd
sail up -d per project before you can worklerd start once, then every project is served
sail artisan, sail composer, sail npmlerd artisan, lerd composer, lerd node, from your own shell
localhost:${APP_PORT}, a different port per projecthttps://myapp.test, automatic, no ports
/etc/hosts edits when you wanted a real hostnameAutomatic .test domains through a dnsmasq container
No TLS, or mkcert wired in by handlerd secure, a real mkcert certificate trusted by your system and browsers
Change the PHP version by switching the Sail image and rebuildinglerd isolate 8.4, or let it read composer.json, no rebuild
Add a service by editing docker-compose.ymllerd service start meilisearch, shared across every site
Queue and scheduler as extra Compose serviceslerd worker start queue / schedule, as user services with self-healing
sail logs -fA log viewer in the dashboard, or lerd logs
docker-compose.yml committed to the repo.lerd.yaml, optional, a handful of lines
Docker Desktop, Orbstack or ColimaRootless Podman, no daemon, no licence

Lerd vs Laravel Sail

LerdLaravel Sail
PlatformsLinux (systemd), macOS, Windows via WSL2 (beta)Linux, macOS, Windows
LicenseOpen source (MIT)Open source (MIT)
Container runtimeRootless Podman, no daemonDocker Desktop / Orbstack / Colima
ArchitectureOne shared nginx, PHP-FPM and service layerA per-project Compose stack
PHP versions7.4, 8.0 to 8.5, per project, no rebuildPer-project Sail image
Services (MySQL, Redis…)One shared instancePer project
.test domainsAutomatic, zero configManual hosts entries, or localhost:${APP_PORT}
HTTPSlerd secure, trusted mkcert certificateManual, or roll your own mkcert
RAM with 5 projects running~200 MB~1–2 GB, five full stacks
Requires changes to project filesNoYes, docker-compose.yml committed
Works on legacy / client reposYes, just lerd linkOnly if you can add Sail
Non-PHP projectsFirst-class via Containerfile.lerdAdd your own container to the stack
Per-project service versionsNo, services are shared and versioned globallyYes, each project pins its own
DashboardWeb UI, system tray, terminal dashboardCLI + Docker Desktop
AI / MCPBuilt-in MCP serverNot built in
CostFreeFree

Choose Sail when: your team already standardised on it, two projects need different major versions of the same database at the same time, or you want the infrastructure defined in the repo.

Choose Lerd when: you work across many projects at once, you cannot modify a client's project files, you want .test routing and HTTPS without wiring them, or you want the same environment on Linux and macOS.

Running both

They coexist. Lerd uses rootless Podman with no daemon, so Docker stays installed and Sail keeps working on the projects you have not moved.

The only file Lerd touches in a project is .env, and only when you run lerd env. The original is saved as .env.before_lerd the first time, so a project can go back:

bash
lerd env:restore

That makes the migration reversible per project, which is the sane way to move a team over: convert one repo, live on it for a week, then do the rest.

What is genuinely different

  • Services are shared, not per project. One MySQL, one Redis, one Mailpit across every site. That is where the memory saving comes from, and it is the one thing Sail does that Lerd does not: pinning a different database major version per project.
  • No sail prefix. lerd artisan and lerd composer run in the project's PHP container but from your own shell and your own directory.
  • The environment is not in the repo. Instead of a Compose file, you commit an optional .lerd.yaml describing PHP, Node, services and workers. Teammates without Lerd are unaffected, since nothing else changed.
  • One sudo at install time. Only to point the system resolver at the .test domains.

Frequently asked questions

Does the import handle S3 and MinIO? Yes, files are mirrored into Lerd's S3-compatible storage. Skip it with --skip-s3 if the project does not use it.

What if my Sail app image will not build? It does not matter. The import starts only the data services with --no-deps, so the app container is never built.

Can I keep Sail's database credentials? The import auto-detects the database name and tries Sail's defaults. Override with --sail-db-name, --sail-db-user and --sail-db-password when your project uses custom ones.

Does it work if I run Sail on Podman Compose? Yes. The command tries docker compose first and falls back to podman compose.

Is Lerd free for commercial work? Yes. MIT licensed, no paid tier.

Next steps

Released under the MIT License.