Skip to content

Commit c8f5895

Browse files
VinozzZrobbkidd
andauthored
fix(ci): publish multi-arch image to multiple registry (#1709)
## Which problem is this PR solving? - #1708 `ko` does produce a multi-arch image, but `docker push` doesn't push a multi-arch image. ## Short description of the changes This PR uses `crane cp` which has multi-arch support to copy multi-arch image manifests between registries. - wire up `crane` as a docker build dependency - reorganize `build_docker.sh` to use a `PRIMARY_DOCKER_REPO` environment variable to designate a prime destination for a particular build - if left unset, `ko.local` is the default and the image will only be built and "published" to the local registry - if set, the image build will be published to the given registry target along with the appropriate tags as determined by the build script - `COPY_DOCKER_REPOS` replaces `KO_DOCKER_REPOS` - a comma-separated list of **additional** registry repos to copy the image published to `PRIMARY_DOCKER_REPO` - same collection of tags will be applied to the copies --------- Co-authored-by: Robb Kidd <[email protected]>
1 parent 1406954 commit c8f5895

File tree

4 files changed

+67
-50
lines changed

4 files changed

+67
-50
lines changed

.circleci/config.yml

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,12 @@ commands:
5656
- restore_cache:
5757
keys:
5858
- v2-googleko-{{ checksum "Makefile" }}
59-
- run: make ko
59+
- run: make ko crane
6060
- save_cache:
6161
key: v2-googleko-{{ checksum "Makefile" }}
6262
paths:
6363
- ./ko
64+
- ./crane
6465

6566
jobs:
6667
test:
@@ -231,7 +232,7 @@ jobs:
231232
- run:
232233
name: build and publish to private ECR
233234
command: |
234-
export KO_DOCKER_REPO="${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com"
235+
export PRIMARY_DOCKER_REPO="${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com"
235236
./build-docker.sh
236237
237238
publish_docker_to_ecr_sippycup:
@@ -255,7 +256,7 @@ jobs:
255256
- run:
256257
name: publish docker image to aws ecr
257258
environment:
258-
KO_DOCKER_REPO: 017118846235.dkr.ecr.us-east-1.amazonaws.com
259+
PRIMARY_DOCKER_REPO: 017118846235.dkr.ecr.us-east-1.amazonaws.com
259260
command: ./build-docker.sh
260261

261262
publish_docker_to_all_public_registries:
@@ -280,7 +281,8 @@ jobs:
280281
- run:
281282
name: build once and publish to all public registries
282283
command: |
283-
export KO_DOCKER_REPOS="${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com,honeycombio,public.ecr.aws/honeycombio,ghcr.io/honeycombio/refinery"
284+
export PRIMARY_DOCKER_REPO="honeycombio"
285+
export COPY_DOCKER_REPOS="${AWS_ACCOUNT_ID}.dkr.ecr.us-east-1.amazonaws.com,public.ecr.aws/honeycombio,ghcr.io/honeycombio/refinery"
284286
echo "${DOCKER_PASSWORD}" | docker login -u "${DOCKER_USERNAME}" --password-stdin
285287
echo "${GITHUB_TOKEN}" | docker login ghcr.io -u "${GITHUB_USERNAME}" --password-stdin
286288
./build-docker.sh

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,6 @@ dockerize*
3030
# cache for ko-build/
3131
ko-cache/
3232
ko
33-
ko*.tar.gz
33+
ko*.tar.gz
34+
crane
35+
crane*.tar.gz

Makefile

Lines changed: 31 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,13 @@ test_all: test_results wait_for_redis
2727
test_results:
2828
@mkdir -p test_results
2929

30-
local_image: export KO_DOCKER_REPO=ko.local
30+
local_image: export PRIMARY_DOCKER_REPO=ko.local
3131
local_image: export CIRCLE_TAG=$(shell git describe --always --match "v[0-9]*" --tags)
3232
local_image: export CIRCLE_BRANCH=$(shell git rev-parse --abbrev-ref HEAD)
3333
local_image: export CIRCLE_SHA1=$(shell git rev-parse HEAD)
34-
local_image: export CIRCLE_BUILD_NUM=''
3534
local_image: export SOURCE_DATE_EPOCH=$(call __latest_modification_time)
3635
#: build the release image locally, available as "ko.local/refinery:<commit>"
37-
local_image:
36+
local_image: ko crane
3837
./build-docker.sh
3938

4039
.PHONY: wait_for_redis
@@ -51,14 +50,14 @@ HOST_OS := $(shell uname -s | tr A-Z a-z)
5150
# You can override this version from an environment variable.
5251
KO_VERSION ?= 0.11.2
5352
KO_RELEASE_ASSET := ko_${KO_VERSION}_${HOST_OS}_x86_64.tar.gz
54-
# ensure the dockerize command is available
53+
# ensure the ko command is available
5554
ko: ko_${KO_VERSION}.tar.gz
5655
tar xzvmf $< ko
5756
chmod u+x ./ko
5857

5958
ko_${KO_VERSION}.tar.gz:
6059
@echo
61-
@echo "+++ Retrieving dockerize tool for Redis readiness check."
60+
@echo "+++ Retrieving ko tool for container building."
6261
@echo
6362
# make sure that file is available
6463
ifeq (, $(shell command -v file))
@@ -71,6 +70,29 @@ endif
7170
&& file ko_tmp.tar.gz | grep --silent gzip \
7271
&& mv ko_tmp.tar.gz $@ || (echo "Failed to download ko. Got:"; cat ko_tmp.tar.gz ; echo "" ; exit 1)
7372

73+
# You can override this version from an environment variable.
74+
CRANE_VERSION ?= 0.19.1
75+
CRANE_RELEASE_ASSET := go-containerregistry_${HOST_OS}_x86_64.tar.gz
76+
# ensure the crane command is available
77+
crane: crane_${CRANE_VERSION}.tar.gz
78+
tar xzvmf $< crane
79+
chmod u+x ./crane
80+
81+
crane_${CRANE_VERSION}.tar.gz:
82+
@echo
83+
@echo "+++ Retrieving crane tool for container registry operations."
84+
@echo
85+
# make sure that file is available
86+
ifeq (, $(shell command -v file))
87+
sudo apt-get update
88+
sudo apt-get -y install file
89+
endif
90+
curl --location --silent --show-error \
91+
--output crane_tmp.tar.gz \
92+
https://github.com/google/go-containerregistry/releases/download/v${CRANE_VERSION}/${CRANE_RELEASE_ASSET} \
93+
&& file crane_tmp.tar.gz | grep --silent gzip \
94+
&& mv crane_tmp.tar.gz $@ || (echo "Failed to download crane. Got:"; cat crane_tmp.tar.gz ; echo "" ; exit 1)
95+
7496
__latest_modification_time := $(strip $(if $(shell git diff --quiet && echo $$?), \
7597
$(shell git log --max-count=1 --pretty=format:"%ct"), \
7698
$(shell git status --short --untracked-files=no --no-column | cut -w -f 3 | xargs ls -ltr -D "%s" | tail -n 1 | cut -w -f 6)))
@@ -105,6 +127,10 @@ endif
105127
clean:
106128
rm -f dockerize.tar.gz
107129
rm -f dockerize
130+
rm -f ko_*.tar.gz
131+
rm -f ko
132+
rm -f crane_*.tar.gz
133+
rm -f crane
108134
rm -rf test_results
109135

110136

build-docker.sh

Lines changed: 27 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -63,54 +63,41 @@ unset GOARCH
6363
export GOFLAGS="-ldflags=-X=main.BuildID=$VERSION"
6464
export SOURCE_DATE_EPOCH=${SOURCE_DATE_EPOCH:-$(make latest_modification_time)}
6565

66-
# If KO_DOCKER_REPOS is set (comma-separated list), build once and push to multiple registries
67-
if [[ -n "${KO_DOCKER_REPOS:-}" ]]; then
68-
# Build the image once to a local registry first
69-
LOCAL_REPO="ko.local"
70-
ORIGINAL_REPO="${KO_DOCKER_REPO:-ko.local}"
71-
export KO_DOCKER_REPO="$LOCAL_REPO"
72-
73-
echo "Building image locally with ko for multi-registry push..."
74-
# shellcheck disable=SC2086
75-
IMAGE_REF=$(./ko publish \
76-
--tags "${TAGS}" \
77-
--base-import-paths \
78-
--platform "linux/amd64,linux/arm64" \
79-
--image-label org.opencontainers.image.source=https://github.com/honeycombio/refinery \
80-
--image-label org.opencontainers.image.licenses=Apache-2.0 \
81-
--image-label org.opencontainers.image.revision=${GIT_COMMIT} \
82-
./cmd/refinery)
83-
84-
echo "Built image: $IMAGE_REF"
85-
echo "Pushing to multiple registries: $KO_DOCKER_REPOS"
86-
87-
IFS=',' read -ra REPOS <<< "$KO_DOCKER_REPOS"
66+
# Build the image once, either to a remote registry designated by PRIMARY_DOCKER_REPO
67+
# or to the local repository as "ko.local/refinery:<tags>" if PRIMARY_DOCKER_REPO is not set.
68+
export KO_DOCKER_REPO="${PRIMARY_DOCKER_REPO:-ko.local}"
69+
70+
echo "Building image locally with ko for multi-registry push..."
71+
# shellcheck disable=SC2086
72+
IMAGE_REF=$(./ko publish \
73+
--tags "${TAGS}" \
74+
--base-import-paths \
75+
--platform "linux/amd64,linux/arm64" \
76+
--image-label org.opencontainers.image.source=https://github.com/honeycombio/refinery \
77+
--image-label org.opencontainers.image.licenses=Apache-2.0 \
78+
--image-label org.opencontainers.image.revision=${GIT_COMMIT} \
79+
./cmd/refinery)
80+
81+
echo "Built image: ${IMAGE_REF}"
82+
83+
# If COPY_DOCKER_REPOS is set, copy the built image to each of the listed registries.
84+
# This is a comma-separated list of registry/repo names, e.g.
85+
# "public.ecr.aws/honeycombio,ghcr.io/honeycombio/refinery"
86+
if [[ -n "${COPY_DOCKER_REPOS:-}" ]]; then
87+
echo "Pushing to multiple registries: ${COPY_DOCKER_REPOS}"
88+
89+
IFS=',' read -ra REPOS <<< "$COPY_DOCKER_REPOS"
8890
for REPO in "${REPOS[@]}"; do
8991
REPO=$(echo "$REPO" | xargs) # trim whitespace
9092
echo "Tagging and pushing to: $REPO"
91-
93+
9294
# Tag for each tag in the TAGS list
9395
IFS=',' read -ra TAG_LIST <<< "$TAGS"
9496
for TAG in "${TAG_LIST[@]}"; do
9597
TAG=$(echo "$TAG" | xargs) # trim whitespace
9698
TARGET_IMAGE="$REPO/refinery:$TAG"
97-
echo "Tagging $IMAGE_REF as $TARGET_IMAGE"
98-
docker tag "$IMAGE_REF" "$TARGET_IMAGE"
99-
echo "Pushing $TARGET_IMAGE"
100-
docker push "$TARGET_IMAGE"
99+
echo "Copying $IMAGE_REF to $TARGET_IMAGE"
100+
./crane copy "$IMAGE_REF" "$TARGET_IMAGE"
101101
done
102102
done
103-
else
104-
# Single registry mode - use ko publish directly
105-
export KO_DOCKER_REPO=${KO_DOCKER_REPO:-ko.local}
106-
echo "Publishing to single registry: $KO_DOCKER_REPO"
107-
# shellcheck disable=SC2086
108-
./ko publish \
109-
--tags "${TAGS}" \
110-
--base-import-paths \
111-
--platform "linux/amd64,linux/arm64" \
112-
--image-label org.opencontainers.image.source=https://github.com/honeycombio/refinery \
113-
--image-label org.opencontainers.image.licenses=Apache-2.0 \
114-
--image-label org.opencontainers.image.revision=${GIT_COMMIT} \
115-
./cmd/refinery
116103
fi

0 commit comments

Comments
 (0)