Containerizing ROS: Why Every Robotics Engineer Needs to Learn Docker
Robotics DevOps · Docker · ROS 2
Containerizing ROS: Why Every Robotics Engineer Needs to Learn Docker
By YOUR NAME · April 26, 2026 · 12 min read
If you have spent more than a week working with the Robot Operating System (ROS), you have inevitably uttered the most dangerous phrase in engineering: "But it works on my machine!"
Robotics is rapidly adopting a Software Defined Hardware paradigm. As systems grow more complex — integrating AI, computer vision, and intricate motion planning — managing software environments across different developers, simulators, and physical robots has become a serious challenge. The solution? Docker.
The ROS Dependency Hell
ROS (both ROS 1 and ROS 2) is incredibly powerful, but it is notoriously tightly coupled to the host operating system. A specific ROS distribution demands a specific Ubuntu release:
| ROS Distribution | Required Ubuntu | EOL |
|---|---|---|
| ROS 1 Noetic | Ubuntu 20.04 Focal | May 2025 |
| ROS 2 Humble | Ubuntu 22.04 Jammy | May 2027 |
| ROS 2 Jazzy | Ubuntu 24.04 Noble | May 2029 |
| ROS 2 Rolling | Ubuntu 24.04 Noble | Ongoing |
Add in custom drivers, specialized computer vision libraries like OpenCV or CUDA, and conflicting Python versions, and your environment becomes a fragile house of cards. When you hand your code to a colleague or deploy to a physical robot, those slight environmental differences lead to catastrophic runtime failures.
Recommended Resource: "Docker Mastery: with Kubernetes +Swarm" by Bret Fisher is the #1 Docker course on Udemy with 250,000+ students. Covers everything from basics to production-grade deployment.
View Course on Udemy →Enter Docker: The Ultimate DevOps Tool for Robotics
Docker solves this by packaging your ROS application — libraries, system tools, code, and runtime — into a standardized unit called a container. Think of it as a shipping container for software: the same container works identically on your laptop, your teammate's workstation, a cloud simulator, or the robot's edge computer.
Total Reproducibility
A container built on your laptop runs exactly the same way everywhere — no "works on my machine" ever again.
Version Isolation
Run ROS 2 Humble and ROS 1 Noetic side-by-side without polluting your host OS.
Rapid Onboarding
New team members spin up the entire dev stack in minutes with one docker compose up command.
Reproducible CI/CD
Automate testing and deployment with the exact same environment in your GitHub Actions pipeline.
Getting Started: Your First ROS Docker Container
Step 1 — Pull the Official ROS Image
The Open Source Robotics Foundation (OSRF) maintains official ROS images on Docker Hub at osrf/ros. Pull your target distribution:
# Pull ROS 2 Jazzy (latest LTS)
docker pull osrf/ros:jazzy-desktop
# Or for ROS 2 Humble
docker pull osrf/ros:humble-desktop
# Quick sanity check — run ros2 topic list
docker run --rm -it osrf/ros:jazzy-desktop bash -c "source /opt/ros/jazzy/setup.bash && ros2 topic list"
Step 2 — Write Your Dockerfile
Create a Dockerfile at the root of your ROS workspace. This example adds a custom Python package and builds your ROS 2 package on top of the base image:
# ── Base image: ROS 2 Jazzy on Ubuntu 24.04 ──
FROM osrf/ros:jazzy-desktop
# Set the working directory
WORKDIR /ros2_ws
# Install system dependencies and Python packages
RUN apt-get update && apt-get install -y \
python3-pip \
ros-jazzy-cv-bridge \
ros-jazzy-image-transport \
&& rm -rf /var/lib/apt/lists/*
RUN pip3 install --no-cache-dir \
opencv-python-headless==4.9.0.80 \
numpy scipy
# Copy your ROS package source code
COPY src/ ./src/
# Source ROS and build the workspace
RUN /bin/bash -c "source /opt/ros/jazzy/setup.bash \
&& colcon build --symlink-install"
# Automatically source the workspace on container start
RUN echo "source /ros2_ws/install/setup.bash" >> ~/.bashrc
CMD ["/bin/bash"]
Step 3 — Manage Multi-Container Setups with Docker Compose
Real robotics stacks involve multiple nodes: a core ROS process, a simulation environment (like Gazebo), custom perception nodes, and a visualization tool like RViz. Docker Compose lets you define and run all of these together:
version: '3.8'
services:
# ── ROS 2 core & custom nodes ──
ros_core:
build: .
container_name: ros2_core
environment:
- ROS_DOMAIN_ID=0
volumes:
- ./src:/ros2_ws/src
- /tmp/.X11-unix:/tmp/.X11-unix
network_mode: host
stdin_open: true
tty: true
# ── Gazebo Simulation ──
gazebo:
image: osrf/ros:jazzy-desktop
container_name: gazebo_sim
environment:
- DISPLAY=${DISPLAY}
- ROS_DOMAIN_ID=0
volumes:
- /tmp/.X11-unix:/tmp/.X11-unix
command: bash -c "source /opt/ros/jazzy/setup.bash && ros2 launch my_robot sim.launch.py"
network_mode: host
depends_on:
- ros_core
Start the entire stack with a single command:
docker compose up --build
Run your ROS simulations in the cloud: DigitalOcean Droplets are a cost-effective way to run containerized ROS environments and CI/CD pipelines. Get $200 in free credits for 60 days as a new user.
Get $200 Free Credits →Unlocking CI/CD for Robotics
The real power of Docker unlocks when you move beyond your local machine. Here is a minimal GitHub Actions workflow that builds your container and runs ROS 2 tests on every push:
name: ROS 2 CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
jobs:
build-and-test:
runs-on: ubuntu-24.04
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Build Docker image
run: docker build -t ros2-ci:latest .
- name: Run unit tests in container
run: |
docker run --rm ros2-ci:latest bash -c \
"source /ros2_ws/install/setup.bash \
&& colcon test --packages-select my_robot_pkg \
&& colcon test-result --verbose"
nvidia-container-toolkit installed on the host and --gpus all flag in your Docker run command. See the NVIDIA Container Toolkit docs for setup.
Best Practices at a Glance
- Pin image tags — Never use
:latestin production. Use versioned tags likeosrf/ros:jazzy-desktop-20250401for full reproducibility. - Layer caching — Copy
package.xmland install dependencies before copying source code, so dependency layers are cached across builds. - Use
.dockerignore— Excludebuild/,install/,log/, and.git/to keep context sizes small and builds fast. - Never run as root — Create a non-root user in your Dockerfile to avoid volume permission issues when bind-mounting your source code.
- Externalize config — Use environment variables and volume mounts for robot-specific config (URDF, params). Never bake them into the image.
ROS 1 vs ROS 2 — Docker Changes Everything
| Feature | Without Docker | With Docker |
|---|---|---|
| Environment setup for new dev | 2–3 days | ✓ 15 minutes |
| Run ROS 1 & ROS 2 side by side | ✗ Very difficult | ✓ Trivial |
| CI/CD on GitHub Actions | ✗ Complex setup | ✓ Native support |
| Deploy to edge robot | Error-prone | ✓ Consistent |
| Reproduce a bug from 6 months ago | ✗ Nearly impossible | ✓ Just run the old image |
Highly recommended book: "Programming Robots with ROS" (O'Reilly) gives you a solid ROS foundation to pair with what you've learned here. Available on Amazon.
View on Amazon →The Bottom Line
In the era of Software Defined Hardware, writing the code is only half the battle — deploying it reliably is the rest. Docker gives robotics engineers the exact tooling they need to stop fighting dependency errors and start building better robots.
The learning curve is gentle. Pull an official image, write a simple Dockerfile, and wire it up with Docker Compose. Within a week you will wonder how you ever worked without it.
Ready to containerize your ROS environment?
Follow along with the companion GitHub repo, or start with the official ROS Docker images.
View GitHub Repo Official ROS Images ↗Disclosure: This post contains affiliate links. If you make a purchase through them, AppliedKaos may earn a small commission at no extra cost to you. All recommendations are based on genuine use and opinion.
Comments
Post a Comment