Bazel install_pkgs向distroless python3-debian11镜像装包失败
问题根因
你判断的完全正确,直接把distroless python3-debian11作为install_pkgs的基础镜像时,镜像里没有dpkg、apt、bash这些安装流程必需的工具,就是包安装失败的直接原因。
另外还有两个容易忽略的问题:
- distroless镜像默认用uid 65532的非root用户启动,就算镜像里带了dpkg,也没有权限做系统级的包安装
- 你用的:debug标签版本,只额外加了busybox提供的基础sh和简单工具,依然没有包管理器、bash这类组件。
为什么Bazel构建没报错
你用的v0.25.0版本io_bazel_rules_docker,install_pkgs规则本身有两个设计问题,导致安装失败不会触发构建报错:
- 错误状态传递有bug:规则启动临时容器跑安装脚本的时候,没有正确把容器内命令的退出状态传回Bazel,遇到
command not found这类127退出码的错误时,会直接忽略,不会判定为构建失败 - 没有前置依赖检查:规则不会提前检查目标基础镜像里有没有安装脚本依赖的bash、dpkg、apt这些工具,只要镜像能正常启动,就默认安装步骤跑完了,直接导出容器文件系统做新镜像。实际上这时候安装脚本根本没执行完,你下载的deb包压根没被解压到镜像文件系统里,运行的时候自然找不到文件。
修复方案
别直接在distroless镜像上跑deb安装,distroless的设计本来就不带包管理器和多余工具,按多阶段构建的思路改BUILD文件逻辑就行:
- 保留基于debian11-slim的install_pkgs步骤,在标准Debian镜像上把所有需要的deb包装完,生成带依赖文件的中间镜像层
- 再写container_image规则,最终基础镜像用distroless python3-debian11,把前一步在debian-slim中间镜像里装好的依赖文件(主要是/usr/lib下的so库、/usr/share下的资源文件)直接复制到distroless镜像的对应路径就行,全程不用在distroless里跑任何安装命令。
核心修改后的BUILD示例:
# 第一步:在标准debian11-slim上下载、安装所有需要的deb包 download_pkgs( name = "ros2_humble_pkgs", image_tar = "@debian11-slim//image", packages = [ "libpython3.9", "libtinyxml2-8", "libfmt7", ], ) install_pkgs( name = "ros2_pkgs_intermediate", image_tar = "@debian11-slim//image", installables_tar = ":ros2_humble_pkgs.tar", installation_cleanup_commands = "rm -rf /var/lib/apt/lists/*", output_image_name = "debian11-slim/ros2-intermediate", ) # 第二步:把中间镜像里装好的依赖文件拷贝到distroless最终镜像 container_image( name = "ros2_pkgs_image", base = "@python3-debian11//image", tars = [":ros2_pkgs_intermediate.tar"], # 按需排除debian-slim里带的冗余文件(比如apt、dpkg相关的无用文件),配置需要的软链接 symlinks = { "/usr/lib/x86_64-linux-gnu/libfmt.so.7": "/usr/lib/x86_64-linux-gnu/libfmt.so.7.1.3", }, )
调试验证命令
# 构建镜像 bazel build //ros2:ros2_pkgs_image # 把构建好的镜像加载到本地docker docker load -i bazel-bin/ros2/ros2_pkgs_image.tar # 启动容器进shell检查文件 docker run -it --rm --entrypoint sh distroless/ros2-debian11:latest ls /usr/lib/x86_64-linux-gnu/libfmt.so.7.1.3
内容的提问来源于stack exchange,提问作者BhanuKiran
相关产品推荐
相关产品推荐

