From 27a1229220dba08bf4bb3c134f648a3dfa12df84 Mon Sep 17 00:00:00 2001 From: Nick Sieger Date: Mon, 9 Nov 2026 15:43:20 -0600 Subject: [PATCH 1/3] feat(offload): add docker-offload-plugin deb/rpm packaging Add Linux packaging recipes for the docker-offload CLI plugin (pkg/offload) and wire the package into docker-bake.hcl: PKGS_BASE, PKG_PLATFORMS_BASE, PKG_DISTROS, a VERSION/OFFLOAD_BIN variable pair, and a _pkg-offload target. Packages prebuilt, signed docker-offload-linux- binaries rather than building from source, same deliberate exception as sbx. No PKG_REPO/PKG_REF defaults, since the Dockerfile never consumes those args (no git clone, no metadata stage). Signed-off-by: Nick Sieger --- docker-bake.hcl | 32 +++++- pkg/offload/Dockerfile | 104 ++++++++++++++++++++ pkg/offload/deb/control | 15 +++ pkg/offload/deb/copyright | 8 ++ pkg/offload/deb/rules | 22 +++++ pkg/offload/deb/source/format | 1 + pkg/offload/rpm/docker-offload-plugin.spec | 38 ++++++++ pkg/offload/scripts/pkg-deb-build.sh | 85 ++++++++++++++++ pkg/offload/scripts/pkg-rpm-build.sh | 90 +++++++++++++++++ pkg/offload/verify.Dockerfile | 107 +++++++++++++++++++++ 10 files changed, 500 insertions(+), 2 deletions(-) create mode 100644 pkg/offload/Dockerfile create mode 100644 pkg/offload/deb/control create mode 100644 pkg/offload/deb/copyright create mode 100755 pkg/offload/deb/rules create mode 100644 pkg/offload/deb/source/format create mode 100644 pkg/offload/rpm/docker-offload-plugin.spec create mode 100755 pkg/offload/scripts/pkg-deb-build.sh create mode 100755 pkg/offload/scripts/pkg-rpm-build.sh create mode 100644 pkg/offload/verify.Dockerfile diff --git a/docker-bake.hcl b/docker-bake.hcl index b9e77488..7fa6af81 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -55,7 +55,8 @@ variable "PKGS_BASE" { "docker-cli", "docker-engine", "model", - "agent" + "agent", + "offload" ] } @@ -91,6 +92,8 @@ variable "PKG_PLATFORMS_BASE" { model = ["darwin/amd64", "darwin/arm64", "linux/amd64", "linux/arm64", "linux/arm/v7", "windows/amd64", "windows/arm64"] # https://github.com/docker/docker-agent/blob/5b9feaabe743a5ad577f2247ed55d5dcb2678e8b/Taskfile.yml#L79 agent = ["darwin/amd64", "darwin/arm64", "linux/amd64", "linux/arm64", "windows/amd64", "windows/arm64"] + # Packages only the prebuilt linux binaries; darwin and windows ship through the source repo. + offload = ["linux/amd64", "linux/arm64"] } } @@ -102,7 +105,8 @@ variable "PKG_PLATFORMS_EXTRA" { variable "PKG_DISTROS" { description = "Package-specific distro mapping. Packages omitted here build for all DISTROS." default = { - docker = ["static"] + docker = ["static"] + offload = ["ubuntu2404", "ubuntu2604", "rockylinux8"] } } @@ -211,6 +215,16 @@ variable "NIGHTLY_BUILD" { default = null } +variable "VERSION" { + description = "Release tag of the prebuilt binaries to package, for example v0.7.48. Only used for the offload package, which packages prebuilt binaries instead of building from source." + default = null +} + +variable "OFFLOAD_BIN" { + description = "Directory with the prebuilt docker-offload-linux- binaries. Only used for the offload package." + default = "./offload-bin" +} + variable "GO_IMAGE" { description = "Go image to use for building packages." default = "golang" @@ -693,6 +707,20 @@ target "_pkg-agent" { } } +# Packages prebuilt, signed docker-offload binaries from a private source repo. Does not +# compile, so PKG_REPO/PKG_REF are not consumed here; the caller may still set them for +# provenance. +target "_pkg-offload" { + args = { + PKG_NAME = PKG_NAME != null && PKG_NAME != "" ? PKG_NAME : "docker-offload-plugin" + PKG_DEB_EPOCH = PKG_DEB_EPOCH != null && PKG_DEB_EPOCH != "" ? PKG_DEB_EPOCH : "" + VERSION = VERSION + } + contexts = { + offload-src = OFFLOAD_BIN + } +} + # Returns the list of supported platforms for a given package. function "pkgPlatforms" { params = [pkg] diff --git a/pkg/offload/Dockerfile b/pkg/offload/Dockerfile new file mode 100644 index 00000000..a2e740fd --- /dev/null +++ b/pkg/offload/Dockerfile @@ -0,0 +1,104 @@ +# syntax=docker/dockerfile:1 + +# Copyright 2026 Docker Packaging authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Packages the signed docker-offload binaries from a GitHub release. Nothing is compiled here. + +ARG XX_VERSION="1.9.0" + +ARG DISTRO_NAME="debian12" +ARG DISTRO_TYPE="deb" +ARG DISTRO_RELEASE="debian" +ARG DISTRO_SUITE="bookworm" +ARG DISTRO_ID="12" +ARG DISTRO_IMAGE="debian:bookworm" + +ARG PKG_NAME="docker-offload-plugin" +ARG VERSION + +# scripts from docker/packaging (gen-deb-changelog, rpm-init, rpm-builddep...) +# see pkg target in docker-bake.hcl +FROM scratch AS scripts + +# cross compilation helper +FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx + +# Directory with docker-offload-linux-, overridden by the offload-src named context +# in docker-bake.hcl. +FROM scratch AS offload-src + +# deb +FROM ${DISTRO_IMAGE} AS builder-deb +# A new BUILDER_EPOCH value refreshes the cached apt layers. +ARG BUILDER_EPOCH +COPY --from=xx / / +ARG DISTRO_NAME +RUN apt-get update && apt-get install -y --no-install-recommends apt-utils bash binutils ca-certificates devscripts equivs +COPY deb /root/package/debian +ARG TARGETPLATFORM +RUN mk-build-deps -t "xx-apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y" -i /root/package/debian/control +WORKDIR /root/package +ARG NIGHTLY_BUILD +ARG VERSION +ARG DISTRO_RELEASE +ARG DISTRO_ID +ARG DISTRO_SUITE +ARG PKG_NAME +ARG PKG_PACKAGER +ARG PKG_DEB_BUILDFLAGS +ARG PKG_DEB_REVISION +ARG PKG_DEB_EPOCH +ARG SOURCE_DATE_EPOCH +RUN --mount=type=bind,source=scripts/pkg-deb-build.sh,target=/usr/local/bin/pkg-deb-build \ + --mount=type=bind,from=scripts,source=gen-deb-changelog.sh,target=/usr/local/bin/gen-deb-changelog \ + --mount=type=bind,from=offload-src,target=/opt/offload-bin < +Homepage: https://www.docker.com +Standards-Version: 3.9.6 +Build-Depends: bash, + debhelper-compat (= 12) + +Package: docker-offload-plugin +Priority: optional +Architecture: linux-any +Enhances: docker-ce-cli +Description: Docker Offload plugin for the Docker CLI. +Homepage: https://docs.docker.com/offload/ diff --git a/pkg/offload/deb/copyright b/pkg/offload/deb/copyright new file mode 100644 index 00000000..d723d73b --- /dev/null +++ b/pkg/offload/deb/copyright @@ -0,0 +1,8 @@ +Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ +Upstream-Name: docker-offload-plugin +Source: https://docs.docker.com/offload/ + +Files: * +Copyright: Docker, Inc. +License: Proprietary + All rights reserved. diff --git a/pkg/offload/deb/rules b/pkg/offload/deb/rules new file mode 100755 index 00000000..aed4e5be --- /dev/null +++ b/pkg/offload/deb/rules @@ -0,0 +1,22 @@ +#!/usr/bin/make -f + +override_dh_builddeb: + dh_builddeb -- -Zxz + +override_dh_auto_build: + +override_dh_auto_test: + ver="$$(/usr/libexec/docker/cli-plugins/docker-offload docker-cli-plugin-metadata | awk '{ gsub(/[",:]/,"")}; $$1 == "Version" { print $$2 }')"; \ + test "$$ver" = "$(VERSION)" && echo "PASS" || (echo "FAIL: got '$$ver', want '$(VERSION)'" && exit 1) + +# The binary is prebuilt and its signature and attestation cover the exact bytes, so do not +# strip or rewrite it. +override_dh_strip: + +override_dh_dwz: + +override_dh_auto_install: + install -D -p -m 0755 /usr/libexec/docker/cli-plugins/docker-offload debian/docker-offload-plugin/usr/libexec/docker/cli-plugins/docker-offload + +%: + dh $@ diff --git a/pkg/offload/deb/source/format b/pkg/offload/deb/source/format new file mode 100644 index 00000000..d3827e75 --- /dev/null +++ b/pkg/offload/deb/source/format @@ -0,0 +1 @@ +1.0 diff --git a/pkg/offload/rpm/docker-offload-plugin.spec b/pkg/offload/rpm/docker-offload-plugin.spec new file mode 100644 index 00000000..1b922905 --- /dev/null +++ b/pkg/offload/rpm/docker-offload-plugin.spec @@ -0,0 +1,38 @@ +%global debug_package %{nil} +# Keep the ELF notes so the prebuilt binary still matches its attested digest. +%global __brp_strip_comment_note %{nil} + +Name: docker-offload-plugin +Version: %{_version} +Release: %{_release}%{?dist} +Epoch: 0 +Summary: Docker Offload plugin for the Docker CLI +Group: Tools/Docker +License: Proprietary +URL: https://docs.docker.com/offload/ +Vendor: Docker +Packager: Docker + +Enhances: docker-ce-cli + +BuildRequires: bash + +%description +Docker Offload plugin for the Docker CLI. + +%prep + +%build +test -f /usr/local/libexec/docker/cli-plugins/docker-offload + +%check +ver="$(/usr/local/libexec/docker/cli-plugins/docker-offload docker-cli-plugin-metadata | awk '{ gsub(/[",:]/,"")}; $1 == "Version" { print $2 }')" +test "$ver" = "%{_origversion}" && echo "PASS" || { echo "FAIL: got '$ver', want '%{_origversion}'"; exit 1; } + +%install +install -D -p -m 0755 /usr/local/libexec/docker/cli-plugins/docker-offload ${RPM_BUILD_ROOT}%{_libexecdir}/docker/cli-plugins/docker-offload + +%files +%{_libexecdir}/docker/cli-plugins/docker-offload + +%changelog diff --git a/pkg/offload/scripts/pkg-deb-build.sh b/pkg/offload/scripts/pkg-deb-build.sh new file mode 100755 index 00000000..2fca3bed --- /dev/null +++ b/pkg/offload/scripts/pkg-deb-build.sh @@ -0,0 +1,85 @@ +#!/usr/bin/env bash + +# Copyright 2026 Docker Packaging authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +: "${NIGHTLY_BUILD=}" +: "${VERSION=}" + +: "${DISTRO_NAME=}" +: "${DISTRO_RELEASE=}" +: "${DISTRO_ID=}" +: "${DISTRO_SUITE=}" + +: "${PKG_NAME=}" +: "${PKG_PACKAGER=}" +: "${PKG_VENDOR=}" + +: "${PKG_DEB_REVISION=}" +: "${PKG_DEB_EPOCH=}" + +: "${SOURCE_DATE_EPOCH=}" +: "${OUTDIR=/out}" + +set -e + +if [ -z "$VERSION" ]; then + echo >&2 "error: VERSION is required" + exit 1 +fi +if [ -z "$DISTRO_NAME" ]; then + echo >&2 "error: DISTRO_NAME is required" + exit 1 +fi +if [ -z "$OUTDIR" ]; then + echo >&2 "error: OUTDIR is required" + exit 1 +fi + +mkdir -p "$OUTDIR" + +if ! command -v xx-info &> /dev/null; then + echo >&2 "error: xx cross compilation helper is required" + exit 1 +fi + +# Derive deb-compatible package version from VERSION. +# Nightly builds use + so they sort higher than the base release: +# v0.24.1-25-g9cf02a7d -> 0.24.1+25~g9cf02a7d +# Tagged pre-release versions use ~ so they sort lower: +# v0.1.0-beta.1 -> 0.1.0~beta.1 +tilde='~' +pkgVersion="${VERSION#v}" +if [ -n "$NIGHTLY_BUILD" ]; then + pkgVersion="${pkgVersion/-/+}" +fi +pkgVersion="${pkgVersion//-/$tilde}" + +gen-deb-changelog "$VERSION" "$pkgVersion" "$DISTRO_RELEASE" "$DISTRO_ID" "$DISTRO_SUITE" "$PKG_DEB_REVISION" "$PKG_DEB_EPOCH" + +pkgoutput="${OUTDIR}/${DISTRO_RELEASE}/${DISTRO_SUITE}/$(xx-info arch)" +if [ -n "$(xx-info variant)" ]; then + pkgoutput="${pkgoutput}/$(xx-info variant)" +fi +mkdir -p "${pkgoutput}" + +set -x + +# Install the prebuilt plugin. deb/rules packages it from here. +install -D -p -m 0755 "/opt/offload-bin/docker-offload-linux-$(xx-info arch)" \ + /usr/libexec/docker/cli-plugins/docker-offload + +chmod -x debian/control debian/copyright +VERSION=${VERSION} dpkg-buildpackage $PKG_DEB_BUILDFLAGS --host-arch $(xx-info debian-arch) --target-arch $(xx-info debian-arch) +cp /root/docker-* "${pkgoutput}"/ diff --git a/pkg/offload/scripts/pkg-rpm-build.sh b/pkg/offload/scripts/pkg-rpm-build.sh new file mode 100755 index 00000000..ae54fa9b --- /dev/null +++ b/pkg/offload/scripts/pkg-rpm-build.sh @@ -0,0 +1,90 @@ +#!/usr/bin/env bash + +# Copyright 2026 Docker Packaging authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +: "${NIGHTLY_BUILD=}" +: "${VERSION=}" + +: "${DISTRO_NAME=}" +: "${DISTRO_RELEASE=}" +: "${DISTRO_ID=}" +: "${DISTRO_SUITE=}" + +: "${PKG_NAME=}" +: "${PKG_PACKAGER=}" +: "${PKG_VENDOR=}" + +: "${PKG_RPM_RELEASE=}" + +: "${SOURCE_DATE_EPOCH=}" +: "${OUTDIR=/out}" + +set -e + +if [ -z "$VERSION" ]; then + echo >&2 "error: VERSION is required" + exit 1 +fi +if [ -z "$DISTRO_NAME" ]; then + echo >&2 "error: DISTRO_NAME is required" + exit 1 +fi +if [ -z "$OUTDIR" ]; then + echo >&2 "error: OUTDIR is required" + exit 1 +fi + +mkdir -p "$OUTDIR" + +if ! command -v xx-info &> /dev/null; then + echo >&2 "error: xx cross compilation helper is required" + exit 1 +fi + +# Derive rpm-compatible package version from VERSION. +# Nightly builds use + so they sort higher than the base release: +# v0.24.1-25-g9cf02a7d -> 0.24.1+25~g9cf02a7d +# Tagged pre-release versions use ~ so they sort lower: +# v0.1.0-beta.1 -> 0.1.0~beta.1 +tilde='~' +pkgVersion="${VERSION#v}" +if [ -n "$NIGHTLY_BUILD" ]; then + pkgVersion="${pkgVersion/-/+}" +fi +pkgVersion="${pkgVersion//-/$tilde}" + +rpmDefine=( + --define "_version ${pkgVersion}" + --define "_origversion ${VERSION}" + --define "_release ${PKG_RPM_RELEASE:-1}" +) + +pkgoutput="${OUTDIR}/${DISTRO_RELEASE}/${DISTRO_SUITE}/$(xx-info arch)" +if [ -n "$(xx-info variant)" ]; then + pkgoutput="${pkgoutput}/$(xx-info variant)" +fi + +set -x + +# Install the prebuilt plugin. The spec packages it from here. +install -D -p -m 0755 "/opt/offload-bin/docker-offload-linux-$(xx-info arch)" \ + /usr/local/libexec/docker/cli-plugins/docker-offload + +rpmbuild --target $(xx-info rhel-arch) $PKG_RPM_BUILDFLAGS "${rpmDefine[@]}" /root/rpmbuild/SPECS/*.spec +mkdir -p "${pkgoutput}" +cp ./RPMS/*/*.* "${pkgoutput}"/ +if [ "$(ls -A ./SRPMS)" ]; then + cp ./SRPMS/* "${pkgoutput}"/ +fi diff --git a/pkg/offload/verify.Dockerfile b/pkg/offload/verify.Dockerfile new file mode 100644 index 00000000..9379d608 --- /dev/null +++ b/pkg/offload/verify.Dockerfile @@ -0,0 +1,107 @@ +# syntax=docker/dockerfile:1 + +# Copyright 2026 Docker Packaging authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +# Installs the built package on a clean distro image and checks the plugin it installs. + +ARG XX_VERSION="1.9.0" + +ARG DISTRO_TYPE="deb" +ARG DISTRO_IMAGE="debian:bookworm" + +# cross compilation helper +FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx + +FROM scratch AS bin +FROM scratch AS scripts + +FROM ${DISTRO_IMAGE} AS base +# The version the plugin must report, for example v0.7.48. Empty skips the version check. +ARG VERSION="" +ARG PLUGIN=/usr/libexec/docker/cli-plugins/docker-offload + +FROM base AS verify-deb +COPY --from=xx / / +ARG DISTRO_RELEASE +ARG DISTRO_ID +ARG DISTRO_SUITE +ARG TARGETPLATFORM +ARG VERSION +ARG PLUGIN +RUN --mount=from=bin,target=/build <&2 "error: no packages found in $dir" + exit 1 + fi + for package in $(find $dir -type f -name '*.deb'); do + ( + set -x + dpkg-deb --info $package + apt-get update + apt-get install -y --no-install-recommends $package + ) + done + set -x + test -x "$PLUGIN" + "$PLUGIN" docker-cli-plugin-metadata + if [ -n "$VERSION" ]; then + "$PLUGIN" docker-cli-plugin-metadata | grep -F "\"Version\": \"$VERSION\"" + fi +EOT + +FROM base AS verify-rpm +COPY --from=xx / / +ARG DISTRO_NAME +ARG DISTRO_RELEASE +ARG DISTRO_ID +ARG DISTRO_SUITE +RUN --mount=type=bind,from=scripts,source=verify-rpm-init.sh,target=/usr/local/bin/verify-rpm-init \ + verify-rpm-init $DISTRO_NAME +ARG TARGETPLATFORM +ARG VERSION +ARG PLUGIN +RUN --mount=from=bin,target=/build <&2 "error: no packages found in $dir" + exit 1 + fi + for package in $(find $dir -type f -name '*.rpm' ! -name '*.src.rpm'); do + ( + set -x + rpm -qilp $package + dnf install -y $package + ) + done + set -x + test -x "$PLUGIN" + "$PLUGIN" docker-cli-plugin-metadata + if [ -n "$VERSION" ]; then + "$PLUGIN" docker-cli-plugin-metadata | grep -F "\"Version\": \"$VERSION\"" + fi +EOT + +FROM verify-${DISTRO_TYPE} AS verify From 13a327c0107b18dbb9f6d721c7e887a0e8b97d89 Mon Sep 17 00:00:00 2001 From: Nick Sieger Date: Tue, 10 Nov 2026 13:47:42 -0600 Subject: [PATCH 2/3] feat(offload): build docker-offload-plugin from source Compile the plugin in the package build (dh_auto_build, rpm %build) through the ce-release make target of the source tree, instead of packaging prebuilt binaries. - source tree passed in as the src named context, dependencies vendored; no git clone - VERSION (v prefix), COMMIT, BUILD, DATE bake variables passed to the make target - optional build-env file secret via PKG_BUILD_ENV_FILE - GO_VERSION pinned to the release toolchain (1.27.3) - strip overrides kept so the packaged binary matches the release binary - offload excluded from the nightly package list Signed-off-by: Nick Sieger --- .github/workflows/.pkgs.yml | 3 ++ docker-bake.hcl | 36 ++++++++++----- pkg/offload/Dockerfile | 53 ++++++++++++++-------- pkg/offload/deb/control | 3 +- pkg/offload/deb/rules | 13 ++++-- pkg/offload/rpm/docker-offload-plugin.spec | 12 +++-- pkg/offload/scripts/pkg-deb-build.sh | 20 ++++++-- pkg/offload/scripts/pkg-rpm-build.sh | 24 ++++++++-- 8 files changed, 112 insertions(+), 52 deletions(-) diff --git a/.github/workflows/.pkgs.yml b/.github/workflows/.pkgs.yml index 69600d06..f07feac1 100644 --- a/.github/workflows/.pkgs.yml +++ b/.github/workflows/.pkgs.yml @@ -21,6 +21,9 @@ jobs: name: Set pkgs output id: set uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 + env: + # offload builds from a private source tree and is built from its own repo. + DISABLED_PACKAGES: offload with: script: | const fs = require('fs'); diff --git a/docker-bake.hcl b/docker-bake.hcl index 7fa6af81..585cd794 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -92,7 +92,7 @@ variable "PKG_PLATFORMS_BASE" { model = ["darwin/amd64", "darwin/arm64", "linux/amd64", "linux/arm64", "linux/arm/v7", "windows/amd64", "windows/arm64"] # https://github.com/docker/docker-agent/blob/5b9feaabe743a5ad577f2247ed55d5dcb2678e8b/Taskfile.yml#L79 agent = ["darwin/amd64", "darwin/arm64", "linux/amd64", "linux/arm64", "windows/amd64", "windows/arm64"] - # Packages only the prebuilt linux binaries; darwin and windows ship through the source repo. + # Linux packages only; darwin and windows ship through the source repo. offload = ["linux/amd64", "linux/arm64"] } } @@ -216,13 +216,25 @@ variable "NIGHTLY_BUILD" { } variable "VERSION" { - description = "Release tag of the prebuilt binaries to package, for example v0.7.48. Only used for the offload package, which packages prebuilt binaries instead of building from source." + description = "Version to build, with v prefix, for example v0.7.52. Only used for the offload package, whose source tree is passed in as the src named context." + default = null +} +variable "COMMIT" { + description = "Short commit of the source tree. Only used for the offload package." + default = null +} +variable "BUILD" { + description = "Build number of the release build. Only used for the offload package." + default = null +} +variable "DATE" { + description = "Commit date of the release tag (YYYY-MM-DD). Only used for the offload package." default = null } -variable "OFFLOAD_BIN" { - description = "Directory with the prebuilt docker-offload-linux- binaries. Only used for the offload package." - default = "./offload-bin" +variable "PKG_BUILD_ENV_FILE" { + description = "File with build secrets, passed to the package build as the build-env secret. Only read by packages that mount it." + default = null } variable "GO_IMAGE" { @@ -707,17 +719,17 @@ target "_pkg-agent" { } } -# Packages prebuilt, signed docker-offload binaries from a private source repo. Does not -# compile, so PKG_REPO/PKG_REF are not consumed here; the caller may still set them for -# provenance. +# The source repo is private, so there is no PKG_REPO/PKG_REF clone. The caller passes the +# vendored source tree as the src named context, and builds are run from the source repo. target "_pkg-offload" { args = { PKG_NAME = PKG_NAME != null && PKG_NAME != "" ? PKG_NAME : "docker-offload-plugin" + GO_IMAGE_VARIANT = GO_IMAGE_VARIANT != null && GO_IMAGE_VARIANT != "" ? GO_IMAGE_VARIANT : "bookworm" PKG_DEB_EPOCH = PKG_DEB_EPOCH != null && PKG_DEB_EPOCH != "" ? PKG_DEB_EPOCH : "" VERSION = VERSION - } - contexts = { - offload-src = OFFLOAD_BIN + COMMIT = COMMIT + BUILD = BUILD + DATE = DATE } } @@ -788,7 +800,7 @@ target "pkg" { # BAKE_LOCAL_PLATFORM is a built-in var returning the current platform's # default platform specification: https://docs.docker.com/build/customize/bake/file-definition/#built-in-variables platforms = LOCAL_PLATFORM != null ? [BAKE_LOCAL_PLATFORM] : distroPlatforms(item.distro, item.pkg) - secret = distroSecrets(item.distro) + secret = concat(distroSecrets(item.distro), PKG_BUILD_ENV_FILE != null && PKG_BUILD_ENV_FILE != "" ? ["type=file,id=build-env,src=${PKG_BUILD_ENV_FILE}"] : []) attest = [ "type=sbom", "type=provenance,mode=max" diff --git a/pkg/offload/Dockerfile b/pkg/offload/Dockerfile index a2e740fd..9abe09f5 100644 --- a/pkg/offload/Dockerfile +++ b/pkg/offload/Dockerfile @@ -14,8 +14,6 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Packages the signed docker-offload binaries from a GitHub release. Nothing is compiled here. - ARG XX_VERSION="1.9.0" ARG DISTRO_NAME="debian12" @@ -26,32 +24,43 @@ ARG DISTRO_ID="12" ARG DISTRO_IMAGE="debian:bookworm" ARG PKG_NAME="docker-offload-plugin" -ARG VERSION -# scripts from docker/packaging (gen-deb-changelog, rpm-init, rpm-builddep...) +ARG GO_IMAGE="golang" +# Must be the exact Go version of the release build, so the package build reproduces it. +ARG GO_VERSION="1.27.3" +ARG GO_IMAGE_VARIANT="bookworm" + +# stage used as named context that mounts hack/scripts # see pkg target in docker-bake.hcl FROM scratch AS scripts +# The source tree is private and is passed in by the caller as the src named context, with +# Go dependencies already vendored. There is no git clone fallback. +FROM scratch AS src + # cross compilation helper FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx -# Directory with docker-offload-linux-, overridden by the offload-src named context -# in docker-bake.hcl. -FROM scratch AS offload-src +# go base image to retrieve /usr/local/go +FROM ${GO_IMAGE}:${GO_VERSION}-${GO_IMAGE_VARIANT} AS go # deb FROM ${DISTRO_IMAGE} AS builder-deb -# A new BUILDER_EPOCH value refreshes the cached apt layers. -ARG BUILDER_EPOCH COPY --from=xx / / +ENV GOPATH="/go" +ENV PATH="$PATH:/usr/local/go/bin:$GOPATH/bin" +ENV GOTOOLCHAIN="local" ARG DISTRO_NAME -RUN apt-get update && apt-get install -y --no-install-recommends apt-utils bash binutils ca-certificates devscripts equivs +RUN apt-get update && apt-get install -y --no-install-recommends apt-utils bash ca-certificates devscripts equivs COPY deb /root/package/debian ARG TARGETPLATFORM RUN mk-build-deps -t "xx-apt-get -o Debug::pkgProblemResolver=yes --no-install-recommends -y" -i /root/package/debian/control WORKDIR /root/package ARG NIGHTLY_BUILD ARG VERSION +ARG COMMIT +ARG BUILD +ARG DATE ARG DISTRO_RELEASE ARG DISTRO_ID ARG DISTRO_SUITE @@ -63,16 +72,17 @@ ARG PKG_DEB_EPOCH ARG SOURCE_DATE_EPOCH RUN --mount=type=bind,source=scripts/pkg-deb-build.sh,target=/usr/local/bin/pkg-deb-build \ --mount=type=bind,from=scripts,source=gen-deb-changelog.sh,target=/usr/local/bin/gen-deb-changelog \ - --mount=type=bind,from=offload-src,target=/opt/offload-bin < Homepage: https://www.docker.com Standards-Version: 3.9.6 Build-Depends: bash, - debhelper-compat (= 12) + debhelper-compat (= 12), + make Package: docker-offload-plugin Priority: optional diff --git a/pkg/offload/deb/rules b/pkg/offload/deb/rules index aed4e5be..1113126e 100755 --- a/pkg/offload/deb/rules +++ b/pkg/offload/deb/rules @@ -1,22 +1,25 @@ #!/usr/bin/make -f +# force packages to be built with xz compression, as Ubuntu 21.10 and up use +# zstd compression, which is non-standard, and breaks 'dpkg-sig --verify' override_dh_builddeb: dh_builddeb -- -Zxz override_dh_auto_build: + make -C $(CURDIR)/offload ce-release VERSION=$(VERSION) COMMIT=$(COMMIT) BUILD=$(BUILD) DATE=$(DATE) BUILD_ENV_FILE=$(BUILD_ENV_FILE) override_dh_auto_test: - ver="$$(/usr/libexec/docker/cli-plugins/docker-offload docker-cli-plugin-metadata | awk '{ gsub(/[",:]/,"")}; $$1 == "Version" { print $$2 }')"; \ - test "$$ver" = "$(VERSION)" && echo "PASS" || (echo "FAIL: got '$$ver', want '$(VERSION)'" && exit 1) + ver="$$($(CURDIR)/offload/dist/docker-offload docker-cli-plugin-metadata | awk '{ gsub(/[",:]/,"")}; $$1 == "Version" { print $$2 }')"; \ + test "$$ver" = "$(VERSION)" && echo "PASS: docker-offload version OK" || (echo "FAIL: docker-offload version ($$ver) did not match $(VERSION)" && exit 1) -# The binary is prebuilt and its signature and attestation cover the exact bytes, so do not -# strip or rewrite it. +# The build is reproducible, and the packaged binary is checked against the release +# checksums, so do not strip or otherwise rewrite it after the build. override_dh_strip: override_dh_dwz: override_dh_auto_install: - install -D -p -m 0755 /usr/libexec/docker/cli-plugins/docker-offload debian/docker-offload-plugin/usr/libexec/docker/cli-plugins/docker-offload + install -D -p -m 0755 $(CURDIR)/offload/dist/docker-offload debian/docker-offload-plugin/usr/libexec/docker/cli-plugins/docker-offload %: dh $@ diff --git a/pkg/offload/rpm/docker-offload-plugin.spec b/pkg/offload/rpm/docker-offload-plugin.spec index 1b922905..1f3a1c88 100644 --- a/pkg/offload/rpm/docker-offload-plugin.spec +++ b/pkg/offload/rpm/docker-offload-plugin.spec @@ -1,5 +1,6 @@ %global debug_package %{nil} -# Keep the ELF notes so the prebuilt binary still matches its attested digest. +# The build is reproducible, and the packaged binary is checked against the release +# checksums, so do not rewrite the ELF notes after the build. %global __brp_strip_comment_note %{nil} Name: docker-offload-plugin @@ -16,6 +17,7 @@ Packager: Docker Enhances: docker-ce-cli BuildRequires: bash +BuildRequires: make %description Docker Offload plugin for the Docker CLI. @@ -23,14 +25,14 @@ Docker Offload plugin for the Docker CLI. %prep %build -test -f /usr/local/libexec/docker/cli-plugins/docker-offload +make -C %{_srcdir} ce-release VERSION=%{_origversion} COMMIT=%{_commit} BUILD=%{_build} DATE=%{_date} BUILD_ENV_FILE=%{_buildenvfile} %check -ver="$(/usr/local/libexec/docker/cli-plugins/docker-offload docker-cli-plugin-metadata | awk '{ gsub(/[",:]/,"")}; $1 == "Version" { print $2 }')" -test "$ver" = "%{_origversion}" && echo "PASS" || { echo "FAIL: got '$ver', want '%{_origversion}'"; exit 1; } +ver="$(%{_srcdir}/dist/docker-offload docker-cli-plugin-metadata | awk '{ gsub(/[",:]/,"")}; $1 == "Version" { print $2 }')" +test "$ver" = "%{_origversion}" && echo "PASS: docker-offload version OK" || { echo "FAIL: docker-offload version ($ver) did not match %{_origversion}"; exit 1; } %install -install -D -p -m 0755 /usr/local/libexec/docker/cli-plugins/docker-offload ${RPM_BUILD_ROOT}%{_libexecdir}/docker/cli-plugins/docker-offload +install -D -p -m 0755 %{_srcdir}/dist/docker-offload ${RPM_BUILD_ROOT}%{_libexecdir}/docker/cli-plugins/docker-offload %files %{_libexecdir}/docker/cli-plugins/docker-offload diff --git a/pkg/offload/scripts/pkg-deb-build.sh b/pkg/offload/scripts/pkg-deb-build.sh index 2fca3bed..b196ab81 100755 --- a/pkg/offload/scripts/pkg-deb-build.sh +++ b/pkg/offload/scripts/pkg-deb-build.sh @@ -16,6 +16,9 @@ : "${NIGHTLY_BUILD=}" : "${VERSION=}" +: "${COMMIT=}" +: "${BUILD=}" +: "${DATE=}" : "${DISTRO_NAME=}" : "${DISTRO_RELEASE=}" @@ -30,7 +33,9 @@ : "${PKG_DEB_EPOCH=}" : "${SOURCE_DATE_EPOCH=}" +: "${SRCDIR=./offload}" : "${OUTDIR=/out}" +: "${BUILD_ENV_FILE=}" set -e @@ -38,6 +43,10 @@ if [ -z "$VERSION" ]; then echo >&2 "error: VERSION is required" exit 1 fi +case "$VERSION" in + v*) ;; + *) echo >&2 "error: VERSION must start with v, got $VERSION"; exit 1 ;; +esac if [ -z "$DISTRO_NAME" ]; then echo >&2 "error: DISTRO_NAME is required" exit 1 @@ -46,6 +55,10 @@ if [ -z "$OUTDIR" ]; then echo >&2 "error: OUTDIR is required" exit 1 fi +if [ ! -f "${SRCDIR}/Makefile" ]; then + echo >&2 "error: no Makefile in ${SRCDIR}; pass the source tree as the src named context" + exit 1 +fi mkdir -p "$OUTDIR" @@ -76,10 +89,7 @@ mkdir -p "${pkgoutput}" set -x -# Install the prebuilt plugin. deb/rules packages it from here. -install -D -p -m 0755 "/opt/offload-bin/docker-offload-linux-$(xx-info arch)" \ - /usr/libexec/docker/cli-plugins/docker-offload - chmod -x debian/control debian/copyright -VERSION=${VERSION} dpkg-buildpackage $PKG_DEB_BUILDFLAGS --host-arch $(xx-info debian-arch) --target-arch $(xx-info debian-arch) +VERSION=${VERSION} COMMIT=${COMMIT} BUILD=${BUILD} DATE=${DATE} BUILD_ENV_FILE=${BUILD_ENV_FILE} \ + dpkg-buildpackage $PKG_DEB_BUILDFLAGS --host-arch $(xx-info debian-arch) --target-arch $(xx-info debian-arch) cp /root/docker-* "${pkgoutput}"/ diff --git a/pkg/offload/scripts/pkg-rpm-build.sh b/pkg/offload/scripts/pkg-rpm-build.sh index ae54fa9b..83aa2611 100755 --- a/pkg/offload/scripts/pkg-rpm-build.sh +++ b/pkg/offload/scripts/pkg-rpm-build.sh @@ -16,6 +16,9 @@ : "${NIGHTLY_BUILD=}" : "${VERSION=}" +: "${COMMIT=}" +: "${BUILD=}" +: "${DATE=}" : "${DISTRO_NAME=}" : "${DISTRO_RELEASE=}" @@ -29,7 +32,9 @@ : "${PKG_RPM_RELEASE=}" : "${SOURCE_DATE_EPOCH=}" +: "${SRCDIR=/usr/local/src/offload}" : "${OUTDIR=/out}" +: "${BUILD_ENV_FILE=}" set -e @@ -37,6 +42,10 @@ if [ -z "$VERSION" ]; then echo >&2 "error: VERSION is required" exit 1 fi +case "$VERSION" in + v*) ;; + *) echo >&2 "error: VERSION must start with v, got $VERSION"; exit 1 ;; +esac if [ -z "$DISTRO_NAME" ]; then echo >&2 "error: DISTRO_NAME is required" exit 1 @@ -45,6 +54,10 @@ if [ -z "$OUTDIR" ]; then echo >&2 "error: OUTDIR is required" exit 1 fi +if [ ! -f "${SRCDIR}/Makefile" ]; then + echo >&2 "error: no Makefile in ${SRCDIR}; pass the source tree as the src named context" + exit 1 +fi mkdir -p "$OUTDIR" @@ -65,10 +78,17 @@ if [ -n "$NIGHTLY_BUILD" ]; then fi pkgVersion="${pkgVersion//-/$tilde}" +# rpm rejects macros with an empty body, so optional values default to %{nil}. +nil='%{nil}' rpmDefine=( --define "_version ${pkgVersion}" --define "_origversion ${VERSION}" --define "_release ${PKG_RPM_RELEASE:-1}" + --define "_srcdir ${SRCDIR}" + --define "_commit ${COMMIT:-$nil}" + --define "_build ${BUILD:-$nil}" + --define "_date ${DATE:-$nil}" + --define "_buildenvfile ${BUILD_ENV_FILE:-$nil}" ) pkgoutput="${OUTDIR}/${DISTRO_RELEASE}/${DISTRO_SUITE}/$(xx-info arch)" @@ -78,10 +98,6 @@ fi set -x -# Install the prebuilt plugin. The spec packages it from here. -install -D -p -m 0755 "/opt/offload-bin/docker-offload-linux-$(xx-info arch)" \ - /usr/local/libexec/docker/cli-plugins/docker-offload - rpmbuild --target $(xx-info rhel-arch) $PKG_RPM_BUILDFLAGS "${rpmDefine[@]}" /root/rpmbuild/SPECS/*.spec mkdir -p "${pkgoutput}" cp ./RPMS/*/*.* "${pkgoutput}"/ From 01bfdab0b23aa7d96b1f3191a6edb6c72d7f4f61 Mon Sep 17 00:00:00 2001 From: Nick Sieger Date: Wed, 11 Nov 2026 11:56:54 -0600 Subject: [PATCH 3/3] chore(offload): align defaults with debian 13 and debhelper 13 - debhelper-compat 13, as in #550 - debian 13 trixie defaults for the distro and Go image variant, as in #567 - xx 1.10.0 Signed-off-by: Nick Sieger --- docker-bake.hcl | 2 +- pkg/offload/Dockerfile | 12 ++++++------ pkg/offload/deb/control | 2 +- pkg/offload/verify.Dockerfile | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/docker-bake.hcl b/docker-bake.hcl index 585cd794..5ece703c 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -724,7 +724,7 @@ target "_pkg-agent" { target "_pkg-offload" { args = { PKG_NAME = PKG_NAME != null && PKG_NAME != "" ? PKG_NAME : "docker-offload-plugin" - GO_IMAGE_VARIANT = GO_IMAGE_VARIANT != null && GO_IMAGE_VARIANT != "" ? GO_IMAGE_VARIANT : "bookworm" + GO_IMAGE_VARIANT = GO_IMAGE_VARIANT != null && GO_IMAGE_VARIANT != "" ? GO_IMAGE_VARIANT : "trixie" PKG_DEB_EPOCH = PKG_DEB_EPOCH != null && PKG_DEB_EPOCH != "" ? PKG_DEB_EPOCH : "" VERSION = VERSION COMMIT = COMMIT diff --git a/pkg/offload/Dockerfile b/pkg/offload/Dockerfile index 9abe09f5..57dbddf0 100644 --- a/pkg/offload/Dockerfile +++ b/pkg/offload/Dockerfile @@ -14,21 +14,21 @@ # See the License for the specific language governing permissions and # limitations under the License. -ARG XX_VERSION="1.9.0" +ARG XX_VERSION="1.10.0" -ARG DISTRO_NAME="debian12" +ARG DISTRO_NAME="debian13" ARG DISTRO_TYPE="deb" ARG DISTRO_RELEASE="debian" -ARG DISTRO_SUITE="bookworm" -ARG DISTRO_ID="12" -ARG DISTRO_IMAGE="debian:bookworm" +ARG DISTRO_SUITE="trixie" +ARG DISTRO_ID="13" +ARG DISTRO_IMAGE="debian:trixie" ARG PKG_NAME="docker-offload-plugin" ARG GO_IMAGE="golang" # Must be the exact Go version of the release build, so the package build reproduces it. ARG GO_VERSION="1.27.3" -ARG GO_IMAGE_VARIANT="bookworm" +ARG GO_IMAGE_VARIANT="trixie" # stage used as named context that mounts hack/scripts # see pkg target in docker-bake.hcl diff --git a/pkg/offload/deb/control b/pkg/offload/deb/control index e3a76361..0cbf6312 100644 --- a/pkg/offload/deb/control +++ b/pkg/offload/deb/control @@ -5,7 +5,7 @@ Maintainer: Docker Homepage: https://www.docker.com Standards-Version: 3.9.6 Build-Depends: bash, - debhelper-compat (= 12), + debhelper-compat (= 13), make Package: docker-offload-plugin diff --git a/pkg/offload/verify.Dockerfile b/pkg/offload/verify.Dockerfile index 9379d608..ac2dda47 100644 --- a/pkg/offload/verify.Dockerfile +++ b/pkg/offload/verify.Dockerfile @@ -16,10 +16,10 @@ # Installs the built package on a clean distro image and checks the plugin it installs. -ARG XX_VERSION="1.9.0" +ARG XX_VERSION="1.10.0" ARG DISTRO_TYPE="deb" -ARG DISTRO_IMAGE="debian:bookworm" +ARG DISTRO_IMAGE="debian:trixie" # cross compilation helper FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx