Missed Part 3 of the “Practical Embedded Development, Containerized” series? Read about Bridging the Three Worlds in Containerized Embedded Develoment first.
You’re sold on containerizing embedded development — but the wrong tools mean fighting daemon overhead, security risks, or cloud development environments that can’t reach your JTAG debugger or USB hardware. As this series has shown, containers eliminate "works on my machine" problems by packaging toolchains and debugger setups into reproducible, portable environments.
Now it’s time to pick the right tools for containerized embedded workflows. This guide covers:
✅ Podman vs. Docker: Why Podman’s daemonless design wins for security and performance — and where Docker’s polished UI and multi-platform builds still excel.
✅ VSCode DevContainers: How the open DevContainer Spec turns containers into standardized IDEs — with direct hardware access.
✅ GitHub Codespaces: When cloud development environments work (and where they fail for embedded development).
✅ Other Tools: Beyond Docker/Podman for legacy toolchains, on-premises CI with hardware access, and Kubernetes-native workflows.
No vendor lock-in. No hand-wavy advice. Just industry-standard tools for embedded engineers.
OCI and DevContainer Standards: The Foundation
Before comparing tools, let’s ground ourselves in the standards that make them interchangeable. These aren’t theoretical — they’re what let you build once, run anywhere, without rewriting configs when tools evolve.
OCI Standard: The USB of Containers
The Open Container Initiative (OCI)External link opens in new tab standardizes containers. Just as USB lets any device plug into any computer — regardless of brand or OS — OCI ensures any container runs on any compliant tool (Podman, Docker, Kubernetes, etc.). It defines three critical specs:
Runtime SpecExternal link opens in new tab: How containers execute: process isolation, filesystem bundles — the “connector shape”.
Image SpecExternal link opens in new tab: How images are structured, built, and shared — the “data transfer protocol”.
Distribution SpecExternal link opens in new tab: How container images are stored and pulled from registries — the "USB hub".
Why it matters for embedded:
Tool agnosticism: Build with Podman, debug with Docker, deploy with Kubernetes — same image, zero changes.
Future-proofing: Your 2020
Dockerfilestill works today (like USB 2.0 in a USB-C port with an adapter).Ecosystem leverage: CI systems, registries, and orchestrators all “speak OCI”.
Example: A Podman-built image runs unchanged in Docker, containerd, or AWS ECS.
DevContainer Spec: IKEA Instructions for Your Dev Environment
While OCI standardizes containers, the DevContainer SpecificationExternal link opens in new tab standardizes development environments. Just as IKEA’s flat-pack designs let you assemble the same bookshelf in any home, this spec lets you replicate a full workspace (toolchain, debuggers, IDE settings) from a single devcontainer.json file.
Key Components:
Configuration formatExternal link opens in new tab (
.devcontainer.json): Blueprint for base image, runtime args, extensions, and hardware access.FeaturesExternal link opens in new tab: Modular components (e.g.,
common-utils,docker-in-docker) to avoid reinventing setups.
Why it matters for teams:
Shareable configs: One file (
devcontainer.json) replicates your entire environment.IDE-agnostic: Officially supported by VSCode and GitHub Codespaces; adopted by other IDEs (e.g., JetBrains IDEs, Eclipse).
Hardware-aware: USB/JTAG passthrough works if your host OS permits it.
Example: Minimal embedded setup with a custom Dockerfile control:
{
"name": "Custom Embedded DevContainer",
"build": {
"dockerfile": "./Dockerfile"
},
"runArgs": ["--device=/dev/ttyACM0"],
"customizations": {
"vscode": {
"extensions": ["ms-vscode.cpptools"]
}
}
}Standards turn containers from "works on my machine" to "works on every machine" — with no lock-in.
These standards enable an entire ecosystem. Here’s how the pieces fit together:

Podman vs. Docker: Architectural Trade-offs
Both PodmanExternal link opens in new tab and DockerExternal link opens in new tab implement OCI standardsExternal link opens in new tab, but their underlying designs create key differences:
| Criteria | Podman | Docker |
|---|---|---|
| Security | ✅ Rootless default | ⚠️ Rootless optional |
| Performance | ✅ Daemonless (lower overhead) | ❌ Daemon overhead |
| Ease of Setup | ⚠️ VM required on Mac/Windows | ✅ Native desktop app |
| OCI Compliance | ✅ Full (community-driven) | ✅ Full (reference implementation) |
Podman’s Strength
Daemonless architectureExternal link opens in new tab means no persistent dockerd process to manage or debug. This translates to:
Faster container startup times
Cleaner resource isolation
No single point of failure behind containers
Security-first design with rootless operation by default. For embedded work involving proprietary toolchains and hardware access, this reduces:
Attack surface area
Compliance risks in regulated environments
Fully open-source implementation gives full auditability.
Docker's Strengths
Polished user experience through Docker DesktopExternal link opens in new tab:
Intuitive GUI for container management
Built-in dashboard for monitoring resources
Easier onboarding for teams new to containers
Mature ecosystem with:
buildxfor well-documented multi-platform buildsExternal link opens in new tabExtensive plugin supportExternal link opens in new tab (volume drivers, logging, etc.)
⚠️ Podman’s VM Layer on Mac/Windows
Set VM resources upfront:
podman machine set --cpus=4 --memory=4096 --disk-size=20USB/JTAG passthrough:
macOS: Manual attachment needed.
Windows: USB/IP forwarding needed, which may add latency.
Test early — some debuggers misbehave through the VM.
The Bottom Line
Choose Podman if you prioritize:
✅ Security and compliance
✅ Kubernetes-aligned architecture
✅ Linux-native workflows (best experience)
✅ Open-source purity
Choose Docker if you need:
✅ Easiest team onboarding
✅ Multi-platform build maturity
✅ Windows compatibility (native device access)
✅ Proprietary tooling integrations
For most embedded teams — especially on Linux — Podman's advantages outweigh Docker's convenience. However, Windows users may prefer Docker for native device access.
But selecting a runtime is only half the battle. The real challenge? Ensuring every engineer — from the CI pipeline to the hardware bench — uses the same environment, with the same tools, and the same access to devices. That’s where VSCode DevContainersExternal link opens in new tab bridges the gap: turning containers into reproducible workspaces that travel with your project.
VSCode DevContainers: IDE as Code
VSCode DevContainersExternal link opens in new tab turn containers into reproducible workspaces by encoding your environment — IDE settings, extensions, and hardware access — in version-controlled configs. The only setup required: cloning the repo.
Why It’s a Game-Changer
Vendor-Neutral Foundation
It works identically across systems via the open DevContainer SpecificationExternal link opens in new tab.IDE as Code
Your.devcontainer/devcontainer.jsondefines:Toolchain versions (compilers, debuggers)
IDE extensions (C/C++ tools, Cortex-Debug)
Runtime arguments (device passthrough, privileges)
Hardware-Awareness
Devices expose to the container via your host’s Docker/Podman. You configure all hardware access indevcontainer.jsonjust as you would for a standalone container.
Example config:
{
"image": "ghcr.io/your-org/embedded-dev:latest",
"runArgs": ["--device=/dev/ttyUSB0"], // Direct USB access
"customizations": {
"vscode": {
"extensions": [
"ms-vscode.cpptools" // C/C++ support
],
"settings": {
"terminal.integrated.shell.linux": "/usr/bin/bash"
}
}
},
"features": {
"ghcr.io/devcontainers/features/common-utils:2": {} // git, curl, etc.
}
}Setup Steps for VSCode DevContainers
Setup requirement: Install the VSCode DevContainers extensionExternal link opens in new tab. It works with Docker out-of-the-box; for Podman, configure the Docker executable path in VSCode settings to point to
podman.Workflow: When opening a project with DevContainers configured, use the
DevContainers: Reopen in Containercommand to start the containerized environment.User experience: Once running in a container, VSCode behaves identically to local development or remote SSH — just with your environment fully containerized.
DevContainers solve local standardization — but what about the cloud?
GitHub Codespaces: Cloud Portability (With Limits)
GitHub CodespacesExternal link opens in new tab extends DevContainers to the cloud, offering browser-accessible environments — ideal for collaboration but useless for hardware debugging.
The Embedded Limitation
❌ No hardware access.
Codespaces runs in a remote VM without local device connectivity. This means that your embedded hardware (JTAG debuggers, USB devices, serial ports) remains completely unavailable. Use Codespaces only for cloud-native tasks (e.g., code reviews, documentation, build testing).
Where It Excels
✅ Cloud-native tasks: Spin up identical environments for code reviews, documentation, building, and simulation.
✅ Online collaboration: Shared environments for pair programming or onboarding.
✅Zero local setup: Develop from any machine with just a browser (or VSCode desktopExternal link opens in new tab).
✅ Preconfigured environments: Uses the same devcontainer.json as local DevContainers.
Availability & Usage
Free for personal accounts (with usage limits) on GitHub-hosted repositories.
Enterprise/managed accounts require paid access.
Best practice: Reserve Codespaces for occasional online collaboration or development on the go (when hardware debugging isn’t needed). Combined with GitHub ActionsExternal link opens in new tab, it’s ideal for CI-based build testing and simulations.
Choosing between local and cloud DevContainers? Here’s how they stack up for embedded development:
| Feature | VSCode DevContainers | GitHub Codespaces |
|---|---|---|
| Hardware Access | ✅ Full (USB/JTAG/serial passthrough) | ❌ None (remote VM restriction) |
| Configuration | ✅ Same .devcontainer.json (local execution) | ✅ Same .devcontainer.json (cloud execution) |
| Portability | ✅ Run anywhere (local machine, teammate’s laptop) | ✅ Run anywhere with internet (but no local hardware) |
| OS Support | ✅ Cross-platform (Win/macOS/Linux) | ✅ Any browser |
| IDE Integration | ✅ Native (VSCode + extensions) | ✅ Full (VSCode in browser) |
| Performance | ✅ Near-native (container overhead) | ⚠️ Cloud latency |
| Security | ✅ Isolated (local rootless containers) | ⚠️ Cloud VM (org trust required) |
| Cost | Free (local) | Free (limited) / Paid |
| Collaboration | ⚠️ Local-only (share via Git) | ✅ Built-in (live shared envsExternal link opens in new tab) |
| Use Case | Best for: Daily development, hardware debugging, team onboarding | Best for: cloud-only tasks (e.g., PR reviews, docs, CI build testing) |
The Broader Ecosystem
While Docker/Podman + DevContainers cover most use cases, the container ecosystem is much broader and offers tools that you might encounter.
Container Runtimes
Container Engines as Docker and Podman rely on Container Runtimes like containerdExternal link opens in new tab (or directly on runc/crun) under the hood. You can use containerd directly for minimal overhead, but expect no dev-friendly features — it’s a plumbing layer, not a replacement. nerdctlExternal link opens in new tab is a Docker-like CLI for containerd, useful if you’re in a Kubernetes environment and miss docker build.
For experimental setups, lilipodExternal link opens in new tab (a minimal and limited container runtime in Rust) and youkiExternal link opens in new tab (an OCI runtime also in Rust) offer lighter-weight options, but neither is production-ready for embedded work yet.
Alternative Environment
distroboxExternal link opens in new tab lets you run full Linux distributions (e.g., Ubuntu 18.04) as containers — ideal for legacy toolchains or proprietary EDA tools without VMs.
DevContainers in Other IDEs
The DevContainer Spec isn’t VSCode-exclusive. JetBrains IDEsExternal link opens in new tab and Visual StudioExternal link opens in new tab support it officially. CodeSandboxExternal link opens in new tab provides a cloud development environment similar to GitHub Codespaces.
DevfilesExternal link opens in new tab is a vendor-neutral alternative to DevContainers. Reproducible environments are defined in a devfile.yaml, which is optimized for cloud/remote workspaces and supported by Eclipse CheExternal link opens in new tab and OpenShift DevSpacesExternal link opens in new tab. Devfiles are less mature for embedded work due to limited hardware passthrough. Worth monitoring if you’re in a Kubernetes-heavy ecosystem.
CI with Hardware
For on-premises CI with JTAG/USB access, use:
KubernetesExternal link opens in new tab + device pluginsExternal link opens in new tab (complex but powerful).
GitHub ActionsExternal link opens in new tab + self-hosted runnersExternal link opens in new tab (simpler, if your runners have USB passthrough).
HelmExternal link opens in new tab to package/deploy containerized toolchains to your own infrastructure.
Further Reading & Experiments
To go deeper, here are practical resources for containerized embedded development:
Bookmark Suggestions
Podman:
- Podman Rootless GuideExternal link opens in new tab Critical for security-compliant embedded development.
DevContainers Community:
DevContainer SpecificationExternal link opens in new tab The "IKEA instructions" for your development environment — study this before customizing.
Official DevContainer TemplatesExternal link opens in new tab Prebuilt configurations for common languages/tools.
Official DevContainer ResourcesExternal link opens in new tab All repositories from the DevContainer Community.
Embedded-Specific DevContainers:
Embedded Container ResourcesExternal link opens in new tab A curated collection of embedded-specific DevContainers.
ARM Cortex-M DevContainerExternal link opens in new tab A DevContainer for developing and debugging on ARM Cortex-M.
Philips AMP DevContainerExternal link opens in new tab DevContainers for embedded C++ and Rust development.
Experiments to Try
Legacy Toolchain: Containerize GCC 5.4 in
distroboxto replace a VMDebugger Test: Compare Podman vs. Docker with your JTAG debugger.
CI Pipeline: Use GitHub Actions + Codespaces to test builds without hardware, and then with a self-hosted runner with USB passthrough.
The container ecosystem is ready for embedded work today. Start with Docker/Podman + DevContainers, then explore advanced tools as needed. The frontier? Standardizing hardware access across runtimes and clouds.

Dávid Juhász