Skip to content

Commit 2a11cee

Browse files
committed
feat(docker): add new Dockerfiles, HCL bake config, and ansible playbook
Add the docker-new pipeline foundation: base, core, and universe Dockerfiles with multi-stage builds, docker-bake.hcl for buildx bake orchestration, ansible playbook with tag-based role selection, entrypoint with UID/GID remapping, and CycloneDDS config. Images build locally with `docker buildx bake -f docker-new/docker-bake.hcl`. No existing files or workflows are affected. Part of #7003. Signed-off-by: Mete Fatih Cırıt <mfc@autoware.org>
1 parent 1e0efff commit 2a11cee

9 files changed

Lines changed: 625 additions & 0 deletions

File tree

.hadolint.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,4 @@ ignored:
33
- DL3013 # Pin versions in pip. Instead of `pip install <package>`, use `pip install <package>==<version>`
44
- DL3015 # Avoid additional packages by specifying `--no-install-recommends`
55
- DL3009 # Delete the apt-get lists after installing something
6+
- DL3002 # Last USER should not be root (multi-stage builds need root in intermediate stages)
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
- name: Autoware development environment
2+
hosts: localhost
3+
connection: local
4+
vars:
5+
rosdistro:
6+
pre_tasks:
7+
- name: Print configuration
8+
ansible.builtin.debug:
9+
msg:
10+
- rosdistro: "{{ rosdistro }}"
11+
tags: [always]
12+
13+
roles:
14+
- role: autoware.dev_env.rmw_implementation
15+
tags: [base, core, universe, rmw]
16+
17+
- role: autoware.dev_env.build_tools
18+
tags: [core, universe, ccache]
19+
20+
- role: autoware.dev_env.dev_tools
21+
tags: [core, universe, dev_tools]
22+
23+
- role: autoware.dev_env.ros2_dev_tools
24+
tags: [core, universe, ros2_dev_tools]
25+
26+
- role: autoware.dev_env.acados
27+
tags: [universe, acados]
28+
29+
- role: autoware.dev_env.geographiclib
30+
tags: [universe, geographiclib]
31+
32+
- role: autoware.dev_env.qt5ct_setup
33+
tags: [universe, qt5ct_setup]
34+
35+
- role: autoware.dev_env.cuda
36+
tags: [universe, nvidia, cuda]
37+
38+
- role: autoware.dev_env.tensorrt
39+
tags: [universe, nvidia, tensorrt]
40+
41+
- role: autoware.dev_env.spconv
42+
tags: [universe, nvidia, spconv]
43+
44+
- role: autoware.dev_env.artifacts
45+
tags: [universe, artifacts]

docker-new/README.md

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
# Run Autoware in Docker
2+
3+
## Image Graph
4+
5+
```mermaid
6+
graph TD
7+
base(["base"])
8+
base --> core-dependencies(["core-dependencies"])
9+
core-dependencies --> core-devel(["core-devel"])
10+
core-devel --> universe-dependencies(["universe-dependencies"])
11+
universe-dependencies --> universe-dependencies-cuda(["universe-dependencies-cuda"])
12+
universe-dependencies --> universe-devel(["universe-devel"])
13+
universe-dependencies-cuda --> universe-devel-cuda(["universe-devel-cuda"])
14+
base --> core(["core"])
15+
core-devel -- " COPY /opt/autoware " --> core
16+
core --> universe-runtime-dependencies(["universe-runtime-dependencies"])
17+
universe-runtime-dependencies --> universe(["universe"])
18+
universe-runtime-dependencies --> universe-cuda(["universe-cuda"])
19+
universe-devel -- " COPY /opt/autoware " --> universe
20+
universe-devel-cuda -- " COPY /opt/autoware " --> universe-cuda
21+
classDef base fill: #e8e8e8, color: #333
22+
classDef devel fill: #bbdefb, color: #333
23+
classDef runtime fill: #c8e6c9, color: #333
24+
classDef cuda fill: #e1bee7, color: #333
25+
class base base
26+
class core-dependencies,core-devel,universe-dependencies,universe-devel devel
27+
class core,universe-runtime-dependencies,universe runtime
28+
class universe-dependencies-cuda,universe-devel-cuda,universe-cuda cuda
29+
```
30+
31+
## Images
32+
33+
| Image | Description | Use case |
34+
| ------------------------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
35+
| `base` | ROS base, sudo, pipx, ansible, RMW, user `aw` | Foundation for all other images |
36+
| `core-dependencies` | Build deps + compiled core packages (except autoware_core and autoware_rviz_plugins) | CI for autoware_core |
37+
| `core-devel` | Adds autoware_core build on top of core-dependencies | Development and CI for packages depending on autoware_core |
38+
| `core` | Runtime-only: rosdep exec deps + compiled core from core-devel | Lightweight core runtime |
39+
| `universe-dependencies` | Ansible universe roles + rosdep build deps for all of autoware | CI for autoware_universe |
40+
| `universe-dependencies-cuda` | Adds CUDA, TensorRT, spconv dev libs | CI for CUDA-dependent packages |
41+
| `universe-devel` | Builds all universe sources (no CUDA) | Development without GPU |
42+
| `universe-devel-cuda` | Builds all universe sources with CUDA | Development with GPU |
43+
| `universe-runtime-dependencies` | Runtime ansible roles + rosdep exec deps | Foundation for final runtime images |
44+
| `universe` | Runtime image with compiled autoware (no CUDA) | Deployment without GPU |
45+
| `universe-cuda` | Runtime image with compiled autoware + CUDA runtime libs | Deployment with GPU |
46+
47+
## Build locally
48+
49+
From the repository root. Targets beyond `base` require source repositories under `src/`:
50+
51+
```bash
52+
# Clone source repositories (needed for core and universe targets)
53+
vcs import src < repositories/autoware.repos
54+
55+
# Build all default targets (universe + universe-cuda)
56+
docker buildx bake -f docker-new/docker-bake.hcl
57+
58+
# Build a specific target (dependencies are resolved automatically)
59+
docker buildx bake -f docker-new/docker-bake.hcl base
60+
docker buildx bake -f docker-new/docker-bake.hcl core-devel
61+
docker buildx bake -f docker-new/docker-bake.hcl universe
62+
docker buildx bake -f docker-new/docker-bake.hcl universe-cuda
63+
64+
# Build for humble
65+
ROS_DISTRO=humble docker buildx bake -f docker-new/docker-bake.hcl base
66+
```
67+
68+
## Usage
69+
70+
```bash
71+
xhost +local:docker
72+
73+
docker run --rm -it \
74+
--net host \
75+
--privileged \
76+
--gpus all \
77+
-e DISPLAY=$DISPLAY \
78+
-e NVIDIA_DRIVER_CAPABILITIES=all \
79+
-e NVIDIA_VISIBLE_DEVICES=all \
80+
-e HOST_UID=$(id -u) \
81+
-e HOST_GID=$(id -g) \
82+
-e QT_X11_NO_MITSHM=1 \
83+
-v /tmp/.X11-unix:/tmp/.X11-unix:rw \
84+
-v $HOME/autoware_map:/home/aw/autoware_map \
85+
-v $HOME/autoware_data:/home/aw/autoware_data \
86+
-v $HOME/autoware:/home/aw/autoware \
87+
-w /home/aw/autoware \
88+
--runtime=nvidia \
89+
autoware:universe-cuda-jazzy \
90+
bash -c "source /opt/autoware/setup.bash && exec bash"
91+
```
92+
93+
| Flag | Why |
94+
| ----------------------------------- | ---------------------------------------------------------------------------------------------------- |
95+
| `--rm` | Remove container on exit to avoid accumulating stopped containers |
96+
| `-it` | Interactive terminal (stdin + TTY) |
97+
| `--net host` | Share host network stack so ROS 2 nodes can discover each other |
98+
| `--privileged` | Access to host devices (sensors, CAN bus, etc.) |
99+
| `--gpus all` | Expose all GPUs to the container |
100+
| `-e DISPLAY` | Forward X11 display for GUI applications (rviz2, rqt) |
101+
| `-e NVIDIA_DRIVER_CAPABILITIES=all` | Enable all NVIDIA driver features (compute, graphics, video) |
102+
| `-e NVIDIA_VISIBLE_DEVICES=all` | Make all GPUs visible inside the container |
103+
| `-e HOST_UID/HOST_GID` | Entrypoint remaps the `aw` user to match host UID/GID, avoiding permission issues on mounted volumes |
104+
| `-e QT_X11_NO_MITSHM` | Disable MIT-SHM for Qt apps (shared memory doesn't work across container boundary) |
105+
| `-v /tmp/.X11-unix` | Mount X11 socket for GUI forwarding |
106+
| `-v autoware_map` | Mount map data from host |
107+
| `-v autoware_data` | Mount perception model data from host |
108+
| `-v autoware` | Mount source code for development |
109+
| `-w /home/aw/autoware` | Set working directory to the mounted source |
110+
| `--runtime=nvidia` | Use NVIDIA container runtime for GPU support |
111+
112+
Or run without volume mounting:
113+
114+
```bash
115+
docker run --rm -it \
116+
--net host \
117+
autoware:core-jazzy
118+
```
119+
120+
The default CycloneDDS config uses the `lo` interface (localhost only). To override it, mount your own config:
121+
122+
```bash
123+
docker run --rm -it \
124+
--net host \
125+
-v /path/to/your/cyclonedds.xml:/home/aw/cyclonedds.xml \
126+
autoware:universe-cuda-jazzy
127+
```

docker-new/base.Dockerfile

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
# check=skip=InvalidDefaultArgInFrom
2+
ARG ROS_DISTRO
3+
4+
FROM ros:${ROS_DISTRO}-ros-base AS base
5+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
6+
7+
ARG ROS_DISTRO
8+
ARG USERNAME=aw
9+
10+
RUN rm -f /etc/apt/apt.conf.d/docker-clean && \
11+
echo 'Binary::apt::APT::Keep-Downloaded-Packages "true";' > /etc/apt/apt.conf.d/keep-cache
12+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
13+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
14+
apt-get update && \
15+
apt-get install -y --no-install-recommends \
16+
sudo \
17+
pipx \
18+
bash-completion \
19+
gosu
20+
21+
# Remove default ubuntu user (present since 24.04, occupies UID 1000)
22+
RUN userdel -r ubuntu 2>/dev/null || true && \
23+
useradd -m -s /bin/bash -U ${USERNAME} && \
24+
echo "${USERNAME} ALL=(ALL) NOPASSWD:ALL" >/etc/sudoers.d/90-user-nopasswd && \
25+
chmod 0440 /etc/sudoers.d/90-user-nopasswd && \
26+
sed -i 's/^#force_color_prompt=yes/force_color_prompt=yes/' /home/${USERNAME}/.bashrc
27+
28+
USER ${USERNAME}
29+
WORKDIR /home/${USERNAME}
30+
31+
# Make pipx shims visible during build steps and at runtime
32+
ENV PATH="/home/${USERNAME}/.local/bin:${PATH}"
33+
34+
# Ansible via pipx
35+
RUN --mount=type=cache,target=/home/aw/.cache/pip,uid=1000,gid=1000 \
36+
--mount=type=cache,target=/home/aw/.cache/pipx,uid=1000,gid=1000 \
37+
python3 -m pipx ensurepath && \
38+
pipx install --include-deps --force "ansible==10.*"
39+
40+
# Make ansible collections visible to all users (root runs ansible in downstream stages)
41+
ENV ANSIBLE_COLLECTIONS_PATH="/home/${USERNAME}/.ansible/collections"
42+
43+
COPY --chown=${USERNAME}:${USERNAME} ansible-galaxy-requirements.yaml /tmp/ansible/
44+
COPY --chown=${USERNAME}:${USERNAME} ansible/ /tmp/ansible/ansible/
45+
46+
WORKDIR /tmp/ansible
47+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
48+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
49+
ansible-galaxy collection install -f -r ansible-galaxy-requirements.yaml && \
50+
ansible-playbook autoware.dev_env.autoware_requirements \
51+
--tags rmw \
52+
-e rosdistro=${ROS_DISTRO}
53+
54+
COPY docker-new/files/cyclonedds.xml /home/${USERNAME}/cyclonedds.xml
55+
ENV CYCLONEDDS_URI=file:///home/${USERNAME}/cyclonedds.xml
56+
57+
WORKDIR /home/${USERNAME}
58+
RUN rm -rf /tmp/ansible
59+
60+
# Entrypoint runs as root so it can adjust UID/GID, then drops to user
61+
USER root
62+
COPY --chmod=755 docker-new/docker-entrypoint.sh /docker-entrypoint.sh
63+
64+
ENV ROS_DISTRO=${ROS_DISTRO}
65+
ENV USERNAME=${USERNAME}
66+
67+
ENTRYPOINT ["/docker-entrypoint.sh"]
68+
CMD ["/bin/bash"]

docker-new/core.Dockerfile

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# syntax=docker/dockerfile:1
2+
# check=skip=InvalidDefaultArgInFrom
3+
ARG BASE_IMAGE
4+
5+
FROM ${BASE_IMAGE} AS core-dependencies
6+
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
7+
8+
USER ${USERNAME}
9+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
10+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
11+
ansible-playbook autoware.dev_env.autoware_requirements \
12+
--tags core \
13+
--skip-tags base \
14+
-e "rosdistro=${ROS_DISTRO}"
15+
USER root
16+
17+
ENV CC="/usr/lib/ccache/gcc"
18+
ENV CXX="/usr/lib/ccache/g++"
19+
ENV CCACHE_DIR="/home/aw/.ccache"
20+
21+
COPY --parents --chown=${USERNAME}:${USERNAME} src/core/**/package.xml /tmp/autoware/
22+
RUN rm -rf /tmp/autoware/src/core/autoware_core /tmp/autoware/src/core/autoware_rviz_plugins
23+
24+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
25+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
26+
apt-get update && \
27+
. "/opt/ros/${ROS_DISTRO}/setup.sh" && \
28+
rosdep install -y --from-paths /tmp/autoware/src/core \
29+
--ignore-src \
30+
--rosdistro "${ROS_DISTRO}" \
31+
--dependency-types=build \
32+
--dependency-types=build_export \
33+
--dependency-types=buildtool \
34+
--dependency-types=buildtool_export \
35+
--dependency-types=test
36+
37+
COPY --chown=${USERNAME}:${USERNAME} src/core/ /tmp/autoware/src/core/
38+
RUN rm -rf /tmp/autoware/src/core/autoware_core /tmp/autoware/src/core/autoware_rviz_plugins
39+
40+
RUN --mount=type=cache,target=/home/aw/.ccache,uid=1000,gid=1000 \
41+
. "/opt/ros/${ROS_DISTRO}/setup.sh" && \
42+
colcon build \
43+
--base-paths /tmp/autoware/src/core \
44+
--install-base /opt/autoware \
45+
--cmake-args -DCMAKE_BUILD_TYPE=Release && \
46+
rm -rf /tmp/autoware
47+
48+
FROM core-dependencies AS core-devel
49+
50+
COPY --parents --chown=${USERNAME}:${USERNAME} \
51+
src/core/autoware_core/**/package.xml \
52+
src/core/autoware_rviz_plugins/**/package.xml \
53+
/tmp/autoware/
54+
55+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
56+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
57+
apt-get update && \
58+
. "/opt/ros/${ROS_DISTRO}/setup.sh" && \
59+
. /opt/autoware/setup.sh && \
60+
rosdep install -y --from-paths /tmp/autoware/src/core \
61+
--ignore-src \
62+
--rosdistro "${ROS_DISTRO}" \
63+
--dependency-types=build \
64+
--dependency-types=build_export \
65+
--dependency-types=buildtool \
66+
--dependency-types=buildtool_export \
67+
--dependency-types=test
68+
69+
COPY --chown=${USERNAME}:${USERNAME} src/core/autoware_core /tmp/autoware/src/core/autoware_core
70+
COPY --chown=${USERNAME}:${USERNAME} src/core/autoware_rviz_plugins /tmp/autoware/src/core/autoware_rviz_plugins
71+
72+
RUN --mount=type=cache,target=/home/aw/.ccache,uid=1000,gid=1000 \
73+
. "/opt/ros/${ROS_DISTRO}/setup.sh" && \
74+
. /opt/autoware/setup.sh && \
75+
colcon build \
76+
--base-paths /tmp/autoware/src/core/autoware_core \
77+
--install-base /opt/autoware \
78+
--cmake-args -DCMAKE_BUILD_TYPE=Release && \
79+
rm -rf /tmp/autoware
80+
81+
FROM ${BASE_IMAGE} AS core
82+
ENV AUTOWARE_RUNTIME=1
83+
84+
COPY --from=core-devel /opt/autoware /opt/autoware
85+
RUN find /opt/autoware -name '*.so' -exec strip --strip-unneeded {} +
86+
87+
COPY --parents src/core/**/package.xml /tmp/
88+
89+
RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
90+
--mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
91+
apt-get update && \
92+
. "/opt/ros/${ROS_DISTRO}/setup.sh" && \
93+
rosdep install -y --from-paths /tmp/src/core \
94+
--dependency-types=exec \
95+
--ignore-src \
96+
--rosdistro "${ROS_DISTRO}" && \
97+
rm -rf /tmp/src

0 commit comments

Comments
 (0)