Skip to content

Commit 9bc2a4d

Browse files
committed
add docker build image for local dev.
1 parent d4dbbdb commit 9bc2a4d

File tree

1 file changed

+219
-0
lines changed

1 file changed

+219
-0
lines changed

hack/build-image-docker.sh

Lines changed: 219 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,219 @@
1+
#!/usr/bin/env bash
2+
3+
# Copyright 2025 The KCP Authors.
4+
#
5+
# Licensed under the Apache License, Version 2.0 (the "License");
6+
# you may not use this file except in compliance with the License.
7+
# You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing, software
12+
# distributed under the License is distributed on an "AS IS" BASIS,
13+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
# See the License for the specific language governing permissions and
15+
# limitations under the License.
16+
17+
# Build container images for KCP using Docker
18+
#
19+
# This script builds container images using Docker (with or without buildx).
20+
#
21+
# Usage examples:
22+
# # Build locally with default settings (uses current git commit hash)
23+
# ./hack/build-image-docker.sh
24+
#
25+
# # Build locally with custom repository name
26+
# REPOSITORY=my-registry/kcp ./hack/build-image-docker.sh
27+
#
28+
# # Build locally without pushing (dry run)
29+
# DRY_RUN=1 ./hack/build-image-docker.sh
30+
#
31+
# # Build for specific architectures only
32+
# ARCHITECTURES="amd64" ./hack/build-image-docker.sh
33+
#
34+
# Environment variables:
35+
# REPOSITORY - Override default repository (default: ghcr.io/kcp-dev/kcp)
36+
# ARCHITECTURES - Space-separated list of architectures (default: "amd64 arm64")
37+
# DRY_RUN - Set to any value to build locally without pushing
38+
# KCP_GHCR_USERNAME/KCP_GHCR_PASSWORD - Registry credentials for pushing
39+
#
40+
# Build tool support:
41+
# - docker + buildx: Multi-arch support with intelligent platform handling
42+
# - docker only: Single architecture fallback
43+
44+
set -euo pipefail
45+
46+
# make git available
47+
if ! [ -x "$(command -v git)" ]; then
48+
echo "Installing git ..."
49+
yum install -y git
50+
fi
51+
52+
# Check if docker is available
53+
if ! [ -x "$(command -v docker)" ]; then
54+
echo "Error: Docker is not available"
55+
exit 1
56+
fi
57+
58+
echo "Using docker for container builds"
59+
# Check if buildx is available for multi-arch builds
60+
if docker buildx version >/dev/null 2>&1; then
61+
echo "Docker buildx is available for multi-arch builds"
62+
DOCKER_BUILDX=true
63+
else
64+
echo "Docker buildx not available, falling back to single-arch builds"
65+
DOCKER_BUILDX=false
66+
fi
67+
68+
69+
if [ -z "${REPOSITORY:-}" ]; then
70+
echo "Error: REPOSITORY environment variable is required"
71+
exit 1
72+
fi
73+
repository=$REPOSITORY
74+
architectures=${ARCHITECTURES:-"amd64 arm64"}
75+
76+
# when building locally, just tag with the current HEAD hash.
77+
version="$(git rev-parse --short HEAD)"
78+
branchName=""
79+
80+
# deduce the tag from the Prow job metadata
81+
if [ -n "${PULL_BASE_REF:-}" ]; then
82+
version="$(git tag --list "$PULL_BASE_REF")"
83+
84+
if [ -z "$version" ]; then
85+
# if the base ref did not point to a tag, it's a branch name
86+
version="$(git rev-parse --short "$PULL_BASE_REF")"
87+
branchName="$PULL_BASE_REF"
88+
else
89+
# If PULL_BASE_REF is a tag, there is no branch available locally, plus
90+
# there is no guarantee that vX.Y.Z is tagged _only_ in the release-X.Y
91+
# branch; because of this we have to deduce the branch name from the tag
92+
branchName="$(echo "$version" | sed -E 's/^v([0-9]+)\.([0-9]+)\..*/release-\1.\2/')"
93+
fi
94+
fi
95+
96+
# Prefix with "pr-" if not on a tag or branch
97+
if [ -n "${PULL_NUMBER:-}" ]; then
98+
version="pr-$PULL_NUMBER-$version"
99+
repository="$repository-prs"
100+
fi
101+
102+
image="$repository:$version"
103+
echo "Building container image $image ..."
104+
105+
# Function to build images with docker buildx
106+
build_with_docker_buildx() {
107+
echo "Building multi-arch image $image ..."
108+
109+
# Create platforms string for buildx
110+
platforms=""
111+
for arch in $architectures; do
112+
if [ -n "$platforms" ]; then
113+
platforms="$platforms,linux/$arch"
114+
else
115+
platforms="linux/$arch"
116+
fi
117+
done
118+
119+
# For push builds, use multi-platform; for local builds, build per arch
120+
if [ -z "${DRY_RUN:-}" ]; then
121+
# Building for push - use multi-platform with --push
122+
docker buildx build \
123+
--file Dockerfile \
124+
--tag "$image" \
125+
--platform "$platforms" \
126+
--build-arg "TARGETOS=linux" \
127+
--push \
128+
.
129+
else
130+
# For local/dry-run builds, build each architecture separately with --load
131+
for arch in $architectures; do
132+
fullTag="$image-$arch"
133+
echo "Building $fullTag ..."
134+
docker buildx build \
135+
--file Dockerfile \
136+
--tag "$fullTag" \
137+
--platform "linux/$arch" \
138+
--build-arg "TARGETOS=linux" \
139+
--build-arg "TARGETARCH=$arch" \
140+
--load \
141+
.
142+
done
143+
# Tag the first architecture as the main image for local use
144+
first_arch=$(echo $architectures | cut -d' ' -f1)
145+
docker tag "$image-$first_arch" "$image"
146+
fi
147+
}
148+
149+
# Function to build images with regular docker (single arch only)
150+
build_with_docker() {
151+
# Use only the first architecture for regular docker
152+
arch=$(echo $architectures | cut -d' ' -f1)
153+
fullTag="$image-$arch"
154+
155+
echo "Building single-arch image $fullTag (docker without buildx) ..."
156+
docker build \
157+
--file Dockerfile \
158+
--tag "$fullTag" \
159+
--platform "linux/$arch" \
160+
--build-arg "TARGETOS=linux" \
161+
--build-arg "TARGETARCH=$arch" \
162+
.
163+
164+
# Tag it as the main image too
165+
docker tag "$fullTag" "$image"
166+
}
167+
168+
# Build images based on available docker features
169+
if [ "$DOCKER_BUILDX" = true ]; then
170+
build_with_docker_buildx
171+
else
172+
build_with_docker
173+
fi
174+
175+
# Additionally to an image tagged with the Git tag, we also
176+
# release images tagged with the current branch name, which
177+
# is somewhere between a blanket "latest" tag and a specific
178+
# tag.
179+
if [ -n "$branchName" ] && [ -z "${PULL_NUMBER:-}" ]; then
180+
branchImage="$repository:$branchName"
181+
182+
if [ "$DOCKER_BUILDX" = true ]; then
183+
echo "Tagging multi-arch image as $branchImage ..."
184+
docker tag "$image" "$branchImage"
185+
else
186+
echo "Tagging single-arch image as $branchImage ..."
187+
docker tag "$image" "$branchImage"
188+
fi
189+
fi
190+
191+
# push images, except in dry runs
192+
if [ -z "${DRY_RUN:-}" ]; then
193+
echo "Logging into GHCR ..."
194+
195+
if [ "$DOCKER_BUILDX" = true ]; then
196+
# buildx with --push already pushed during build
197+
echo "Images already pushed during buildx build"
198+
else
199+
# Regular docker - need to login and push
200+
if [ -n "${GHCR_USERNAME:-}" ] && [ -n "${GHCR_PASSWORD:-}" ]; then
201+
echo "$GHCR_PASSWORD" | docker login ghcr.io -u "$GHCR_USERNAME" --password-stdin
202+
else
203+
echo "Skipping login (GHCR_USERNAME/GHCR_PASSWORD not provided)"
204+
fi
205+
206+
echo "Pushing images ..."
207+
docker push "$image"
208+
209+
if [ -n "${branchImage:-}" ]; then
210+
docker push "$branchImage"
211+
212+
213+
fi
214+
fi
215+
else
216+
echo "Not pushing images because \$DRY_RUN is set."
217+
fi
218+
219+
echo "Done."

0 commit comments

Comments
 (0)