Why Docker Wasn't Enough: My Journey to Dev Containers
I don’t like installing stuff I don’t need.
I’ve been using Arch Linux for over 12 years and always keep my system clean and minimalist, until Go and Rust forced me to break that rule.
Ever since I started using Docker, I no longer install language toolchains locally, except for the essential ones. I use Docker for all the projects I work on. My workflow used to be simple:
- Open the editor
- Start containers and auto-mount the project directory
- Start coding
The editor runs on the host, but the project and its dependencies (message broker, database, and other services) live inside containers. This setup worked well for PHP and TypeScript projects. Then Go and Rust projects broke everything and forced me to rethink the entire workflow.
When Docker Mounts Fail
The problem is not Docker, but how language servers (LSPs) work.
Both editor and LSP run outside the container, while the project dependencies are inside. The LSP needs access to all source and dependency files to work properly.
For PHP and TypeScript projects, this is fine because their dependencies (vendor and node_modules) live inside the project directory.
Go stores dependencies in $GOPATH/pkg/mod, and Rust stores them under $HOME/.cargo.
By default, these directories exist only inside the container, so the editor cannot see them and LSP features break.
I tried fixing this issue a few times without success. Even when mounting these directories, the extensions, language servers, compilers, and other tools still have to run on the host. At that point, developing inside Docker offers no real benefit over local development.
As a result, I installed their toolchains locally and ditched Docker for Go and Rust projects. This fixed the LSP issue, but it cluttered my system with extra files.
This solution introduced another issue. Arch Linux is a rolling-release distro. You can’t easily pin a specific toolchain version or switch between versions required by different projects. At that point, I lost both Docker’s isolation and Arch’s minimalism.
That’s when I found Dev Containers.
Dev Containers: The Middle Ground
Dev Containers solved most of the issues I had with Docker-based development.
The editor still runs on the host, but connects to the container where all the dependencies and tools live. That means everything (LSP, debugger, build tools) runs in the same environment. No more missing paths or “can’t find package” errors.
You can also specify editor extensions, define settings, configure devcontainer features, and more for each project. You put all this in a single file, commit it, and everyone on your team uses the same setup.
It feels like developing locally while keeping the host system clean. As a bonus, I can even remove project-specific extensions from my editor.
But Then… New Trade-offs
Dev Containers solved my isolation problem, but created a new one: editor support.
According to containers.dev/supporting, only three editors support Dev Containers: VS Code, Visual Studio, and IntelliJ IDEA. For me, that leaves only one real option: VS Code.
That’s where privacy becomes the trade-off.
The sole reason I migrated from Ubuntu to Arch Linux was privacy, after Ubuntu introduced user tracking1. I now face the same dilemma with editor telemetry.
The official VS Code build is proprietary and sends telemetry to Microsoft. On the other hand, Code-OSS, the open-source version I normally use, doesn’t support Dev Containers because that feature is under Microsoft’s license.
I’ve used Cursor IDE before, and it supports Dev Containers out of the box. Zed has announced that Dev Containers support is now in preview and will be released in stable at the start of next year2.
However, for the time being, I have to stick with the official VS Code build, though I may change my main editor in the near future. That leaves me choosing between privacy, convenience, and editor support.
Dev Containers finally solved the technical problems Docker couldn’t. The remaining issues are editor support and SSH/GPG integration, both of which require non-trivial setup.
Dev Containers fixed my local workflow at the cost of editor choice. What’s your approach?