Docker is well-known and is widely used in the software application realm. In recent years, it has made its way into many embedded software projects. In embedded development, it is mainly used for running builds and tests locally on the machine or on Continuous Integration/Continuous Deployment (CI/CD) platforms.
Check out our Using Docker for Embedded Development blog post to learn more about it. The Dockerfile can start off simple with a few required packages, and it quickly grows in size and complexity as a project progresses. Aside from a complicated Dockerfile, in order to develop code within a Docker container, we have to install screen-based text editors such as vim. For the developers who are not familiar with any of the screen-based text editors, they have to spend some time learning one of them before they can be productive within a Docker container. It will definitely speed things up if we can visualize and modify the files within the Docker container on an IDE. This is where Dev Containers come in.
What are Dev Containers?
A Dev Container, or Development Container, is a Docker Container that provides an isolated, consistent environment that consists of the IDE, tools, and packages that we need to develop software. Once it is set up and checked into version control, the developers can focus on the real product instead of spending extra time on setting up or replicating the build environment.
Why Dev Containers?
A dev container has all the benefits that a Docker container can offer, such as being a fast, lightweight, and standardized environment. By being able to integrate with the IDE, it provides an interface for us to interact with a Docker container and makes a complicated Docker container more manageable. The following sections will expand on the benefits of using dev containers.
Time Saving
In the beginning of a project, time spent on setting up a build and test environment is unavoidable, but we can save the time when the next developer tries to set up the same environment. When new developers join the team, many hours could be spent on trying to set up or replicate the same environment. With dev containers, one can set up the environment by just installing an IDE, such as Visual Studio Code, Docker and running the dev container.
Consistency
There are many existing ways of creating isolated environments and managing tools and packages, such as using Python Virtual Environments and Poetry, but we often still end up dealing with the “it works on my machine” situation. For example, a different version of a toolchain can result in a different binary that acts differently. By using the dev containers, all developers use the same versions of tools and configurations to build and test their code.
IDE Integration
Dev containers improve the interaction with the Docker container by integrating with the IDEs. The IDEs that currently support Dev Containers are Visual Studio Code (VS Code) and JetBrains IDEs, and we will be focusing on the VS Code Dev Containers in this blog post. The configuration of a dev container is described in a devcontainer.json file. The devcontainer.json file can be created manually or by using the VS Code Dev Container extension in a .devcontainer directory in the root directory of our project.
With the devcontainer.json in place, the project can now be opened in a dev container by using the VS Code Dev Container extension’s Reopen in Container command. It will look exactly like when it is opened locally on the host machine. VS Code extensions such as C/C++ (IntelliSense) and Cortex-Debug can be configured in the customizations section of the devcontainer.json so that these extensions will be installed in the dev container. By doing so, we can now navigate the code base and even debug the code in the dev container.The following is an example of a devcontainer.json that uses ubuntu:24.04 as a base image and installs Git, VSCode’s C/C++, and CMake Tools extensions:
{
"image": "ubuntu:24.04",
"features": {
"ghcr.io/devcontainers/features/git": {},
},
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools",
"ms-vscode.cmake-tools"
],
},
}
}
When we open the VS Code integrated terminal (for MacBook users: command + shift + P -> View: Toggle Terminal), we are actually within the Docker container. Because of that, we can use the tools that were installed within the Docker container to interact with the code base. For example, if GCC is installed in the container, we can now build our code without having to install GCC on our host machine and the version of the GCC is fixed. VS Code has a nice documentation on how to set up and start using a dev container.
Devcontainer CLI
When we open a project, VS Code uses a CLI in the background to configure the dev container. The CLI is available for developers to create and use dev containers outside of the IDE. The following are the steps to get started on the devcontainer CLI:
// For MacBook users, install node via Homebrew
brew install node
// Install devcontainer CLI via npm
sudo npm install -g @devcontainers/cli
// Spin up a dev container
devcontainer up --workspace-folder <path-to-the-project>
// Run a command in the dev container
devcontainer exec --workspace-folder <path-to-the-project> <command>
Simplify Dockerfile
Dev containers make Dockerfiles modular. Instead of installing all the required IDEs, tools, and packages in a single Dockerfile, we can make use of the features section of the devcontainer.json by adding the tools we want to install in our Docker container. The features are links to the Docker images hosted on public or private Docker registries. A list of official dev container features can be found here. We can install IDEs or tools that cannot be found on the public Docker registry in a customized Docker image, but instead, by turning them into features that can be included in the dev container, we can have a much simpler base image. The customized features can then be reused in other projects as well.
Automatic Mounting of Filesystem
When we open a project with a dev container on an IDE, it automatically mounts the project’s filesystem within the Docker container. Modifications to the files on the IDE will reflect in both the local files on the host machine and the files in the Docker container. This can be achieved by running a Docker container with the -v or -volume flag by using the Docker CLI, but the dev container sets it up without having to type out the long Docker CLI command.
Conclusion
Docker itself has been a revolutionary tool. Dev containers further elevate the usage of Docker in software development. Besides the benefits of saving time and providing a consistent development environment provided by the nature of Docker containers, dev containers reduce the complexity of using Docker by integrating with IDEs and simplifying the Dockerfiles.
Dojo Five is dedicated to modernizing the embedded industry by using modern practices and tools such as Docker and dev containers. If you are interested in bringing your project to the next level, you can schedule a call with our team. Or, feel free to check out EmbedOps, our CI build platform. It’s free to sign up.
We look forward to hearing from you! -D5


