What are dev containers?
Dev Containers are a VS Code feature that lets you use a Docker container as a complete development environment. All your development tools, dependencies, and runtime are packaged inside the container, while VS Code on your host machine provides the interface.Why use dev containers?
Consistency: Everyone on your team gets the exact same development environment, regardless of their host operating system (Windows, macOS, or Linux). Isolation: The container doesn’t affect your host system. Install whatever you need inside the container without worrying about conflicts with other projects or system libraries. Portability: The entire environment is defined in code (Dockerfile and devcontainer.json). Share these files, and anyone can recreate your exact setup. Clean removal: Delete the container when you’re done - your host system remains unchanged. No leftover libraries, configurations, or dependencies. Version control: Environment configuration is tracked alongside your code, ensuring reproducibility across time and teams.Dev Containers solve the classic “it works on my machine” problem by ensuring everyone works in identical environments.
How dev containers work
Architecture overview
When you open a project in a dev container, VS Code operates in a client-server architecture:- VS Code UI runs on your host machine (Windows/macOS/Linux)
- VS Code Server runs inside the Docker container
- The UI communicates with the server over a connection bridge
- All development operations (editing, terminal, debugging) execute in the container
- Your source code is accessible in both environments via bind mounts
Connection flow
What happens when you open a dev container
- Detection: VS Code finds
.devcontainer/devcontainer.jsonin your workspace - Image build: Docker builds the image from
.devcontainer/Dockerfile(first time only) - Container creation: Docker creates a container from the image
- Volume mounting: Your workspace folder is mounted into the container
- Server installation: VS Code Server is installed inside the container
- Extension installation: Configured extensions are installed in the container
- Post-create hook:
postCreateCommandruns to set up the environment - Connection: VS Code UI connects to the container server
- Ready: You can now develop inside the container
TurtleBot3 dev container configuration
File structure
The dev container is configured through files in the.devcontainer/ directory:
Dockerfile
Defines the container image with all necessary software. Base image:- Ubuntu 24.04 Noble
- ROS2 Jazzy desktop-full installation
- Essential development tools
- Gazebo Harmonic simulator
- Navigation2 and Cartographer (SLAM)
- ROS-Gazebo bridge
- OpenGL and Mesa utilities for GPU
- Python dependencies (numpy, transforms3d)
- Development tools (git, vim, colcon, vcstool)
The Dockerfile is only executed during image build. Subsequent container starts reuse the built image.
devcontainer.json
Configures how VS Code integrates with the container. Build configuration:--network=host: Container shares host network stack (simplifies ROS2 networking)--privileged: Required for GPU access--shm-size=2gb: Shared memory for ROS2 message passing--device=/dev/dri: GPU device for hardware acceleration
Desktop-lite feature
The dev container uses thedesktop-lite feature to provide a graphical desktop environment:
- Xfce desktop environment
- TigerVNC server
- noVNC web client
- Supervisor for process management
Lifecycle hooks
Dev containers support lifecycle scripts that run at specific times.postCreateCommand
Runs once when the container is first created.post-create.sh script:
- Detects GPU capabilities and configures rendering
- Sets up
.bashrcwith ROS2 environment sourcing - Adds useful aliases (
tb3_empty,tb3_teleop, etc.) - Clones TurtleBot3 repositories from GitHub
- Installs package dependencies with
rosdep - Creates the
~/mapsdirectory for saved maps
postStartCommand
Runs every time the container starts.post-start.sh script:
- Verifies TurtleBot3 packages exist
- Builds the workspace with
colcon build - Sources the install environment
- Displays quick start instructions
The distinction between post-create and post-start ensures heavy operations (cloning, dependency installation) only happen once, while the build happens on every start to catch any changes.
Working inside the dev container
Terminal sessions
When you open a terminal in VS Code, it automatically runs inside the container. All commands execute in the container environment with access to ROS2, Gazebo, and all installed tools. Automatic environment setup: The.bashrc configured by post-create.sh automatically sources:
File editing
Files in the workspace are accessible from both host and container:- Edit files in VS Code on your host
- Changes immediately appear in the container
- Build and run commands in the container terminal
- Results are visible in both locations
- All files in the workspace directory
- Custom packages in
src/ - Configuration files
- Maps saved to workspace
- The container itself
- Installed apt packages (defined in Dockerfile)
- Files outside the workspace mount
- Build artifacts in
build/,install/,log/
Debugging
VS Code’s debugging features work seamlessly:- Set breakpoints in Python or C++ code
- Debugger runs inside the container
- Access to all ROS2 topics and services
- Full symbol resolution and variable inspection
Customizing the dev container
Adding software packages
Persistent (recommended): EditDockerfile
Changing environment variables
Editdevcontainer.json:
Adding VS Code extensions
Editdevcontainer.json:
Modifying initialization
Editpost-create.sh or post-start.sh to add custom setup steps:
Rebuilding the container
After modifying configuration files, rebuild the container: Full rebuild (recommended after Dockerfile changes):- F1 → “Dev Containers: Rebuild Container”
- Rebuilds image and creates new container
- Runs post-create and post-start scripts
- F1 → “Dev Containers: Rebuild Container Without Cache”
- Forces Docker to rebuild all layers
- Takes longer but ensures clean state
Platform-specific considerations
Windows
- Use WSL 2 backend for best performance
- File I/O can be slower than Linux
- GPU support requires recent Docker Desktop and WSL 2
macOS
- No native GPU passthrough (uses software rendering)
- File sharing can have performance overhead
- Use VirtioFS for improved file system performance
Linux
- Best performance (native Docker)
- Direct GPU access available
- No additional layers between container and hardware
Benefits for ROS2 development
Dev containers are particularly valuable for ROS2 projects:- Complex dependencies: ROS2, Gazebo, Navigation2, and Cartographer are pre-installed and configured
- Environment isolation: Multiple ROS projects can use different ROS distros without conflicts
- Team consistency: Everyone uses the same ROS2 version, packages, and configurations
- CI/CD integration: Same container can be used in automated testing pipelines
- Learning friendly: New developers get a working environment in minutes, not hours