From f97df2273b2add17311054d24895c7e1ba7b5e78 Mon Sep 17 00:00:00 2001 From: Matt Spencer Date: Thu, 16 Jul 2026 07:12:48 +0000 Subject: [PATCH] Create better caching of rosdep dependencies For both devcontainer and deployable container. Also add ability to use docker from inside the devcontainer. --- .devcontainer/jazzy/Dockerfile.jazzy | 27 ++++---- .devcontainer/jazzy/devcontainer-lock.json | 9 +++ .devcontainer/jazzy/devcontainer.json | 6 ++ Dockerfile | 15 +++++ rosdep-packages.txt | 73 ++++++++++++++++++++++ scripts/freeze-rosdep.sh | 7 +++ 6 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 .devcontainer/jazzy/devcontainer-lock.json create mode 100644 rosdep-packages.txt create mode 100755 scripts/freeze-rosdep.sh diff --git a/.devcontainer/jazzy/Dockerfile.jazzy b/.devcontainer/jazzy/Dockerfile.jazzy index a8c5458..6a7827e 100644 --- a/.devcontainer/jazzy/Dockerfile.jazzy +++ b/.devcontainer/jazzy/Dockerfile.jazzy @@ -2,6 +2,7 @@ FROM osrf/ros:jazzy-desktop-full ARG USERNAME=USERNAME ARG USER_UID=1000 ARG USER_GID=$USER_UID +ARG TARGETARCH # Delete user if it exists in container (e.g Ubuntu Noble: ubuntu) RUN if id -u $USER_UID ; then userdel `id -un $USER_UID` ; fi @@ -47,13 +48,18 @@ RUN apt-get update \ python3-vcstool \ && rm -rf /var/lib/apt/lists/* -# Optional: pre-install apt dependencies resolved from rosdep on a previous run. -COPY .devcontainer/jazzy/ /tmp/devcontainer-jazzy/ - -RUN apt-get update \ - && if [ -f /tmp/devcontainer-jazzy/rosdep-apt-packages.txt ]; then \ - grep -Ev '^\s*($|#)' /tmp/devcontainer-jazzy/rosdep-apt-packages.txt | xargs -r apt-get install -y --no-install-recommends; \ - fi \ +# system deps from frozen rosdep manifest — no rosdep at build or startup +# NOTE: There should be a check in your CI that this file is up to date. +# Something like: +# ./scripts/freeze-rosdep.sh && git diff --exit-code rosdep-packages.txt +COPY rosdep-packages.txt /tmp/rosdep-packages.txt +# The --mount=type=cache option caches the apt packages with buildkit +# The id-apt-cache-${TARGETARCH} option allows for separate caches for different architectures +# this enables parallel builds for different architectures without cache conflicts +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt-cache-${TARGETARCH} \ + rm -f /etc/apt/apt.conf.d/docker-clean \ + && apt-get update \ + && xargs -r -a /tmp/rosdep-packages.txt apt-get install -y --no-install-recommends \ && rm -rf /var/lib/apt/lists/* RUN apt-get update \ @@ -61,13 +67,6 @@ RUN apt-get update \ ros-${ROS_DISTRO}-rmw-cyclonedds-cpp \ && rm -rf /var/lib/apt/lists/* -# ROS 2 ament build tools -# RUN apt-get install -y \ -# ros-${ROS_DISTRO}-ament-cmake \ -# ros-${ROS_DISTRO}-ament-cmake-auto \ -# ros-${ROS_DISTRO}-ament-python \ -# ros-${ROS_DISTRO}-ament-lint-auto \ -# ros-${ROS_DISTRO}-ament-lint-common ENV SHELL=/bin/bash diff --git a/.devcontainer/jazzy/devcontainer-lock.json b/.devcontainer/jazzy/devcontainer-lock.json new file mode 100644 index 0000000..f87566e --- /dev/null +++ b/.devcontainer/jazzy/devcontainer-lock.json @@ -0,0 +1,9 @@ +{ + "features": { + "ghcr.io/devcontainers/features/docker-from-docker:1": { + "version": "1.10.0", + "resolved": "ghcr.io/devcontainers/features/docker-from-docker@sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e", + "integrity": "sha256:c2c2cf829505ead8e4892c88c31b6594ae94a2bbb209e16e1fac456c1a3a624e" + } + } +} diff --git a/.devcontainer/jazzy/devcontainer.json b/.devcontainer/jazzy/devcontainer.json index e99b210..8aa1650 100644 --- a/.devcontainer/jazzy/devcontainer.json +++ b/.devcontainer/jazzy/devcontainer.json @@ -10,6 +10,12 @@ } }, "workspaceFolder": "/workspaces/agv_pro_ros2", + "features": { + "ghcr.io/devcontainers/features/docker-from-docker:1": { + "version": "latest", + "moby": true + } + }, "customizations": { "vscode": { "extensions": [ diff --git a/Dockerfile b/Dockerfile index 70fce06..be43d19 100644 --- a/Dockerfile +++ b/Dockerfile @@ -25,7 +25,22 @@ RUN cd ./src/upstream/livox_ros_driver2 && \ # Apply patches to upstream # RUN ./patches/apply_patches.sh +# system deps from frozen rosdep manifest — no rosdep at build or startup +# NOTE: There should be a check in your CI that this file is up to date. +# Something like: +# ./scripts/freeze-rosdep.sh && git diff --exit-code rosdep-packages.txt +COPY rosdep-packages.txt /tmp/rosdep-packages.txt +# The --mount=type=cache option caches the apt packages with buildkit +# The id-apt-cache-${TARGETARCH} option allows for separate caches for different architectures +# this enables parallel builds for different architectures without cache conflicts +RUN --mount=type=cache,target=/var/cache/apt,sharing=locked,id=apt-cache-${TARGETARCH} \ + rm -f /etc/apt/apt.conf.d/docker-clean \ + && apt-get update \ + && xargs -r -a /tmp/rosdep-packages.txt apt-get install -y --no-install-recommends \ + && rm -rf /var/lib/apt/lists/* + # Install dependencies with rosdep +# This will catch anything that wasn't installed via .deb's from the frozen rosdep manifest. RUN apt-get update && \ rosdep update && \ rosdep install --from-paths src --ignore-src -r -y && \ diff --git a/rosdep-packages.txt b/rosdep-packages.txt new file mode 100644 index 0000000..5c967a4 --- /dev/null +++ b/rosdep-packages.txt @@ -0,0 +1,73 @@ +git +libapr1-dev libaprutil1-dev +libboost-all-dev +libpcap0.8-dev +libpcl-apps1.14 libpcl-common1.14 libpcl-features1.14 libpcl-filters1.14 libpcl-io1.14 libpcl-kdtree1.14 libpcl-keypoints1.14 libpcl-ml1.14 libpcl-octree1.14 libpcl-outofcore1.14 libpcl-people1.14 libpcl-recognition1.14 libpcl-registration1.14 libpcl-sample-consensus1.14 libpcl-search1.14 libpcl-segmentation1.14 libpcl-stereo1.14 libpcl-surface1.14 libpcl-tracking1.14 libpcl-visualization1.14 +libpcl-dev +libqt5core5t64 +libqt5gui5t64 +libqt5opengl5t64 +libqt5widgets5t64 +python3-pytest +qtbase5-dev +ros-jazzy-ament-cmake +ros-jazzy-ament-cmake-auto +ros-jazzy-ament-cmake-black +ros-jazzy-ament-cmake-clang-format +ros-jazzy-ament-cmake-clang-tidy +ros-jazzy-ament-cmake-copyright +ros-jazzy-ament-cmake-xmllint +ros-jazzy-ament-copyright +ros-jazzy-ament-flake8 +ros-jazzy-ament-index-cpp +ros-jazzy-ament-lint-auto +ros-jazzy-ament-lint-common +ros-jazzy-ament-pep257 +ros-jazzy-asio-cmake-module +ros-jazzy-builtin-interfaces +ros-jazzy-cartographer-ros +ros-jazzy-common-interfaces +ros-jazzy-controller-manager +ros-jazzy-diff-drive-controller +ros-jazzy-geometry-msgs +ros-jazzy-io-context +ros-jazzy-joint-state-broadcaster +ros-jazzy-joint-state-publisher +ros-jazzy-message-filters +ros-jazzy-nav-msgs +ros-jazzy-nav2-bringup +ros-jazzy-nav2-simple-commander +ros-jazzy-orbbec-camera +ros-jazzy-pcl-conversions +ros-jazzy-pcl-ros +ros-jazzy-pluginlib +ros-jazzy-rcl-interfaces +ros-jazzy-rclcpp +ros-jazzy-rclcpp-components +ros-jazzy-rclpy +ros-jazzy-rcutils +ros-jazzy-resource-retriever +ros-jazzy-robot-state-publisher +ros-jazzy-ros2-control +ros-jazzy-rosbag2 +ros-jazzy-rosidl-default-generators +ros-jazzy-rosidl-default-runtime +ros-jazzy-rtabmap-demos +ros-jazzy-rtabmap-slam +ros-jazzy-rtabmap-sync +ros-jazzy-rtabmap-util +ros-jazzy-rtabmap-viz +ros-jazzy-rviz-common +ros-jazzy-rviz-default-plugins +ros-jazzy-rviz-ogre-vendor +ros-jazzy-rviz-rendering +ros-jazzy-rviz2 +ros-jazzy-sensor-msgs +ros-jazzy-serial-driver +ros-jazzy-std-msgs +ros-jazzy-teleop-twist-keyboard +ros-jazzy-tf2 +ros-jazzy-tf2-geometry-msgs +ros-jazzy-tf2-ros +ros-jazzy-visualization-msgs +ros-jazzy-xacro diff --git a/scripts/freeze-rosdep.sh b/scripts/freeze-rosdep.sh new file mode 100755 index 0000000..620f475 --- /dev/null +++ b/scripts/freeze-rosdep.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +set -euo pipefail +ROS_DISTRO="${ROS_DISTRO:-jazzy}" +rosdep update --rosdistro "$ROS_DISTRO" >/dev/null 2>&1 || true +rosdep keys --from-paths src --ignore-src --rosdistro "$ROS_DISTRO" 2>/dev/null \ + | xargs rosdep resolve --rosdistro "$ROS_DISTRO" 2>/dev/null \ + | awk '/^#apt/{a=1;next} /^#/{a=0} a' | sort -u > rosdep-packages.txt \ No newline at end of file