From b320292f4bd39ef70f50349ac71ba934a0d4a965 Mon Sep 17 00:00:00 2001 From: Markus Rudy Date: Mon, 15 Jan 2024 16:58:31 +0100 Subject: [PATCH] ci: reproducible images based on upstream releases --- .github/workflows/build-images-releases.yaml | 173 ++++--------------- Makefile.defs | 4 +- images/cilium/Dockerfile | 24 +-- images/operator/Dockerfile | 17 +- 4 files changed, 45 insertions(+), 173 deletions(-) diff --git a/.github/workflows/build-images-releases.yaml b/.github/workflows/build-images-releases.yaml index 8ecfe04375de5..b77d72f841fae 100644 --- a/.github/workflows/build-images-releases.yaml +++ b/.github/workflows/build-images-releases.yaml @@ -1,22 +1,25 @@ name: Image Release Build on: + workflow_dispatch: + inputs: + tag: + description: container image tag + required: false push: tags: - - v1.15.[0-9]+ - - v1.15.[0-9]+-rc.[0-9]+ + - v[0-9]+.* permissions: # To be able to access the repository with `actions/checkout` contents: read - # Required to generate OIDC tokens for `sigstore/cosign-installer` authentication - id-token: write + # Push to ghcr.io + packages: write jobs: build-and-push: timeout-minutes: 45 name: Build and Push Images - environment: release runs-on: ubuntu-22.04 strategy: matrix: @@ -39,110 +42,53 @@ jobs: - name: operator-generic dockerfile: ./images/operator/Dockerfile - - name: hubble-relay - dockerfile: ./images/hubble-relay/Dockerfile - - - name: clustermesh-apiserver - dockerfile: ./images/clustermesh-apiserver/Dockerfile - - - name: docker-plugin - dockerfile: ./images/cilium-docker-plugin/Dockerfile - steps: - - name: Checkout main branch to access local actions - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - with: - ref: ${{ github.event.repository.default_branch }} - persist-credentials: false - - - name: Set Environment Variables - uses: ./.github/actions/set-env-variables - - name: Set up Docker Buildx uses: docker/setup-buildx-action@988b5a0280414f521da01fcc63a27aeeb4b104db # v3.6.1 - - name: Login to DockerHub - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 - if: ${{ env.PUSH_TO_DOCKER_HUB == 'true' }} - with: - username: ${{ secrets.DOCKER_HUB_RELEASE_USERNAME }} - password: ${{ secrets.DOCKER_HUB_RELEASE_PASSWORD }} - - - name: Login to quay.io - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 - with: - registry: quay.io - username: ${{ secrets.QUAY_USERNAME_RELEASE_USERNAME }} - password: ${{ secrets.QUAY_PASSWORD_RELEASE_PASSWORD }} - - name: Getting image tag id: tag run: | - tag=${GITHUB_REF##*/} - echo tag=$tag >> $GITHUB_OUTPUT - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - echo image_tags=${{ github.repository_owner }}/${{ matrix.name }}:$tag,quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:$tag >> $GITHUB_OUTPUT + if [ -z "${{ github.event.inputs.tag }}" ] + then + echo tag=${GITHUB_REF##*/} >> $GITHUB_OUTPUT else - echo image_tags=quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:$tag >> $GITHUB_OUTPUT + echo tag=${{ github.event.inputs.tag }}>> $GITHUB_OUTPUT fi + - name: Login to GitHub Container Registry + uses: docker/login-action@v3 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + - name: Checkout Source Code uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 with: persist-credentials: false + - name: Determine SOURCE_DATE_EPOCH + id: epoch + run: echo epoch=$(git log -1 --pretty=%ct) >> $GITHUB_OUTPUT + - name: Release Build ${{ matrix.name }} uses: docker/build-push-action@5176d81f87c23d6fc96624dfdbcd9f3830bbe445 # v6.5.0 id: docker_build_release + env: + SOURCE_DATE_EPOCH: ${{ steps.epoch.outputs.epoch }} with: provenance: false context: . file: ${{ matrix.dockerfile }} push: true platforms: linux/amd64,linux/arm64 - tags: ${{ steps.tag.outputs.image_tags }} + tags: | + ghcr.io/${{ github.repository }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }} target: release build-args: | OPERATOR_VARIANT=${{ matrix.name }} - - - name: Install Cosign - uses: sigstore/cosign-installer@59acb6260d9c0ba8f4a2f9d9b48431a222b68e20 # v3.5.0 - - - name: Sign Container Image - run: | - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - cosign sign -y docker.io/${{ github.repository_owner }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - fi - cosign sign -y quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - - - name: Generate SBOM - uses: anchore/sbom-action@d94f46e13c6c62f59525ac9a1e147a99dc0b9bf5 # v0.17.0 - with: - artifact-name: sbom_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx.json - output-file: ./sbom_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx.json - image: quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }} - upload-release-assets: false - - - name: Attach SBOM to container images - run: | - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - cosign attach sbom --sbom sbom_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx.json docker.io/${{ github.repository_owner }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - fi - cosign attach sbom --sbom sbom_${{ matrix.name }}_${{ steps.tag.outputs.tag }}.spdx.json quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}@${{ steps.docker_build_release.outputs.digest }} - - - name: Sign SBOM Image - run: | - if [ "${{ env.PUSH_TO_DOCKER_HUB }}" == "true" ]; then - docker_build_release_digest="${{ steps.docker_build_release.outputs.digest }}" - image_name="docker.io/${{ github.repository_owner }}/${{ matrix.name }}:${docker_build_release_digest/:/-}.sbom" - docker_build_release_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)" - cosign sign -y "docker.io/${{ github.repository_owner }}/${{ matrix.name }}@${docker_build_release_sbom_digest}" - fi - - docker_build_release_digest="${{ steps.docker_build_release.outputs.digest }}" - image_name="quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:${docker_build_release_digest/:/-}.sbom" - docker_build_release_sbom_digest="sha256:$(docker buildx imagetools inspect --raw ${image_name} | sha256sum | head -c 64)" - cosign sign -y "quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}@${docker_build_release_sbom_digest}" + SOURCE_DATE_EPOCH=${{ steps.epoch.outputs.epoch }} - name: Image Release Digest shell: bash @@ -153,13 +99,8 @@ jobs: job_name_underscored=${job_name_capital//-/_} echo "${job_name_underscored}_DIGEST := \"${{ steps.docker_build_release.outputs.digest }}\"" > image-digest/makefile-digest.txt - echo "### ${{ matrix.name }}" > image-digest/${{ matrix.name }}.txt - echo "" >> image-digest/${{ matrix.name }}.txt - if [ "${{ env.PUSH_TO_DOCKERHUB }}" == "true" ]; then - echo "\`docker.io/${{ github.repository_owner }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_release.outputs.digest }}\`" >> image-digest/${{ matrix.name }}.txt - fi - echo "\`quay.io/${{ env.QUAY_ORGANIZATION }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_release.outputs.digest }}\`" >> image-digest/${{ matrix.name }}.txt - echo "" >> image-digest/${{ matrix.name }}.txt + printf "%s\n\n" "### ${{ matrix.name }}" >> $GITHUB_STEP_SUMMARY + echo "\`ghcr.io/${{ github.repository }}/${{ matrix.name }}:${{ steps.tag.outputs.tag }}@${{ steps.docker_build_release.outputs.digest }}\`" >> $GITHUB_STEP_SUMMARY # Upload artifact digests - name: Upload artifact digests @@ -168,57 +109,3 @@ jobs: name: image-digest ${{ matrix.name }} path: image-digest retention-days: 10 - - image-digests: - name: Display Digests - runs-on: ubuntu-22.04 - needs: build-and-push - steps: - - name: Getting image tag - id: tag - run: | - echo tag=${GITHUB_REF##*/} >> $GITHUB_OUTPUT - - name: Downloading Image Digests - shell: bash - run: | - mkdir -p image-digest/ - - - name: Download digests of all images built - uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 - with: - path: image-digest/ - pattern: "*image-digest *" - - - name: Image Digests Output - shell: bash - run: | - cd image-digest/ - echo "## Docker Manifests" > ../image-digest-output.txt - echo "" >> ../image-digest-output.txt - find -type f -regex ".*image-digest .*" -not -name "makefile-digest.txt" | sort | xargs -d '\n' cat >> ../image-digest-output.txt - - - name: Image Makefile Digests - shell: bash - run: | - cd image-digest/ - echo "# File generated by .github/workflows/build-images-releases.yaml; DO NOT EDIT." > ../Makefile.digests - echo "# Copyright "$(date +'%Y')" Authors of Cilium" >> ../Makefile.digests - echo "# SPDX-License-Identifier: Apache-2.0" >> ../Makefile.digests - echo "" >> ../Makefile.digests - find -type f -name "makefile-digest.txt" | sort | xargs -d '\n' awk '{print "export " $0}' >> ../Makefile.digests - - # Upload artifact digests - - name: Upload artifact digests - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5 - with: - name: image-digest-output.txt-${{ steps.tag.outputs.tag }} - path: image-digest-output.txt - retention-days: 10 - - # Upload artifact digests - - name: Upload artifact digests - uses: actions/upload-artifact@89ef406dd8d7e03cfd12d9e0a4a378f454709029 # v4.3.5 - with: - name: Makefile.digests-${{ steps.tag.outputs.tag }} - path: Makefile.digests - retention-days: 10 diff --git a/Makefile.defs b/Makefile.defs index f3af931a44e9e..e84205779726b 100644 --- a/Makefile.defs +++ b/Makefile.defs @@ -120,7 +120,7 @@ ifeq ($(NOSTRIP),) # # -w: Omit the DWARF symbol table. # -s: Omit the symbol table and debug information. - GO_BUILD_LDFLAGS += -s -w + GO_BUILD_LDFLAGS += -s -w -buildid= endif ifneq ($(wildcard $(dir $(lastword $(MAKEFILE_LIST)))/images/cilium/Dockerfile),) @@ -144,7 +144,7 @@ BPF_SRCFILES := $(filter-out $(BPF_SRCFILES_IGNORE),$(subst ../,,$(subst $(ROOT_ CILIUM_DATAPATH_SHA256=$(shell cd $(ROOT_DIR); cat $(BPF_SRCFILES) | sha256sum | awk '{print $$1}') GO_BUILD_LDFLAGS += -X "github.com/cilium/cilium/pkg/datapath/loader.DatapathSHA256=$(CILIUM_DATAPATH_SHA256)" -GO_BUILD_FLAGS += -mod=vendor +GO_BUILD_FLAGS += -mod=vendor -trimpath GO_TEST_FLAGS += -mod=vendor -vet=all GO_CLEAN_FLAGS += -mod=vendor diff --git a/images/cilium/Dockerfile b/images/cilium/Dockerfile index adfeb809952b0..067e7d3c40888 100644 --- a/images/cilium/Dockerfile +++ b/images/cilium/Dockerfile @@ -35,6 +35,7 @@ ARG TARGETOS ARG TARGETARCH # MODIFIERS are extra arguments to be passed to make at build time. ARG MODIFIERS +ARG SOURCE_DATE_EPOCH=0 # # Please do not add any dependency updates before the 'make install' here, @@ -42,14 +43,14 @@ ARG MODIFIERS # WORKDIR /go/src/github.com/cilium/cilium RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium --mount=target=/root/.cache,type=cache --mount=target=/go/pkg,type=cache \ - make GOARCH=${TARGETARCH} DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} PKG_BUILD=1 ${MODIFIERS} \ + SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} make GOARCH=${TARGETARCH} DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} PKG_BUILD=1 ${MODIFIERS} \ build-container install-container-binary RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium --mount=target=/root/.cache,type=cache --mount=target=/go/pkg,type=cache \ # install-bash-completion will execute the bash_completion script. It is # fine to run this with same architecture as BUILDARCH since the output of # bash_completion is the same for both architectures. - make GOARCH=${BUILDARCH} DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} PKG_BUILD=1 ${MODIFIERS} \ + SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} make GOARCH=${BUILDARCH} DESTDIR=/tmp/install/${TARGETOS}/${TARGETARCH} PKG_BUILD=1 ${MODIFIERS} \ install-bash-completion licenses-all && \ mv LICENSE.all /tmp/install/${TARGETOS}/${TARGETARCH}/LICENSE.all @@ -58,6 +59,8 @@ COPY images/cilium/init-container.sh \ plugins/cilium-cni/cni-uninstall.sh \ /tmp/install/${TARGETOS}/${TARGETARCH} +RUN find /tmp/install/${TARGETOS}/${TARGETARCH} -depth -execdir touch --no-dereference -a -m -t $(date -u -d @${SOURCE_DATE_EPOCH} +%Y%m%d%H%M.%S) '{}' ';' + # # Cilium runtime install. # @@ -68,26 +71,13 @@ COPY images/cilium/init-container.sh \ # built while allowing the new versions to make changes that are not # backwards compatible. # -FROM ${CILIUM_RUNTIME_IMAGE} as release +FROM quay.io/cilium/cilium:v1.15.8@sha256:3b5b0477f696502c449eaddff30019a7d399f077b7814bcafabc636829d194c7 as release # TARGETOS is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETOS # TARGETARCH is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETARCH -LABEL maintainer="maintainer@cilium.io" -RUN echo ". /etc/profile.d/bash_completion.sh" >> /etc/bash.bashrc -COPY --from=cilium-envoy /usr/lib/libcilium.so /usr/lib/libcilium.so -COPY --from=cilium-envoy /usr/bin/cilium-envoy /usr/bin/cilium-envoy-starter /usr/bin/ -# When used within the Cilium container, Hubble CLI should target the -# local unix domain socket instead of Hubble Relay. -ENV HUBBLE_SERVER=unix:///var/run/cilium/hubble.sock -COPY --from=hubble /out/${TARGETOS}/${TARGETARCH}/bin/hubble /usr/bin/hubble -COPY --from=hubble /out/linux/bash_completion /etc/bash_completion.d/hubble - -COPY --from=builder /tmp/install/${TARGETOS}/${TARGETARCH} / -WORKDIR /home/cilium -ENV INITSYSTEM="SYSTEMD" -CMD ["/usr/bin/cilium-dbg"] +COPY --link --from=builder /tmp/install/${TARGETOS}/${TARGETARCH} / # # Cilium debug image. diff --git a/images/operator/Dockerfile b/images/operator/Dockerfile index e5aae8f8a3d96..b7f813db74e4b 100644 --- a/images/operator/Dockerfile +++ b/images/operator/Dockerfile @@ -19,13 +19,14 @@ ARG TARGETARCH ARG OPERATOR_VARIANT # MODIFIERS are extra arguments to be passed to make at build time. ARG MODIFIERS +ARG SOURCE_DATE_EPOCH=0 WORKDIR /go/src/github.com/cilium/cilium RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium \ --mount=type=cache,target=/root/.cache \ --mount=type=cache,target=/go/pkg \ - make GOARCH=${TARGETARCH} DESTDIR=/out/${TARGETOS}/${TARGETARCH} ${MODIFIERS} \ + SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH} make GOARCH=${TARGETARCH} DESTDIR=/out/${TARGETOS}/${TARGETARCH} ${MODIFIERS} \ build-container-${OPERATOR_VARIANT} install-container-binary-${OPERATOR_VARIANT} # licenses-all is a "script" that executes "go run" so its ARCH should be set @@ -35,6 +36,8 @@ RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium \ --mount=type=cache,target=/go/pkg \ make GOARCH=${BUILDARCH} licenses-all && mv LICENSE.all /out/${TARGETOS}/${TARGETARCH} +RUN find /out/${TARGETOS}/${TARGETARCH} -depth -execdir touch --no-dereference -a -m -t $(date -u -d @${SOURCE_DATE_EPOCH} +%Y%m%d%H%M.%S) '{}' ';' + # BUILDPLATFORM is an automatic platform ARG enabled by Docker BuildKit. # Represents the plataform where the build is happening, do not mix with # TARGETARCH @@ -54,20 +57,12 @@ RUN --mount=type=bind,readwrite,target=/go/src/github.com/cilium/cilium \ --mount=type=cache,target=/go/pkg \ ./build-gops.sh -FROM ${BASE_IMAGE} as release +FROM quay.io/cilium/operator-generic:v1.15.8@sha256:e77ae6fc8a978f98363cf74d3c883dfaa6454c6e23ec417a60952f29408e2f18 as release # TARGETOS is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETOS # TARGETARCH is an automatic platform ARG enabled by Docker BuildKit. ARG TARGETARCH -ARG OPERATOR_VARIANT -LABEL maintainer="maintainer@cilium.io" -COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -COPY --from=gops /out/${TARGETOS}/${TARGETARCH}/bin/gops /bin/gops -COPY --from=builder /out/${TARGETOS}/${TARGETARCH}/usr/bin/cilium-${OPERATOR_VARIANT} /usr/bin/cilium-${OPERATOR_VARIANT} -COPY --from=builder /out/${TARGETOS}/${TARGETARCH}/LICENSE.all /LICENSE.all -WORKDIR / -ENV GOPS_CONFIG_DIR=/ -CMD ["/usr/bin/cilium-${OPERATOR_VARIANT}"] +COPY --link --from=builder /out/${TARGETOS}/${TARGETARCH} / FROM --platform=${BUILDPLATFORM} ${CILIUM_BUILDER_IMAGE} as debug-tools