Skip to content

Commit 2b841c4

Browse files
authored
[ROS] Update Official Docker image docs (#2578)
* Remove references to dedicated ROS distros as final ROS 1 version, Noetic, is now EOL * Redirect primary links to documentation landing page as docs page is more up-to-date and pertinent for users * Remove retired ROS blog - https://www.ros.org/news/2020/01/ros-blog-retired.html * Update OSRF URL redirect * Update example image tag to rolling to avoid docs from becoming stale * Consolidate branding and dated references * Update Q&A links to stackexchange given migration - https://discourse.ros.org/t/planned-migration-of-ros-answers-and-gazebo-answers-to-robotics-stack-exchange/28068 - https://discourse.ros.org/t/new-static-archives-for-ros-and-gazebo-answers/41346 * Simplify cloning overlay source * Simplify use of mixin setting * Split runner and builder stages as example to save on image size as well as on build time using caching * Simplify scripting for dependencies * Lint use of ARGs for readability of each stage * Simplify example cache mount for apt and update rosdep along with apt list to ensure package index is fresh * Update categories for ROS to include additional relevant entries * Shorten derivation script * Use ros-core tag for minimal installer * Stage example image sizes for demos * Simplify naming * Omit cacher from size table to focus on primary targets * Modify and mount custom apt config accounting for included docker-clean default * Simplify RUN directive for apt config * Stage WIP edits * Update package cache before cloning source to avoid running rosdep update for each source change as docker build --no-cache can still be used to force update * Fix use of EOF in Dockerfile * Simply RUN directives * Expand bullet points about optimizations * Expand upon runner vs installer comparison * Linting * Fix grammar and spelling * Linting * Rename stage in apt get example while keeping with uniquely spelled noun that is self descriptive yet unmistakable * Comment on overwriting defaults to persist minimal cache
1 parent 0d4dd5b commit 2b841c4

File tree

2 files changed

+99
-96
lines changed

2 files changed

+99
-96
lines changed

ros/content.md

Lines changed: 97 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
# What is [ROS](https://www.ros.org/)?
1+
# What is [ROS](https://docs.ros.org/)?
22

33
The Robot Operating System (ROS) is a set of software libraries and tools that help you build robot applications. From drivers to state-of-the-art algorithms, and with powerful developer tools, ROS has what you need for your next robotics project. And it's all open source.
44

55
> [wikipedia.org/wiki/Robot_Operating_System](https://en.wikipedia.org/wiki/Robot_Operating_System)
66
7-
[%%LOGO%%](https://www.ros.org/)
7+
[%%LOGO%%](https://docs.ros.org/)
88

99
# How to use this image
1010

@@ -13,7 +13,7 @@ The Robot Operating System (ROS) is a set of software libraries and tools that h
1313
To create your own ROS docker images and install custom packages, here's a simple example of installing the C++, Python client library demos using the official released Debian packages via apt-get.
1414

1515
```dockerfile
16-
FROM %%IMAGE%%:foxy
16+
FROM %%IMAGE%%:rolling-ros-core as aptgetter
1717

1818
# install ros package
1919
RUN apt-get update && apt-get install -y \
@@ -28,8 +28,8 @@ CMD ["ros2", "launch", "demo_nodes_cpp", "talker_listener_launch.py"]
2828
Note: all ROS images include a default entrypoint that sources the ROS environment setup before executing the configured command, in this case the demo packages launch file. You can then build and run the Docker image like so:
2929

3030
```console
31-
$ docker build -t my/ros:app .
32-
$ docker run -it --rm my/ros:app
31+
$ docker build -t my/ros:aptgetter .
32+
$ docker run -it --rm my/ros:aptgetter
3333
[INFO] [launch]: process[talker-1]: started with pid [813]
3434
[INFO] [launch]: process[listener-2]: started with pid [814]
3535
[INFO] [talker]: Publishing: 'Hello World: 1'
@@ -44,59 +44,85 @@ $ docker run -it --rm my/ros:app
4444
To create your own ROS docker images and build custom packages, here's a simple example of installing a package's build dependencies, compiling it from source, and installing the resulting build artifacts into a final multi-stage image layer.
4545

4646
```dockerfile
47-
ARG FROM_IMAGE=%%IMAGE%%:foxy
47+
ARG FROM_IMAGE=%%IMAGE%%:rolling
4848
ARG OVERLAY_WS=/opt/ros/overlay_ws
4949

5050
# multi-stage for caching
5151
FROM $FROM_IMAGE AS cacher
52+
ARG OVERLAY_WS
53+
54+
# overwrite defaults to persist minimal cache
55+
RUN rosdep update --rosdistro $ROS_DISTRO && \
56+
cat <<EOF > /etc/apt/apt.conf.d/docker-clean && apt-get update
57+
APT::Install-Recommends "false";
58+
APT::Install-Suggests "false";
59+
EOF
5260

5361
# clone overlay source
54-
ARG OVERLAY_WS
5562
WORKDIR $OVERLAY_WS/src
56-
RUN echo "\
57-
repositories: \n\
58-
ros2/demos: \n\
59-
type: git \n\
60-
url: https://github.com/ros2/demos.git \n\
61-
version: ${ROS_DISTRO} \n\
62-
" > ../overlay.repos
63-
RUN vcs import ./ < ../overlay.repos
64-
65-
# copy manifests for caching
66-
WORKDIR /opt
67-
RUN mkdir -p /tmp/opt && \
68-
find ./ -name "package.xml" | \
69-
xargs cp --parents -t /tmp/opt && \
70-
find ./ -name "COLCON_IGNORE" | \
71-
xargs cp --parents -t /tmp/opt || true
63+
RUN cat <<EOF | vcs import .
64+
repositories:
65+
ros2/demos:
66+
type: git
67+
url: https://github.com/ros2/demos.git
68+
version: ${ROS_DISTRO}
69+
EOF
70+
71+
# derive build/exec dependencies
72+
RUN bash -e <<'EOF'
73+
declare -A types=(
74+
[exec]="--dependency-types=exec"
75+
[build]="")
76+
for type in "${!types[@]}"; do
77+
rosdep install -y \
78+
--from-paths \
79+
ros2/demos/demo_nodes_cpp \
80+
ros2/demos/demo_nodes_py \
81+
--ignore-src \
82+
--reinstall \
83+
--simulate \
84+
${types[$type]} \
85+
| grep 'apt-get install' \
86+
| awk '{gsub(/'\''/,"",$4); print $4}' \
87+
| sort -u > /tmp/${type}_debs.txt
88+
done
89+
EOF
7290

7391
# multi-stage for building
7492
FROM $FROM_IMAGE AS builder
75-
76-
# install overlay dependencies
7793
ARG OVERLAY_WS
78-
WORKDIR $OVERLAY_WS
79-
COPY --from=cacher /tmp/$OVERLAY_WS/src ./src
80-
RUN . /opt/ros/$ROS_DISTRO/setup.sh && \
81-
apt-get update && rosdep install -y \
82-
--from-paths \
83-
src/ros2/demos/demo_nodes_cpp \
84-
src/ros2/demos/demo_nodes_py \
85-
--ignore-src \
86-
&& rm -rf /var/lib/apt/lists/*
94+
95+
# install build dependencies
96+
COPY --from=cacher /tmp/build_debs.txt /tmp/build_debs.txt
97+
RUN --mount=type=cache,target=/etc/apt/apt.conf.d,from=cacher,source=/etc/apt/apt.conf.d \
98+
--mount=type=cache,target=/var/lib/apt/lists,from=cacher,source=/var/lib/apt/lists \
99+
--mount=type=cache,target=/var/cache/apt,sharing=locked \
100+
< /tmp/build_debs.txt xargs apt-get install -y
87101

88102
# build overlay source
103+
WORKDIR $OVERLAY_WS
89104
COPY --from=cacher $OVERLAY_WS/src ./src
90-
ARG OVERLAY_MIXINS="release"
91105
RUN . /opt/ros/$ROS_DISTRO/setup.sh && \
92106
colcon build \
93107
--packages-select \
94108
demo_nodes_cpp \
95109
demo_nodes_py \
96-
--mixin $OVERLAY_MIXINS
110+
--mixin release
111+
112+
# multi-stage for running
113+
FROM $FROM_IMAGE-ros-core AS runner
114+
ARG OVERLAY_WS
115+
116+
# install exec dependencies
117+
COPY --from=cacher /tmp/exec_debs.txt /tmp/exec_debs.txt
118+
RUN --mount=type=cache,target=/etc/apt/apt.conf.d,from=cacher,source=/etc/apt/apt.conf.d \
119+
--mount=type=cache,target=/var/lib/apt/lists,from=cacher,source=/var/lib/apt/lists \
120+
--mount=type=cache,target=/var/cache/apt,sharing=locked \
121+
< /tmp/exec_debs.txt xargs apt-get install -y
97122

98-
# source entrypoint setup
99-
ENV OVERLAY_WS $OVERLAY_WS
123+
# setup overlay install
124+
ENV OVERLAY_WS=$OVERLAY_WS
125+
COPY --from=builder $OVERLAY_WS/install $OVERLAY_WS/install
100126
RUN sed --in-place --expression \
101127
'$isource "$OVERLAY_WS/install/setup.bash"' \
102128
/ros_entrypoint.sh
@@ -105,11 +131,36 @@ RUN sed --in-place --expression \
105131
CMD ["ros2", "launch", "demo_nodes_cpp", "talker_listener_launch.py"]
106132
```
107133

108-
The example above starts by using [`vcstool`](https://github.com/dirk-thomas/vcstool) to clone source repos of interest into the cacher stage. One could similarly `COPY` code from the local build context into the source directory as well. Package manifest files are then cached in a temporary directory where the following builder stage may copy from to install necessary dependencies with [`rosdep`](https://github.com/ros-infrastructure/rosdep). This is done prior to copying the rest of the source files to preserve the multi-stage build cache, given unaltered manifests do not alter declared dependencies, saving time and bandwidth. The overlay is then built using [`colcon`](https://colcon.readthedocs.io/en/released/), the entrypoint updated to source the workspace, and the default command set to launch the demo.
134+
The example above consists of three sequential stages. The `cacher` stage first updates the apt lists and ROS index, uses [`vcstool`](https://github.com/dirk-thomas/vcstool) to clone a demo repo into the workspace source directory, and derives build and runtime dependency sets using [`rosdep`](https://docs.ros.org/en/rolling/Tutorials/Intermediate/Rosdep.html). The `builder` stage installs the derived build dependencies, sources the ROS install underlay, and compiles the source in release mode using [`colcon`](https://docs.ros.org/en/rolling/Tutorials/Beginner-Client-Libraries/Colcon-Tutorial.html). Finally, the `runner` stage installs only runtime dependencies, copies the compiled workspace artifacts, and sets up the environment to launch the demo. Note the example consists of several subtle optimizations:
135+
136+
- Multi-Stage Build
137+
- Dependency derivation, compilation, and runtime setup are partitioned
138+
- Maximizes cache retention despite package source or build/runtime changes
139+
- Greater concurrency, e.g., colcon build while runtime apt installs
140+
- Persistent Cache Propagation
141+
- Use of [`--mount`](https://docs.docker.com/engine/reference/builder/#run---mount) to cache temp data without bloating layers
142+
- Maintain temporally consistent apt lists between parallel stages
143+
- Avoid needless network I/O between stages or across Docker rebuilds
144+
- Minimal Image Size
145+
- Final stage builds from `ros-core` for smallest runtime image
146+
- Builds and installs only a select few packages in the workspace
147+
- Only workspace install artifacts are copied into final layers
109148

110-
Note: `--from-paths` and `--packages-select` are set here as so to only install the dependencies and build for the demo C++ and Python packages, among many in the demo git repo that was cloned. To install the dependencies and build all the packages in the source workspace, merely change the scope by setting `--from-paths src/` and dropping the `--packages-select` arguments.
149+
For comparison, the resulting `runner` image is similar in size to the earlier `aptgetter` example. This allows you to develop and distribute custom ROS packages without significantly increasing image size compared to pre-built Debian installations:
111150

112-
For more advance examples such as daisy chaining multiple overlay workspaces to improve caching of docker image build layers, using tools such as ccache to accelerate compilation with colcon, or using buildkit to save build time and bandwidth even when dependencies change, the project `Dockerfile`s in the ROS 2 [Navigation2](https://github.com/ros-planning/navigation2) repo are excellent resources.
151+
```console
152+
$ docker image ls my/ros --format "table {{.Tag}}\t{{.Size}}"
153+
TAG SIZE
154+
aptgetter 504MB
155+
runner 510MB
156+
builder 941MB
157+
$ docker image ls ros --format "table {{.Tag}}\t{{.Size}}"
158+
TAG SIZE
159+
rolling-ros-core 489MB
160+
rolling 876MB
161+
```
162+
163+
For more advance examples such as daisy chaining multiple overlay workspaces to improve caching of docker image build layers, using tools such as ccache to accelerate compilation with colcon, or using buildkit to save build time and bandwidth even when dependencies change, the project `Dockerfile`s in the [Navigation2](https://github.com/ros-planning/navigation2) repo are excellent resources.
113164

114165
## Deployment use cases
115166

@@ -119,19 +170,18 @@ Developing such complex systems with cutting edge implementations of newly publi
119170

120171
With the advancements and standardization of software containers, roboticists are primed to acquire a host of improved developer tooling for building and shipping software. To help alleviate the growing pains and technical challenges of adopting new practices, we have focused on providing an official resource for using ROS with these new technologies.
121172

122-
For a complete listing of supported architectures and base images for each ROS Distribution Release, please read the official REP on target platforms for either [ROS 1](https://www.ros.org/reps/rep-0003.html) or for [ROS 2](https://www.ros.org/reps/rep-2000.html).
173+
For a complete listing of supported architectures and base images for each ROS Distribution Release, please read the official REP on target platforms [here](https://www.ros.org/reps/rep-2001.html).
123174

124175
## Deployment suggestions
125176

126177
The available tags include supported distros along with a hierarchy tags based off the most common meta-package dependencies, designed to have a small footprint and simple configuration:
127178

128179
- `ros-core`: minimal ROS install
129180
- `ros-base`: basic tools and libraries (also tagged with distro name with LTS version as `latest`)
130-
- `ros1-bridge`: tools and libraries to run hybrid ROS 1 - ROS 2 systems and bridge messages between them
131181

132182
In the interest of keeping `ros-core` tag minimal in image size, developer tools such as `rosdep`, `colcon` and `vcstools` are not shipped in `ros_core`, but in `ros-base` instead.
133183

134-
The rest of the common meta-packages such as `desktop` are hosted on repos under OSRF's Docker Hub profile [here](https://hub.docker.com/r/osrf/ros/). These meta-packages include graphical dependencies and hook a host of other large packages such as X11, X server, etc. So in the interest of keeping the official images lean and secure, the desktop packages are just being hosted with OSRF's profile. For an extensive list of available variants, please read the official REP on target platforms for either [ROS 1](https://ros.org/reps/rep-0150.html) or for [ROS 2](https://www.ros.org/reps/rep-2001.html).
184+
The rest of the common meta-packages such as `desktop` are hosted on repos under OSRF's Docker Hub profile [here](https://hub.docker.com/r/osrf/ros/). These meta-packages include graphical dependencies and hook a host of other large packages such as X11, X server, etc. So in the interest of keeping the official images lean and secure, the desktop packages are just being hosted with OSRF's profile.
135185

136186
### Volumes
137187

@@ -201,59 +251,10 @@ $ docker compose rm
201251

202252
> Note: the auto-generated network, `ros_demos_default`, will persist until you explicitly remove it using `docker compose down`.
203253

204-
### ROS 1 Bridge
205-
206-
To ease ROS 2 migration, [`ros1_bridge`](https://index.ros.org/p/ros1_bridge) is a ROS 2 package that provides bidirectional communication between ROS 1 and ROS 2. As a minimal example, given the ROS 2 Dockerfile above, we'll create the ROS 1 equivalent below, and name the Dockerfile appropriately.
207-
208-
```dockerfile
209-
FROM %%IMAGE%%:noetic
210-
211-
# install ros package
212-
RUN apt-get update && apt-get install -y \
213-
ros-${ROS_DISTRO}-ros-tutorials \
214-
ros-${ROS_DISTRO}-common-tutorials && \
215-
rm -rf /var/lib/apt/lists/*
216-
217-
# launch ros package
218-
CMD ["roslaunch", "roscpp_tutorials", "talker_listener_launch"]
219-
```
220-
221-
The compose file bellow spawns services for both talker listener demos while connecting the two via a dynamic bridge. You may then view the log output from both pairs of talker and listener nodes cross talking over the `/chatter` topic.
222-
223-
```yaml
224-
services:
225-
ros1:
226-
build:
227-
context: ./
228-
dockerfile: ros1.Dockerfile
229-
230-
ros2:
231-
build:
232-
context: ./
233-
dockerfile: ros2.Dockerfile
234-
235-
bridge:
236-
image: ros:foxy-ros1-bridge
237-
environment:
238-
- "ROS_HOSTNAME=bridge"
239-
- "ROS_MASTER_URI=http://ros1:11311"
240-
command: ros2 run ros1_bridge dynamic_bridge
241-
```
242-
243254
# More Resources
244255

245-
[ROS.org](http://www.ros.org/): Main ROS website
246-
[Q&A](https://answers.ros.org/questions/): Ask questions. Get answers
256+
[Docs](https://docs.ros.org/): ROS Developer Documentation
257+
[Q&A](https://robotics.stackexchange.com/): Ask questions. Get answers
247258
[Forums](https://discourse.ros.org/): Hear the latest discussions
248-
[Blog](http://www.ros.org/news/): Stay up-to-date
249259
[Packages](https://index.ros.org/?search_packages=true): Discover indexed packages
250-
[OSRF](https://www.osrfoundation.org/): Open Source Robotics Foundation
251-
252-
## ROS 2
253-
254-
[Index](https://docs.ros.org): ROS 2 Documentation
255-
[Design](https://design.ros2.org/): ROS 2 Design Articles
256-
257-
## ROS 1
258-
259-
[Wiki](http://wiki.ros.org/Documentation): ROS 1 Documentation
260+
[OSRF](https://www.openrobotics.org/): Open Source Robotics Foundation

ros/metadata.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
{
22
"hub": {
33
"categories": [
4+
"languages-and-frameworks",
5+
"machine-learning-and-ai",
46
"operating-systems"
57
]
68
}

0 commit comments

Comments
 (0)