π Learning and exploring the Development Containers specification and related ecosystem tooling.
Development Containers
An open specification for enriching containers with development specific content and settings.
I've used a lot of Docker and containers, but I've generally preferred to not use them as a shell for my development environment. I prefer using the host system directly because it's generally faster, has more freedom, and is already configured the way I need it.
But in 2025, I like using agentic coding agents and I want to cordon them off into their own space to avoid rm -rf
-like mishaps. I need to up my "dev environment in a container" game, and I think the Development Containers spec has created potentially good options. Let me try it out. And maybe I'll find that I even prefer to do most of my development in a container?
The words "development" and "containers" are overloaded and conflated severely in this space. Let's break it down.
- Development Containers specification
-
The Development Containers spec defines the meaning of the
devcontainers.json
file. This is the core component of the ecosystem of tooling around it. Notice how "Development Containers" is capitalized. - development containers
- The general idea of using containers for development. This is an unbranded concept that no one can own.
devcontainers
GitHub org-
The source code for the Development Containers spec and its first-party tooling is in the
devcontainers
GitHub organization at https://github.com/devcontainers.
In the wild, you will see these names and variations of them referring to sometimes-ambiguous things in the space. Some of the common variations are:
- DevContainers
- dev container
I personally like the abbreviated, one-worded, and capitalized "DevContainers" name to refer to the official specification and its related tooling. I also like "dev container" to colloquially refer to a container used for development.
Even within the devcontainers
GitHub org, the naming is inconsistent:
- The devcontainers/cli repository uses the name "Dev Container CLI" (abbreviated "Dev" and singular "Container")
- The devcontainers/features repository uses the name "Development Container Features (unabbreviated "Development" and singular "Container")
- The devcontainers/images repository uses the name "Development Containers Images" (unabbreviated "Development" and plural "Containers")
This repository illustrates different concepts, patterns and examples via standalone subprojects. Each subproject is completely independent of the others and do not depend on the root project. This standalone subproject constraint forces the subprojects to be complete and maximizes the reader's chances of successfully running, understanding, and re-using the code.
The subprojects include:
Use the DevContainers CLI to create and develop inside a container with basic development tools installed.
See the README in basic/.
Author custom DevContainer features to define a development container tailored to your exact needs.
DevContainers features are built on a foundation of shell scripting. Ad hoc shell scripting with Bash. Lots and lots of it. I remember having the same reaction in 2022 when I first looked at DevContainers. I get that there is a reason to use Bash/POSIX shell instead of a full programming language because it reduces a dependency on a runtime or compiler toolchain. But, these scripts have oodles of dependencies on the many commands they call. For example, in the Go feature, it depends on:
curl
git
tar
gpg
awk
- and more...
Maybe use Go/Node.js and execute subprocesses, and use their standard libraries for HTTP requests, file I/O, and string manipulation. They can even be tested!
There is a lot to be desired in the DevContainers first-party elements (the CLI and the features), but I'm hopeful that the core spec is all we need. I can use DevPod and write my own features, as needed.
General clean-ups, TODOs and things I wish to implement for this project:
- DONE Implement the
basic/
subproject- DONE Re-work it to not use SSH because of the port forward shortcomings of the CLI. Just run the basic Go program. This truly becomes a "hello world" example.
- DONE Implement the
custom/
subproject- Use DevPod
- (Update: I used custom features) I want to use a custom template.
- (Update: I'll get to that soon enough; also DevPod kind of already does it?) Consider using SSH here.
- (Answer: yes, looks like it from the docs) Can "features" depend on other features? It's probably not a good idea to get very nested, but I want to know what's possible.
- Make a connection to things like Dagger and Nix. I've had my eye on these things. I like their ideas. I'm not sure they are a good fit for me right now, but it's important to keep them in the mix because I'm especially unsure about how useful DevContainers is for me and I don't want to find myself building a substantial dependency on DevContainers because of its shakey foundations on ad hoc shell scripting and a never-fully-baked reference implementation (the CLI).