Skip to content

Laravel Sail alternative

Sail is the one environment Lerd migrates for you. Every other move in this documentation is a manual dump and restore. A Sail stack has a predictable shape, so Lerd can read the Compose file and lift the project out of it in a single command.

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

The project is now on https://myapp.test with a trusted certificate, no port to remember and no sail up to run first. docker-compose.yml is still sitting in the repo, untouched, if you want to go back.

The one-command migration

lerd sail import reads the Compose file and remaps any port that would clash with Lerd's running services, so Sail and Lerd can be up at the same time without a fight. Then it starts only the data services with --no-deps, which is the part that matters in practice: the app image is never built, so a Node quirk or a private registry login that breaks sail up cannot block the migration. It waits for the database, detects the real database name, dumps it, imports it into Lerd's MySQL or PostgreSQL, mirrors the S3 and MinIO objects into Lerd's storage, and stops Sail when it is done.

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

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

What Sail costs once several projects are open

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

The bill arrives when the projects multiply. Each repo is a full stack, so five open repos means five copies of PHP, five databases, five Redis instances and five ports to keep straight. Lerd's answer is to stop the cost scaling with the project count: one nginx, one PHP-FPM per version and one instance of each service, shared across every site as rootless Podman containers under your own user, with a .test domain and a certificate handed to each project and nothing committed to the repo.

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
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

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

  • The database outlives the project. In Sail the data lives in a Compose volume belonging to that repo, so sail down -v in the wrong directory takes it with it. In Lerd one MySQL and one PostgreSQL hold every site's databases, independently of whether the site is linked. That is also the one thing Sail does that Lerd does not: pinning a different database major version per project.
  • No sail prefix, and no sail up. lerd artisan and lerd composer run in the project's PHP container but from your own shell, in your own directory. There is no per-project stack to bring up first, so a project you have not opened in a month responds the moment you load its URL.
  • 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.