DevContainers Compatibility #891
Replies: 6 comments 1 reply
|
Thanks for raising this. Before I dig in I want to make sure I'm solving the right problem, because there are two quite different things people mean by this and they land in very different places. One is lerd running inside the devcontainer, so the whole PHP environment travels with the project and you get it over Remote SSH. That one is a real piece of engineering rather than a docs page. lerd runs everything as rootless Podman quadlets, so inside a devcontainer you're into nested user namespaces and a systemd enabled base image, and then the .test resolution and the local CA trust both live on the host, so neither the container resolver nor your laptop's browser gets them for free. Doable, but it's a feature, not a paragraph. The other is lerd staying on the host and serving a project whose source you also open in a devcontainer, with the container acting as an editor and tooling sandbox. That one mostly works today and is genuinely just a documentation gap. Which of those two are you after? And when you say remotely over SSH, is the machine running lerd a remote box you're connecting to from a laptop, or is it all local and SSH is just how VS Code attaches? |
That's the more immediate solution, that would mean expose a stdio/stdin for lerd to communicate with. Yes, it would mean separating the UI and the App itself so these run detached.
... but this one is faster to implement. The problem is that the DevContainer also contains the webserver and else, apart from the editor.
Personally, I would just the second option since the first looks more like a v3.0. In the future, it would be great to have multiple DevContainers, each one with its own Lerd.
Both; the intention is to make this setup. PHPStorm allows to run inside a DevContainer, and the IDE Server exposes ports that go through PHPStorm client. If you run The problem of remove DevContainers with SSH is that the main container where you connect to must handle proxying the ports from other services when it runs in a docker-composer.yml stack, and you're on your own. |
|
Good, that settles the scope, option two is the one and it's mostly a docs job. One thing I want to flag though, because I think it dissolves most of the pain you described. The port forwarding dance only exists because the webserver lives inside the devcontainer. If lerd serves from the host, it goes away entirely. No artisan serve, no 8080 to 80 mapping, no proxying the rest of the compose stack through whichever container you happen to be attached to. The source sits on the host, gets bind mounted into the devcontainer, and lerd serves it as https://site.test from host nginx. The devcontainer goes back to being what it's actually good at, an editor and a place to run composer, node, artisan, phpunit, without any of that landing on the host. The one bit worth getting right is file ownership, since the devcontainer and rootless podman are both writing into the same tree and their uid mappings need to agree. That's the part I'd rather document properly than hand wave. The remote case is where I think ports are the wrong villain. If the lerd box is remote, the .test resolution and the local CA trust both live on that box. Your laptop's browser has neither, so even with every port forwarded you'd get a name that doesn't resolve and a cert nothing trusts. That's a tunnel plus a hosts entry plus importing the remote CA, and it's true whether or not a devcontainer is anywhere in the picture. So, for the remote setup, do you actually want to browse the site from your laptop's browser against a remote lerd, or is it enough that the IDE is remote and the site just opens on that machine? Those are pretty different asks and only one of them needs new machinery. |
|
Browse the site from your laptop's browser against a remote lerd.
Yeah, the main intention is to allow to browse the web project from the remote client (while the container is on a remote host, or on the client), and let Lerd handle how from inside the container, or by connecting to the container via ssh and proxy the internal ports (even if that means two ssh connections: one for the remote IDE/Code Editor and another for Lerd). Another alternative would be to ssh into the host itself, or expose Podman on the host via port mapping, so Lerd connects to Podman automatically remotely. I prefer the SSH option. |
|
Circling back on this, I went and reproduced the option two path locally so I can hand you something concrete to try rather than theory. The shape is what we agreed: your source lives on the host, lerd serves it from host nginx as https://yoursite.test, and the devcontainer bind mounts that same tree and goes back to being just an editor and a place to run composer, node, artisan, phpunit. No webserver in the container, no artisan serve, no port dance. The one thing that actually decides whether this is pleasant or miserable is uid mapping, and I can now say exactly why. lerd runs everything as rootless podman, so its php container runs as your host user, container root maps straight back to your account. When your devcontainer writes into the shared tree it needs to resolve to that same host user, otherwise every file it creates, vendor, bootstrap cache, compiled views, storage, lands owned by a high subuid that neither your editor nor lerd's php can rewrite. lerd makes the project dirs world writable, so the wrong mapping looks fine for about five minutes, the writes succeed, the site keeps serving, and then the app 500s the moment the framework tries to overwrite a cache file it no longer owns. So this is not cosmetic, it is the whole ballgame. The fix is one line. Point VS Code at podman with dev.containers.dockerPath set to podman, then in devcontainer.json add: "runArgs": ["--userns=keep-id"]keep-id maps the container user back to your host account, so anything the container writes comes out owned by you, and lerd's php can read and rewrite it, and vice versa. The vscode and node base images already run as uid 1000 which lines up cleanly. If you would rather not touch runArgs you can run the container as root and rootless podman maps that to you as well, but keep-id with a normal user is the tidier answer. If you can give that a spin, two things would tell me it is solid for your setup. First, browsing https://yoursite.test from the machine running lerd just works while the tree is open in the devcontainer. Second, after a composer install or an artisan make from inside the container, the new files show up owned by you on the host, not by some 100999 uid. If both hold I will write this up properly as a docs page. The remote browse case you raised at the end is a separate animal, the .test resolution and CA both live on the lerd box, so I want to keep that out of this page and treat it on its own. |
|
Okay, I tried to spin a Laravel Sail project with Lerd. The first problem I encountered was that Laravel Sail exposes port 80 by default, so APP_PORT=9080Apart from that, Lerd works great since, AFAIK, the containers (MySQL, Valkey) works and Lerd serves the site, and with that profiling works. I would prefer FrankenPHP on non-worker, which makes profiling work anyway. It uses caddy, so there is an argument for more convenient DNS/SSL handling, especially on multiple sites. What about remote DevContainersThis is my biggest gripe. Lerd works great locally, but since I'm finishing moving DevContainers to remote so the team can work from out anywhere with sandboxing and backups, I cannot use Lerd since it cannot see the local project, so cannot serve it. The only way for this to work is make a "Lerd sidecar" on the container: let it serve the site, and the Lerd CLI/App connect to it. This basically means splitting the app in two. Then...So yes, DevContainer itself can work if it's locally. On remote, Lerd simply does not work, which kills my use case. |
Uh oh!
There was an error while loading. Please reload this page.
It would be great if there was a documented way to use Lerd within a DevContainer, especially when doing so remotely (SSH).
All reactions