Keep build-only dependencies out of the main image (#356) - #2
Draft
dv-picknik wants to merge 1 commit into
Draft
Conversation
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
[written by AI]
Addresses space-ros#356. Stacked on PickNikRobotics/space-ros#388 (
add-docker) — review that first; this PR's base isadd-docker, so the diff shown here is only the size work.The Earthly version of this work is space-ros#357, which space-ros#388 conflicts with by deleting the
Earthfile. This is that work ported to theDockerfile, minus the parts that measurement or review killed.Problem
Everything the main image needs to compile Space ROS also ships in it: GCC, CMake, binutils,
ros-dev-tools(which drags in colcon, rosdep, vcstool, bloom), plus the headers and CMake config files of the built install. None of it is used to run Space ROS.Approach
pre-installation-buildstage holdingbison build-essential cmake git wget.setup,ikos-install, androsdepderive from it;prepare-image— the final image's parent — stays on plainpre-installationand no longer installsros-dev-tools. The dev image reinstallsros-dev-toolsin theimagestage as before.buildstrips the install for non-dev variants:include/,share/**/cmake/,*.cmake,CMakeLists.txt,*.pyc. Done inbuild, beforeimagecopies${SPACEROS_DIR}— a delete in a later layer only writes a whiteout over the parent layer and reclaims nothing.clang-formatadded toexcluded-deps.txt, so main skips it and dev still gets it.prepare-imagerunsrosdeps.shwithAPT::Install-Recommends "false"and cleans/var/lib/apt/lists/*in that same layer. Without the first, droppingros-dev-toolsnewly pulls 23 MB of Recommends (manpages-dev, DejaVu fonts, libgd/libjpeg/libtiff/X11) behindlibc6-dev; the baseline dodged that only becausebuild-essentialhad already installedlibc6-devunder--no-install-recommends. Without the second, therm -rfalready in theimagestage masks those bytes instead of reclaiming them.docs/USAGE.md: one note that:latestcarries no compiler, CMake, or colcon and no headers, and that building against Space ROS means:dev.Two latent bugs this surfaced
Both are pre-existing and only fixed here because dropping
ros-dev-toolsexposed them. Both were found by running the image, not by reading it.python3-yamlreached the image only throughros-dev-tools. Replace Earthly with Docker Buildx for Space ROS builds (#107) space-ros/space-ros#388 converted the Earthfile'spip3 install pyyaml lark packaging catkin_pkg psutilto apt packages but droppedpyyaml; it kept working by accident. It is not a resolved rosdep at all — onlylibyaml-devis. Without itimport rclpyraisesModuleNotFoundError: No module named 'yaml'and the wholeros2CLI is dead. Now requested explicitly inprepare-image.python3-argcompleteis a resolved rosdep thatexcluded-deps.txtfiltered out, so it too arrived only viaros-dev-tools. It is a realros2cliruntime dependency: without itros2cliswallows the extension'sImportErrorand silently drops everyros2 topicverb (bw delay echo find hz info list pub type) andros2 service echo. No error, the commands just cease to exist — andros2 pkg liststill returns all 212 packages, so a smoke test that only checks package discovery passes green on a broken image. Removed fromexcluded-deps.txt.Verification
Both variants built locally and compared against
add-dockerat 8c27019.add-dockerdocker image inspect --format '{{.Size}}')ros2 pkg list−254.3 MB, −55%. 127 apt packages gone (gcc/g++/binutils/cmake/make, git/wget/subversion/mercurial/bzr, all of colcon, rosdep, vcstool, bloom, clang-format, python3-pytest); zero packages added. Of the shrink,
/opt/ros/spacerosdrops 168 MB → 128 MB,include/alone accounting for 40 MB.Parity against the baseline image, not just liveness:
ros2 {topic,node,param,service,action,interface,lifecycle,pkg} --helpexpose byte-identical verb sets.ros2 topic pub+ros2 topic echo --onceround-trips astd_msgs/msg/String;rclpy.create_nodeworks.import rclpy, yaml, lark, catkin_pkg, psutil, netifaces, numpy, packaging, argcompleteall succeed.gcc/cmake/colcon/git/vcs/clang-formatall present,/opt/ikos/bin/ikospresent,include/and 154*Config.cmakefiles retained. Its baseline was not built, so no dev-image delta is claimed.pre-commit(includinghadolint) passes.docker buildx build --call checkis clean formain/dev×image/export-build-test/export-repos.Deliberately not done
rm -rf /usr/include, from Reduce core image size by a further 50% space-ros/space-ros#357. @ivanperez-keera objected there to removing files a package owns, leaving dpkg's view of the filesystem inconsistent. Agreed; the-devpackages would have to go instead, which is the follow-up below.localepurgeand dpkgpath-exclude, from Reduce core image size by a further 50% space-ros/space-ros#357. Measured, they buy nothing:ubuntu:noblealready ships/etc/dpkg/dpkg.cfg.d/excludes, which drops man pages and.motranslations as packages unpack. A/B build ofubuntu:noble+locales+git wget curl cmake build-essential python3-pipgives 569,976 KB withoutlocalepurgeand 570,496 KB with — 520 KB larger, the cost of the package itself — with/usr/share/localeat 612 KB either way. The Earthfile builds from the same base, so this holds for Reduce core image size by a further 50% space-ros/space-ros#357 too.Follow-ups
rosdep --dependency-types exec.rosdeps.shcurrently installs build dependencies into the runtime image. Measured against this branch'srosdepstage: 45 resolved deps → 35. Five are not already inexcluded-deps.txt—libgtest-dev libssl-dev pkg-config python3-dev python3-jsonschema— andpython3-devis what pullslibc6-dev+libpython3.12-dev. That chain is 68 MB installed, though other retained-devpackages also depend onlibc6-dev, so the realized saving is lower. This is the central idea of a parallel Earthfile-based attempt at Reduce image size by removing build dependencies unused at runtime space-ros/space-ros#356 (Reduce runtime image build dependencies (#356). sylvesterkaczmarek/space-ros#1) and is worth taking.ros2 topic listand a Python import check, notros2 pkg list— per thepython3-argcompletebug above, package discovery survives breakage that removes half the CLI.rosdeps.sh's header line is dead code. The generator writesapt-get install -y \followed by rosdep's#[apt] Installation commands:comment, so the continuation is swallowed and the real work is oneapt-get install -y <pkg>per line, emitted verbatim by rosdep. That is why this PR sets the apt config instead of adding a flag there. Worth straightening out separately, in Replace Earthly with Docker Buildx for Space ROS builds (#107) space-ros/space-ros#388's code.