From f281b10ae8f8cbdcec9027e69a13aab5b6a7bd07 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:13:53 +0200 Subject: [PATCH 1/2] docker: add combined static package Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- .github/CODEOWNERS | 1 + .github/labeler.yml | 8 +- .github/workflows/.build.yml | 23 ++- .github/workflows/build-docker.yml | 10 + .github/workflows/release-docker.yml | 19 ++ docker-bake.hcl | 84 +++++++-- pkg/docker/Dockerfile | 178 ++++++++++++++++++ pkg/docker/scripts/check-gomod.sh | 24 +++ pkg/docker/scripts/pkg-static-build.sh | 242 +++++++++++++++++++++++++ pkg/docker/verify.Dockerfile | 80 ++++++++ 10 files changed, 646 insertions(+), 23 deletions(-) create mode 100644 pkg/docker/Dockerfile create mode 100755 pkg/docker/scripts/check-gomod.sh create mode 100755 pkg/docker/scripts/pkg-static-build.sh create mode 100644 pkg/docker/verify.Dockerfile diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index b7055b8a..a0f49adb 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -4,5 +4,6 @@ pkg/model/* @docker/ai-models-infra pkg/buildx/* @docker/build pkg/agent/* @docker/ai-agent-team pkg/containerd/* @docker/engine +pkg/docker/* @docker/engine pkg/docker-cli/* @docker/engine pkg/docker-engine/* @docker/engine diff --git a/.github/labeler.yml b/.github/labeler.yml index 16da7df9..194093b0 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -35,11 +35,15 @@ area/pkg/credential-helpers: area/pkg/docker-cli: - changed-files: - - any-glob-to-any-file: 'pkg/docker-cli/**' + - any-glob-to-any-file: + - 'pkg/docker/**' + - 'pkg/docker-cli/**' area/pkg/docker-engine: - changed-files: - - any-glob-to-any-file: 'pkg/docker-engine/**' + - any-glob-to-any-file: + - 'pkg/docker/**' + - 'pkg/docker-engine/**' area/pkg/model: - changed-files: diff --git a/.github/workflows/.build.yml b/.github/workflows/.build.yml index 87e28cb3..c5439f7c 100644 --- a/.github/workflows/.build.yml +++ b/.github/workflows/.build.yml @@ -88,14 +88,15 @@ jobs: const includes = []; const verifications = []; for (const targetName of Object.keys(def.target)) { - if (!targetName.startsWith(`pkg-${inpName}-`)) { - continue; - } const match = targetName.match(/^pkg-(.+)-([^-]+)$/); if (!match) { throw new Error(`Invalid target name: ${targetName}`); } + const pkgName = match[1]; const distro = match[2]; + if (pkgName !== inpName) { + continue; + } if (distroFilter.length > 0 && !distroFilter.includes(distro)) { core.info(`Skipping ${targetName} because it doesn't match the input distro filter`); continue; @@ -358,6 +359,22 @@ jobs: * commit: [\`${RUNHCS_COMMIT}\`](${RUNHCS_REPO}/commit/${RUNHCS_COMMIT}) EOF fi + + if [ "$INPUT_NAME" = "docker" ]; then + cat >> "/tmp/summary.txt" <<-EOF + * cli + * repo: ${CLI_REPO} + * ref: \`${CLI_REF}\` + * version: \`${CLI_VERSION}\` + * commit: [\`${CLI_COMMIT}\`](${CLI_REPO}/commit/${CLI_COMMIT}) + * containerd + * repo: ${CONTAINERD_REPO} + * version: \`${CONTAINERD_VERSION}\` + * runc + * repo: ${RUNC_REPO} + * version: \`${RUNC_VERSION}\` + EOF + fi cat >> "/tmp/summary.txt" <<-EOF * packages: \`$(find /tmp/release -type f | wc -l)\` files diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml index 92cb8bd6..35911fdd 100644 --- a/.github/workflows/build-docker.yml +++ b/.github/workflows/build-docker.yml @@ -16,6 +16,7 @@ on: - '.github/workflows/.build.yml' - '.github/workflows/build-docker.yml' - 'hack/scripts/**' + - 'pkg/docker/**' - 'pkg/docker-engine/**' - 'pkg/docker-cli/**' - 'docker-bake.hcl' @@ -27,6 +28,7 @@ on: - '.github/workflows/.build.yml' - '.github/workflows/build-docker.yml' - 'hack/scripts/**' + - 'pkg/docker/**' - 'pkg/docker-engine/**' - 'pkg/docker-cli/**' - 'docker-bake.hcl' @@ -47,3 +49,11 @@ jobs: id-token: write with: name: docker-cli + + docker: + uses: ./.github/workflows/.build.yml + permissions: + contents: read + id-token: write + with: + name: docker diff --git a/.github/workflows/release-docker.yml b/.github/workflows/release-docker.yml index 7bc072eb..7aa0288f 100644 --- a/.github/workflows/release-docker.yml +++ b/.github/workflows/release-docker.yml @@ -93,3 +93,22 @@ jobs: secrets: rh_user: ${{ secrets.RH_USER }} rh_pass: ${{ secrets.RH_PASS }} + + docker: + if: ${{ inputs.distros == '' || contains(inputs.distros, 'static') }} + uses: ./.github/workflows/.build.yml + permissions: + contents: write # needed to create release and upload artifacts + id-token: write # needed to sign attestations + with: + name: docker + release: ${{ inputs.release }} + distros: ${{ inputs.distros }} + vars: | + PKG_REPO=${{ inputs.engine-repo }} + PKG_REF=${{ inputs.engine-ref }} + CLI_REPO=${{ inputs.cli-repo }} + CLI_REF=${{ inputs.cli-ref }} + DOCKER_VERSION=${{ inputs.version }} + dockerhub_username: docker + dockerhub_oidc_connectionid: ${{ vars.DOCKERHUB_OIDC_CONNECTIONID }} diff --git a/docker-bake.hcl b/docker-bake.hcl index 99373e30..66597788 100644 --- a/docker-bake.hcl +++ b/docker-bake.hcl @@ -50,6 +50,7 @@ variable "PKGS_BASE" { "compose", "containerd", "credential-helpers", + "docker", "docker-cli", "docker-engine", "model", @@ -79,6 +80,8 @@ variable "PKG_PLATFORMS_BASE" { containerd = ["linux/amd64", "linux/arm/v6", "linux/arm/v7", "linux/arm64", "linux/ppc64le", "linux/s390x", "windows/amd64", "windows/arm64"] # https://github.com/docker/docker-credential-helpers/blob/f9d3010165b642df37215b1be945552f2c6f0e3b/docker-bake.hcl#L56-L66 credential-helpers = ["darwin/amd64", "darwin/arm64", "linux/amd64", "linux/arm/v6", "linux/arm/v7", "linux/arm64", "linux/ppc64le", "linux/s390x", "windows/amd64"] + # Combined Docker static archives include Engine and CLI, so this uses the Engine platform set. + docker = ["linux/amd64", "linux/arm/v6", "linux/arm/v7", "linux/arm64", "linux/ppc64le", "linux/s390x", "windows/amd64", "windows/arm64"] # https://github.com/docker/cli/blob/84038691220e7ba3329a177e4e3357b4ee0e3a52/docker-bake.hcl#L30-L42 docker-cli = ["darwin/amd64", "darwin/arm64", "linux/386", "linux/amd64", "linux/arm/v6", "linux/arm/v7", "linux/arm64", "linux/ppc64le", "linux/riscv64", "linux/s390x", "windows/amd64", "windows/arm64"] # https://github.com/moby/moby/blob/83264918d3e1c61341511e360a7277150b914b3f/docker-bake.hcl#L82-L91 @@ -95,6 +98,13 @@ variable "PKG_PLATFORMS_EXTRA" { default = {} } +variable "PKG_DISTROS" { + description = "Package-specific distro mapping. Packages omitted here build for all DISTROS." + default = { + docker = ["static"] + } +} + variable "PKG_CONTEXTS_EXTRA" { description = "Additional package context mapping to merge from an override bake definition." default = {} @@ -174,6 +184,18 @@ variable "PKG_RPM_RELEASE" { default = null } +variable "CLI_REPO" { + description = "Repository URL of the Docker CLI to build. Only used for the combined Docker static package." + default = null +} +variable "CLI_REF" { + description = "Reference (branch, tag, commit) of the Docker CLI to build. Only used for the combined Docker static package." + default = null +} +variable "DOCKER_VERSION" { + description = "Docker version to use for the combined Docker static package. If empty, the Engine source version is used." + default = null +} variable "RUNC_REF" { description = "Reference (branch, tag, commit) of runc to build. Only used for containerd package. If not set, defaults to the version specified in containerd's script/setup/runc-version file." default = null @@ -595,6 +617,20 @@ target "_pkg-credential-helpers" { } } +target "_pkg-docker" { + args = { + PKG_NAME = PKG_NAME != null && PKG_NAME != "" ? PKG_NAME : "docker" + PKG_REPO = PKG_REPO != null && PKG_REPO != "" ? PKG_REPO : "https://github.com/docker/docker.git" + PKG_REF = PKG_REF != null && PKG_REF != "" ? PKG_REF : "master" + CLI_REPO = CLI_REPO != null && CLI_REPO != "" ? CLI_REPO : "https://github.com/docker/cli.git" + CLI_REF = CLI_REF != null && CLI_REF != "" ? CLI_REF : "master" + DOCKER_VERSION = DOCKER_VERSION + GO_VERSION = GO_VERSION != null && GO_VERSION != "" ? GO_VERSION : "1.26.5" # https://github.com/moby/moby/blob/master/Dockerfile + GO_IMAGE_VARIANT = GO_IMAGE_VARIANT != null && GO_IMAGE_VARIANT != "" ? GO_IMAGE_VARIANT : "bookworm" + PKG_REMOTE_DOCKERFILE = "Dockerfile" + } +} + target "_pkg-docker-cli" { args = { PKG_NAME = PKG_NAME != null && PKG_NAME != "" ? PKG_NAME : "docker-ce-cli" @@ -689,22 +725,28 @@ group "default" { } target "pkg" { - name = "pkg-${pkg}-${distro}" - description = "Build ${pkg} package for ${distro}" - inherits = ["_common", "_distro-${distro}", "_pkg-${pkg}"] + name = "pkg-${item.pkg}-${item.distro}" + description = "Build ${item.pkg} package for ${item.distro}" + inherits = ["_common", "_distro-${item.distro}", "_pkg-${item.pkg}"] matrix = { - pkg = PKGS - distro = DISTROS - } - context = pkgContext(pkg) + item = flatten([ + for pkg in PKGS : [ + for distro in lookup(PKG_DISTROS, pkg, DISTROS) : { + pkg = pkg + distro = distro + } + ] + ]) + } + context = pkgContext(item.pkg) contexts = { scripts = "./hack/scripts" } - output = ["type=local,dest=./bin/pkg/${pkg}/${distro}"] + output = ["type=local,dest=./bin/pkg/${item.pkg}/${item.distro}"] # 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(distro, pkg) - secret = distroSecrets(distro) + platforms = LOCAL_PLATFORM != null ? [BAKE_LOCAL_PLATFORM] : distroPlatforms(item.distro, item.pkg) + secret = distroSecrets(item.distro) attest = [ "type=sbom", "type=provenance,mode=max" @@ -712,18 +754,24 @@ target "pkg" { } target "verify" { - name = "verify-${pkg}-${distro}" - description = "Verify ${pkg} package for ${distro}" - inherits = ["_common", "_distro-${distro}", "_pkg-${pkg}"] + name = "verify-${item.pkg}-${item.distro}" + description = "Verify ${item.pkg} package for ${item.distro}" + inherits = ["_common", "_distro-${item.distro}", "_pkg-${item.pkg}"] matrix = { - pkg = PKGS - distro = DISTROS - } - context = pkgContext(pkg) + item = flatten([ + for pkg in PKGS : [ + for distro in lookup(PKG_DISTROS, pkg, DISTROS) : { + pkg = pkg + distro = distro + } + ] + ]) + } + context = pkgContext(item.pkg) dockerfile = "verify.Dockerfile" contexts = { scripts = "./hack/scripts" - bin = "./bin/pkg/${pkg}/${distro}" + bin = "./bin/pkg/${item.pkg}/${item.distro}" } no-cache = true output = ["type=cacheonly"] diff --git a/pkg/docker/Dockerfile b/pkg/docker/Dockerfile new file mode 100644 index 00000000..72af04cf --- /dev/null +++ b/pkg/docker/Dockerfile @@ -0,0 +1,178 @@ +# syntax=docker/dockerfile:1 + +# Copyright 2022 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. + +ARG XX_VERSION="1.9.0" + +# https://github.com/moby/moby/blob/master/Dockerfile#L157 +ARG GOWINRES_VERSION="v0.3.1" + +# https://github.com/docker/cli/blob/master/Dockerfile#L9 +ARG GOVERSIONINFO_VERSION="v1.4.1" + +ARG DISTRO_NAME="debian12" +ARG DISTRO_TYPE="deb" +ARG DISTRO_RELEASE="debian" +ARG DISTRO_ID="12" +ARG DISTRO_SUITE="bookworm" +ARG DISTRO_IMAGE="debian:bookworm" + +ARG PKG_NAME="docker" +ARG PKG_REPO="https://github.com/docker/docker.git" +ARG PKG_REF="master" +ARG CLI_REPO="https://github.com/docker/cli.git" +ARG CLI_REF="master" +ARG DOCKER_VERSION + +ARG GO_IMAGE="golang" +ARG GO_VERSION="1.26.5" +ARG GO_IMAGE_VARIANT="bookworm" + +ARG TAGPREFIX="docker-" + +# stage used as named context that mounts hack/scripts +# see pkg target in docker-bake.hcl +FROM scratch AS scripts + +# cross compilation helper +FROM --platform=$BUILDPLATFORM tonistiigi/xx:${XX_VERSION} AS xx + +# go base image to retrieve /usr/local/go +FROM --platform=$BUILDPLATFORM ${GO_IMAGE}:${GO_VERSION}-${GO_IMAGE_VARIANT} AS gocross + +# src +FROM --platform=$BUILDPLATFORM alpine AS src-base +RUN apk add --no-cache bash curl file git zip tar + +FROM src-base AS engine-src +WORKDIR /src +ARG PKG_REPO +RUN git init . && git remote add origin "${PKG_REPO}" +ARG PKG_REF +RUN git fetch origin "${PKG_REF}" +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD + +FROM src-base AS cli-src +WORKDIR /src +ARG CLI_REPO +RUN git init . && git remote add origin "${CLI_REPO}" +ARG CLI_REF +RUN git fetch origin "${CLI_REF}" +refs/heads/*:refs/remotes/origin/* +refs/tags/*:refs/tags/* && git checkout -q FETCH_HEAD + +# metadata +FROM src-base AS metadata-builder +ARG PKG_REPO +ARG PKG_REF +ARG CLI_REPO +ARG CLI_REF +ARG DOCKER_VERSION +ARG NIGHTLY_BUILD +ARG TAGPREFIX +RUN --mount=type=bind,from=scripts,source=gen-ver.sh,target=/usr/local/bin/gen-ver \ + --mount=type=bind,from=engine-src,source=/src,target=/engine-src \ + --mount=type=bind,from=cli-src,source=/src,target=/cli-src <&2 "error: ARG ${name} not found in /engine-src/Dockerfile" + exit 1 + fi + printf '%s\n' "$value" + } + CONTAINERD_VERSION="$(dockerfile_arg CONTAINERD_VERSION)" + RUNC_VERSION="$(dockerfile_arg RUNC_VERSION)" + VERSION="${DOCKER_VERSION:-${ENGINE_GENVER_VERSION}}" + case "$VERSION" in + v*) ;; + *) VERSION="v${VERSION}" ;; + esac + cat > "/out/metadata.env" <<-EOF +REPO=${PKG_REPO%.*} +REF=${PKG_REF} +VERSION=${VERSION} +COMMIT=${ENGINE_GENVER_COMMIT} +CLI_REPO=${CLI_REPO%.*} +CLI_REF=${CLI_REF} +CLI_VERSION=${CLI_GENVER_VERSION} +CLI_COMMIT=${CLI_GENVER_COMMIT} +CONTAINERD_REPO=https://github.com/containerd/containerd +CONTAINERD_VERSION=${CONTAINERD_VERSION} +RUNC_REPO=https://github.com/opencontainers/runc +RUNC_VERSION=${RUNC_VERSION} +EOF +EOT + +FROM scratch AS metadata +COPY --from=metadata-builder /out / + +# static +FROM --platform=$BUILDPLATFORM ${DISTRO_IMAGE} AS build-base-static +COPY --from=xx / / +RUN apt-get update && apt-get install -y --no-install-recommends bash ca-certificates file git zip tar +ENV GOPROXY="https://proxy.golang.org|direct" +ENV GOPATH="/go" +ENV PATH="$PATH:/usr/local/go/bin:$GOPATH/bin" +ENV GOTOOLCHAIN="local" + +FROM build-base-static AS gowinres +ARG GOWINRES_VERSION +RUN --mount=type=bind,from=gocross,source=/usr/local/go,target=/usr/local/go,rw \ + GOBIN=/out GO111MODULE=on go install "github.com/tc-hib/go-winres@${GOWINRES_VERSION}" + +FROM build-base-static AS goversioninfo +ARG GOVERSIONINFO_VERSION +RUN --mount=type=bind,from=gocross,source=/usr/local/go,target=/usr/local/go,rw \ + GOBIN=/out GO111MODULE=on go install "github.com/josephspurrier/goversioninfo/cmd/goversioninfo@${GOVERSIONINFO_VERSION}" + +FROM build-base-static AS builder-static +RUN apt-get install -y --no-install-recommends clang cmake dpkg-dev gcc libc6-dev lld llvm make pkg-config +ARG PKG_NAME +ARG PKG_REF +ARG CLI_REF +ARG DOCKER_VERSION +ARG NIGHTLY_BUILD +ARG TAGPREFIX +WORKDIR /build +ARG TARGETPLATFORM +RUN xx-apt-get install -y gcc libc6-dev libapparmor-dev libnftables-dev libsecret-1-dev libseccomp-dev libsystemd-dev libudev-dev linux-libc-dev pkg-config +RUN --mount=type=bind,source=scripts/pkg-static-build.sh,target=/usr/local/bin/pkg-static-build \ + --mount=type=bind,source=scripts/check-gomod.sh,target=/usr/local/bin/check-gomod \ + --mount=type=bind,from=scripts,source=gen-ver.sh,target=/usr/local/bin/gen-ver \ + --mount=type=bind,from=scripts,source=fix-cc.sh,target=/usr/local/bin/fix-cc \ + --mount=type=bind,from=engine-src,source=/src,target=/go/src/github.com/docker/docker,rw \ + --mount=type=bind,from=cli-src,source=/src,target=/go/src/github.com/docker/cli,rw \ + --mount=type=bind,from=gocross,source=/usr/local/go,target=/usr/local/go,rw \ + --mount=type=bind,from=gowinres,source=/out/go-winres,target=/usr/bin/go-winres \ + --mount=type=bind,from=goversioninfo,source=/out/goversioninfo,target=/usr/bin/goversioninfo \ + --mount=type=tmpfs,target=/go/src/github.com/docker/docker/cli/winresources/dockerd \ + --mount=type=tmpfs,target=/go/src/github.com/docker/docker/cli/winresources/docker-proxy \ + --mount=type=tmpfs,target=/go/src/github.com/docker/cli/winresources \ + OUTDIR=/out BUILDDIR=/build ENGINE_SRCDIR=/go/src/github.com/docker/docker CLI_SRCDIR=/go/src/github.com/docker/cli pkg-static-build + +FROM builder-${DISTRO_TYPE} AS build-pkg +ARG BUILDKIT_SBOM_SCAN_STAGE=true + +FROM scratch AS pkg +COPY --from=build-pkg /out / diff --git a/pkg/docker/scripts/check-gomod.sh b/pkg/docker/scripts/check-gomod.sh new file mode 100755 index 00000000..3f07af3a --- /dev/null +++ b/pkg/docker/scripts/check-gomod.sh @@ -0,0 +1,24 @@ +#!/bin/sh + +# Copyright 2025 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. + +if [ -f "${SRCDIR}/vendor.mod" ]; then + echo off +elif [ -f "${SRCDIR}/go.mod" ]; then + echo on +else + echo >&2 "error: go.mod or vendor.mod not found" + exit 1 +fi diff --git a/pkg/docker/scripts/pkg-static-build.sh b/pkg/docker/scripts/pkg-static-build.sh new file mode 100755 index 00000000..713e1f5e --- /dev/null +++ b/pkg/docker/scripts/pkg-static-build.sh @@ -0,0 +1,242 @@ +#!/usr/bin/env bash + +# Copyright 2022 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=}" + +: "${DOCKER_VERSION=}" + +: "${BUILDDIR=/work/build}" +: "${ENGINE_SRCDIR=/work/engine-src}" +: "${CLI_SRCDIR=/work/cli-src}" +: "${OUTDIR=/out}" + +: "${TAGPREFIX=docker-}" + +set -e + +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 + +for l in $(gen-ver "${ENGINE_SRCDIR}"); do + export "ENGINE_${l?}" +done + +for l in $(TAGPREFIX= gen-ver "${CLI_SRCDIR}"); do + export "CLI_${l?}" +done + +version="${DOCKER_VERSION:-${ENGINE_GENVER_VERSION}}" +case "$version" in + v*) ;; + *) version="v${version}" ;; +esac +version_no_v="${version#v}" + +export GO111MODULE +GO111MODULE=$(SRCDIR="${ENGINE_SRCDIR}" check-gomod) + +xx-go --wrap +fix-cc + +# prefer ld for cross-compiling arm64 +# https://github.com/moby/moby/commit/f676dab8dc58c9eaa83b260c631a92d95a7a0b10 +if [ "$(xx-info arch)" = "arm64" ]; then + XX_CC_PREFER_LINKER=ld xx-clang --setup-target-triple +fi + +binext=$([ "$(xx-info os)" = "windows" ] && echo ".exe" || true) + +engine_builddir="${BUILDDIR}/docker-engine" +cli_builddir="${BUILDDIR}/docker-cli" +runtime_builddir="${BUILDDIR}/docker-runtime" +combined_builddir="${BUILDDIR}/docker" +runtime_srcdir="${BUILDDIR}/runtime-src" +containerd_srcdir="${runtime_srcdir}/containerd" +runc_srcdir="${runtime_srcdir}/runc" +runhcs_srcdir="${runtime_srcdir}/runhcs" +mkdir -p "$engine_builddir" "$cli_builddir" "$runtime_builddir" "$combined_builddir" "$runtime_srcdir" + +dockerfile_arg() { + local name="$1" + local value + value=$(sed -n -E "s/^ARG ${name}=(.*)$/\1/p" "${ENGINE_SRCDIR}/Dockerfile" | head -n1) + value="${value#\"}" + value="${value%\"}" + if [ -z "$value" ]; then + echo >&2 "error: ARG ${name} not found in ${ENGINE_SRCDIR}/Dockerfile" + exit 1 + fi + printf '%s\n' "$value" +} + +fetch_git_ref() { + local repo="$1" + local ref="$2" + local dest="$3" + + git init "$dest" + git -C "$dest" remote add origin "$repo" + git -C "$dest" fetch --depth 1 origin "$ref" + git -C "$dest" checkout -q FETCH_HEAD +} + +( + set -x + pushd "${ENGINE_SRCDIR}" + CGO_ENABLED=1 VERSION="${version}" DOCKER_GITCOMMIT="${ENGINE_GENVER_COMMIT}" ./hack/make.sh binary + mv "./bundles/binary-daemon/dockerd${binext}" "${engine_builddir}/" + if [ "$(xx-info os)" != "windows" ]; then + mv "./bundles/binary-daemon/docker-proxy${binext}" "${engine_builddir}/" + fi + popd + xx-verify --static "${engine_builddir}/dockerd${binext}" + if [ "$(xx-info os)" != "windows" ]; then + xx-verify --static "${engine_builddir}/docker-proxy${binext}" + fi +) + +# TODO: build tini for windows +if [ "$(xx-info os)" != "windows" ]; then + ( + set -x + pushd "${ENGINE_SRCDIR}" + # FIXME: can't use clang with tini + CC=$(xx-info)-gcc PREFIX="${engine_builddir}" TMP_GOPATH="/go" hack/dockerfile/install/install.sh tini + popd + xx-verify --static "${engine_builddir}/docker-init" + ) +fi + +( + set -x + pushd "${CLI_SRCDIR}" + CGO_ENABLED=0 GO111MODULE=off VERSION="${version}" GITCOMMIT="${CLI_GENVER_COMMIT}" GO_LINKMODE=static TARGET="${cli_builddir}" ./scripts/build/binary + popd + xx-verify --static "${cli_builddir}/docker" +) + +if [ "$(xx-info os)" = "linux" ] || [ "$(xx-info os)" = "windows" ]; then + containerd_version=$(dockerfile_arg CONTAINERD_VERSION) + + ( + set -x + fetch_git_ref "https://github.com/containerd/containerd.git" "$containerd_version" "$containerd_srcdir" + containerd_revision=$(git -C "$containerd_srcdir" rev-parse HEAD) + pushd "$containerd_srcdir" + CC="$(xx-info)-gcc" CGO_ENABLED=0 GO111MODULE=on make STATIC=1 VERSION="${containerd_version}" REVISION="${containerd_revision}" bin/containerd + if [ "$(xx-info os)" = "linux" ]; then + CC="$(xx-info)-gcc" CGO_ENABLED=0 GO111MODULE=on make STATIC=1 VERSION="${containerd_version}" REVISION="${containerd_revision}" bin/containerd-shim-runc-v2 + fi + CC="$(xx-info)-gcc" CGO_ENABLED=0 GO111MODULE=on make STATIC=1 VERSION="${containerd_version}" REVISION="${containerd_revision}" bin/ctr + mv bin/containerd bin/ctr "$runtime_builddir/" + if [ "$(xx-info os)" = "linux" ]; then + mv bin/containerd-shim-runc-v2 "$runtime_builddir/" + fi + popd + if [ "$(xx-info os)" = "windows" ]; then + mv "${runtime_builddir}/containerd" "${runtime_builddir}/containerd.exe" + mv "${runtime_builddir}/ctr" "${runtime_builddir}/ctr.exe" + fi + xx-verify --static "${runtime_builddir}/containerd${binext}" + xx-verify --static "${runtime_builddir}/ctr${binext}" + if [ "$(xx-info os)" = "linux" ]; then + xx-verify --static "${runtime_builddir}/containerd-shim-runc-v2" + fi + ) +fi + +if [ "$(xx-info os)" = "linux" ]; then + runc_version=$(dockerfile_arg RUNC_VERSION) + + ( + set -x + fetch_git_ref "https://github.com/opencontainers/runc.git" "$runc_version" "$runc_srcdir" + pushd "$runc_srcdir" + CGO_ENABLED=1 GO111MODULE=on make static + mv runc "$runtime_builddir/" + popd + xx-verify --static "${runtime_builddir}/runc" + ) +fi + +if [ "$(xx-info os)" = "windows" ]; then + runhcs_ref=$(cat "${containerd_srcdir}/script/setup/runhcs-version") + + ( + set -x + fetch_git_ref "https://github.com/Microsoft/hcsshim.git" "$runhcs_ref" "$runhcs_srcdir" + pushd "$runhcs_srcdir" + GO111MODULE=on go build -mod=vendor -o "${runtime_builddir}/containerd-shim-runhcs-v1.exe" ./cmd/containerd-shim-runhcs-v1 + popd + xx-verify --static "${runtime_builddir}/containerd-shim-runhcs-v1.exe" + ) +fi + +cp "${engine_builddir}"/* "$combined_builddir/" +cp -L "${cli_builddir}/docker" "$combined_builddir/docker${binext}" +if [ "$(xx-info os)" = "linux" ] || [ "$(xx-info os)" = "windows" ]; then + cp "${runtime_builddir}"/* "$combined_builddir/" +fi + +pkgoutput="$OUTDIR/static/$(xx-info os)/$(xx-info arch)" +if [ -n "$(xx-info variant)" ]; then + pkgoutput="${pkgoutput}/$(xx-info variant)" +fi +mkdir -p "${pkgoutput}" + +workdir=$(mktemp -d -t docker-packaging.XXXXXXXXXX) +mkdir -p "$workdir/docker" +( + set -x + cp "${combined_builddir}"/* "$workdir/docker/" + cp "${ENGINE_SRCDIR}/LICENSE" "$workdir/docker/engine.LICENSE" + cp "${ENGINE_SRCDIR}/README.md" "$workdir/docker/engine.README.md" + cp "${CLI_SRCDIR}/LICENSE" "$workdir/docker/cli.LICENSE" + cp "${CLI_SRCDIR}/README.md" "$workdir/docker/cli.README.md" + if [ -d "$containerd_srcdir" ]; then + cp "${containerd_srcdir}/LICENSE" "$workdir/docker/containerd.LICENSE" + cp "${containerd_srcdir}/README.md" "$workdir/docker/containerd.README.md" + fi + if [ -d "$runc_srcdir" ]; then + cp "${runc_srcdir}/LICENSE" "$workdir/docker/runc.LICENSE" + cp "${runc_srcdir}/README.md" "$workdir/docker/runc.README.md" + fi + if [ -d "$runhcs_srcdir" ]; then + cp "${runhcs_srcdir}/LICENSE" "$workdir/docker/runhcs.LICENSE" + cp "${runhcs_srcdir}/README.md" "$workdir/docker/runhcs.README.md" + fi +) +if [ "$(xx-info os)" = "windows" ]; then + ( + set -x + cd "$workdir" + zip -r "${pkgoutput}/docker-${version_no_v}.zip" docker + ) +else + ( + set -x + tar -czf "${pkgoutput}/docker-${version_no_v}.tgz" -C "$workdir" docker + ) +fi diff --git a/pkg/docker/verify.Dockerfile b/pkg/docker/verify.Dockerfile new file mode 100644 index 00000000..b677d26a --- /dev/null +++ b/pkg/docker/verify.Dockerfile @@ -0,0 +1,80 @@ +# syntax=docker/dockerfile:1 + +# Copyright 2022 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. + +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 --platform=$BUILDPLATFORM ${DISTRO_IMAGE} AS base + +FROM base AS verify-static +RUN apt-get update && apt-get install -y --no-install-recommends tar unzip +COPY --from=xx / / +ARG TARGETPLATFORM +RUN --mount=from=bin,target=/build <&2 "warning: no packages found in $dir" + exit 0 + fi + if [ "$(xx-info os)" = "windows" ]; then + found= + for package in $(find $dir -type f -name '*.zip'); do + found=1 + ( + set -x + unzip -l $package + workdir=$(mktemp -d -t docker-verify.XXXXXXXXXX) + unzip -q $package -d $workdir + xx-verify --static $workdir/docker/docker.exe + xx-verify --static $workdir/docker/dockerd.exe + xx-verify --static $workdir/docker/containerd.exe + xx-verify --static $workdir/docker/ctr.exe + xx-verify --static $workdir/docker/containerd-shim-runhcs-v1.exe + ) + done + if [ -z "$found" ]; then + echo >&2 "error: no packages found in $dir" + exit 1 + fi + exit 0 + fi + for package in $(find $dir -type f -name '*.tgz'); do + ( + set -x + tar zxvf $package -C /usr/bin --strip-components=1 + ) + done + set -x + docker --version + dockerd --version + containerd --version + ctr --version + runc --version +EOT + +FROM verify-${DISTRO_TYPE} From a814b998c224c93848847b5c56aa3a6ba5680f74 Mon Sep 17 00:00:00 2001 From: CrazyMax <1951866+crazy-max@users.noreply.github.com> Date: Sat, 15 Aug 2026 18:19:04 +0200 Subject: [PATCH 2/2] static: add checksum files for package archives Static package builds now emit a sibling .sha256 file for each generated .tgz and .zip archive. Static package verification checks the generated checksum before unpacking artifacts. Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com> --- pkg/agent/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/agent/verify.Dockerfile | 2 ++ pkg/buildx/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/buildx/verify.Dockerfile | 2 ++ pkg/compose/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/compose/verify.Dockerfile | 2 ++ pkg/containerd/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/containerd/verify.Dockerfile | 2 ++ pkg/credential-helpers/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/credential-helpers/verify.Dockerfile | 2 ++ pkg/docker-cli/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/docker-cli/verify.Dockerfile | 2 ++ pkg/docker-engine/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/docker-engine/verify.Dockerfile | 2 ++ pkg/docker/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/docker/verify.Dockerfile | 4 ++++ pkg/model/scripts/pkg-static-build.sh | 11 +++++++++-- pkg/model/verify.Dockerfile | 2 ++ 18 files changed, 101 insertions(+), 18 deletions(-) diff --git a/pkg/agent/scripts/pkg-static-build.sh b/pkg/agent/scripts/pkg-static-build.sh index 61e63bc0..c8128bc1 100755 --- a/pkg/agent/scripts/pkg-static-build.sh +++ b/pkg/agent/scripts/pkg-static-build.sh @@ -76,15 +76,22 @@ for pkgname in *; do cp "${pkgname}"/* ${SRCDIR}/LICENSE ${SRCDIR}/README.md "$workdir/${pkgname}/" ) if [ "$(xx-info os)" = "windows" ]; then + pkgfile="${pkgoutput}/${pkgname}_${GENVER_VERSION#v}.zip" ( set -x cd "$workdir" - zip -r "${pkgoutput}/${pkgname}_${GENVER_VERSION#v}.zip" "${pkgname}" + zip -r "$pkgfile" "${pkgname}" ) else + pkgfile="${pkgoutput}/${pkgname}_${GENVER_VERSION#v}.tgz" ( set -x - tar -czf "${pkgoutput}/${pkgname}_${GENVER_VERSION#v}.tgz" -C "$workdir" "${pkgname}" + tar -czf "$pkgfile" -C "$workdir" "${pkgname}" ) fi + ( + set -x + cd "$pkgoutput" + sha256sum "${pkgfile##*/}" > "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/agent/verify.Dockerfile b/pkg/agent/verify.Dockerfile index b5d2595e..04a9b908 100644 --- a/pkg/agent/verify.Dockerfile +++ b/pkg/agent/verify.Dockerfile @@ -108,6 +108,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/buildx/verify.Dockerfile b/pkg/buildx/verify.Dockerfile index da99e826..7d0c2b09 100644 --- a/pkg/buildx/verify.Dockerfile +++ b/pkg/buildx/verify.Dockerfile @@ -108,6 +108,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/compose/verify.Dockerfile b/pkg/compose/verify.Dockerfile index 93402bbd..c7f29f94 100644 --- a/pkg/compose/verify.Dockerfile +++ b/pkg/compose/verify.Dockerfile @@ -108,6 +108,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/containerd/verify.Dockerfile b/pkg/containerd/verify.Dockerfile index f2e80fc1..0228eb00 100644 --- a/pkg/containerd/verify.Dockerfile +++ b/pkg/containerd/verify.Dockerfile @@ -112,6 +112,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/credential-helpers/verify.Dockerfile b/pkg/credential-helpers/verify.Dockerfile index f28c4f0c..49725173 100644 --- a/pkg/credential-helpers/verify.Dockerfile +++ b/pkg/credential-helpers/verify.Dockerfile @@ -121,6 +121,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/docker-cli/verify.Dockerfile b/pkg/docker-cli/verify.Dockerfile index ec44407c..a663b726 100644 --- a/pkg/docker-cli/verify.Dockerfile +++ b/pkg/docker-cli/verify.Dockerfile @@ -108,6 +108,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/docker-engine/verify.Dockerfile b/pkg/docker-engine/verify.Dockerfile index 8c14d36d..48ec729a 100644 --- a/pkg/docker-engine/verify.Dockerfile +++ b/pkg/docker-engine/verify.Dockerfile @@ -121,6 +121,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" +) diff --git a/pkg/docker/verify.Dockerfile b/pkg/docker/verify.Dockerfile index b677d26a..8529d043 100644 --- a/pkg/docker/verify.Dockerfile +++ b/pkg/docker/verify.Dockerfile @@ -47,6 +47,8 @@ RUN --mount=from=bin,target=/build < "${pkgfile##*/}.sha256" + ) done diff --git a/pkg/model/verify.Dockerfile b/pkg/model/verify.Dockerfile index 92de98c2..55fa98b0 100644 --- a/pkg/model/verify.Dockerfile +++ b/pkg/model/verify.Dockerfile @@ -108,6 +108,8 @@ RUN --mount=from=bin,target=/build <