Dev Containers: The Best Dev Setup You’re Not Using
I have found myself advocating for Development Containers, or Dev Containers for short, more and more frequently. Stop wasting time fixing dev environments. Dev Containers let you spin up a fully configured setup fast - so you can focus on coding.
❓ Why use a container as a development environment?
If you’re thinking, “Why do I need the overhead of a container?” or “Can’t I just run my tools directly on my machine?”, I’m going to answer those questions.
Firstly, as any software engineer knows, our development environments are brittle. Things are constantly evolving and occasionally breaking - when they do, our productivity takes a hit. That effect is only magnified when working in a team, where environment mismatches can lead to frustrating inconsistencies.
“Software engineering is what happens to programming when you add time and other programmers.”
Many teams share scripts to automate and standardise as much of the local development setup as possible. But what if you could take that further and encapsulate the entire development “machine”? This would improve ramp-up time for both new and long-term engineers.
I wrote “machine” in quotes because we’re going to explore how Dev Containers fulfill this requirement using containers. If the entire development environment were declarative, then just as we often rebuild infrastructure rather than troubleshooting it, we could apply the same principle to development environments.
A Dev Container is essentially a Docker container that includes:
- A lightweight OS,
- Required runtimes and shared libraries,
- Any specific developer tooling you install.
This environment is repeatable, can be created on-demand, and integrates seamlessly with modern editors like:
Instead of copying your source code into the container, it’s typically mounted as a Linux volume, similar to a network share.
And because it can be easily created, it can just as easily be recreated.
The tooling takes care of most of the setup. Here’s a simple example of a devcontainer.json
file that creates a
Go development environment and installs the Go extension in Visual Studio Code:
{ "name": "Go Dev Container", "image": "mcr.microsoft.com/devcontainers/go:1-1.23-bookworm",
// Uncomment for .NET development instead
// "image": "mcr.microsoft.com/devcontainers/dotnet:1-9.0-bookworm",
"postCreateCommand": "go version",
"customizations": {
"vscode": {
"extensions": [
"golang.go"
// Uncomment for .NET development
// "ms-dotnettools.csdevkit"
]
}
}
}
For your first attempt, I recommend starting with a simple program and a minimal Dev Container configuration. If you’re using VS Code, install the Dev Containers extension.
🔄 Repeatable & Predictable Environments Without Admin Access
If you don’t have admin privileges on your machine - or prefer not to install SDKs and dependencies locally - Dev Containers are a great solution.

Having your tooling inside the Dev Container lets you:
- Maintain separate Dev Containers per project.
- Avoid SDK version conflicts (e.g., Python 3.10 for one project, 3.12 for another).
- Check the configuration into source control, so new developers can spin up an identical environment without manual setup.

Whenever you need to refresh or upgrade your environment, simply update the Dev Container definition and rebuild it - no tedious uninstall/reinstall process required.
🐧 Getting More Comfortable with Linux
With most modern infrastructure running on Linux-based containers, working in a Linux Dev Container aligns your development environment closer to production.
If you’re on Windows, this is especially useful since it allows you to:
- Work in a native Linux shell.
- Get familiar with Bash scripting and common Linux utilities.
- Use tools like
tcpdump
for network debugging. - Inspect binaries and running processes more effectively.
🚀 Performance When You Need It
If your local machine lacks CPU/RAM, you can:
- Run your Dev Container remotely on a powerful server.
- Still use VS Code locally, connecting to the remote Dev Container.
This is ideal for:
- Data-heavy tasks (e.g., data wrangling, machine learning).
- Projects requiring large memory allocations.
- Offloading intensive workloads to cloud or on-prem servers.
Even if you don’t use remote Dev Containers, they allow cross-device portability - whether you’re on a Mac laptop or a Windows desktop, your development environment remains identical.
🔒 Security Benefits
Running your Dev Container remotely enhances security:
- Your code never resides on your laptop - only in the remote container.
- If your laptop is lost or stolen, no local source code is compromised.
GitHub Codespaces offers hosted Dev Containers on virtual machines (this is a paid service). This ensures:
- Your environment is always available without setup hassle.
- Security is enhanced, since your local device contains no sensitive code.
I personally don’t use Codespaces, as my blog and personal projects don’t require that level of security, or a machine that is more powerful than my laptop, but for teams handling sensitive codebases, it’s a compelling option.
Conclusion
Dev Containers provide a repeatable, isolated, and declarative development environment that eliminates “it works on my machine” problems. Whether you need portability, security, or ease of setup, they are a powerful tool worth adopting.
If you’re new to them, try setting up a simple devcontainer.json
for your next project - chances are, you won’t look
back.