-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathbuild-image.sh
More file actions
180 lines (147 loc) · 6.48 KB
/
build-image.sh
File metadata and controls
180 lines (147 loc) · 6.48 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
#!/usr/bin/env bash
#
# SPDX-FileCopyrightText: © Vegard IT GmbH (https://vegardit.com)
# SPDX-FileContributor: Sebastian Thomschke
# SPDX-License-Identifier: Apache-2.0
# SPDX-ArtifactOfProjectHomePage: https://github.com/vegardit/docker-traefik-logrotate
shared_lib="$(dirname "${BASH_SOURCE[0]}")/.shared"
[[ -e $shared_lib ]] || curl -sSfL "https://raw.githubusercontent.com/vegardit/docker-shared/v1/download.sh?_=$(date +%s)" | bash -s v1 "$shared_lib" || exit 1
# shellcheck disable=SC1091 # Not following: $shared_lib/lib/build-image-init.sh was not specified as input
source "$shared_lib/lib/build-image-init.sh"
#################################################
# declare image meta
#################################################
image_repo=${DOCKER_IMAGE_REPO:-vegardit/traefik-logrotate}
base_image=${DOCKER_BASE_IMAGE:-alpine:3}
# matching supported Linux platforms of Traefik docker image https://hub.docker.com/_/traefik/tags?name=latest
platforms="linux/amd64,linux/arm/v6,linux/arm64/v8,linux/ppc64le,linux/riscv64,linux/s390x"
declare -A image_meta=(
[authors]="Vegard IT GmbH (vegardit.com)"
[title]="$image_repo"
[description]="Multi-arch Alpine based image to rotate Traefik access logs"
[source]="$(git config --get remote.origin.url)"
[revision]="$(git rev-parse --short HEAD)"
[version]="$(git rev-parse --short HEAD)"
[created]="$(date -u +'%Y-%m-%dT%H:%M:%SZ')"
)
#################################################
# define tags
#################################################
declare -a tags=()
tags+=("${DOCKER_IMAGE_TAG:-latest}")
#################################################
# decide if multi-arch build
#################################################
if [[ ${DOCKER_PUSH:-} == "true" || ${DOCKER_PUSH_GHCR:-} == "true" ]]; then
build_multi_arch="true"
fi
#################################################
# prepare docker
#################################################
run_step -- docker version
# https://github.com/docker/buildx/#building-multi-platform-images
run_step -- docker buildx version # ensures buildx is enabled
export DOCKER_BUILDKIT=1
export DOCKER_CLI_EXPERIMENTAL=1 # prevents "docker: 'buildx' is not a docker command." in older Docker versions
if [[ ${build_multi_arch:-} == "true" ]]; then
# Use a temporary local registry to work around Docker/Buildx/BuildKit quirks,
# enabling us to build/test multiarch images locally before pushing.
run_step -- start_docker_registry LOCAL_REGISTRY
# Register QEMU emulators so Docker can run and build multi-arch images
run_step "Install QEMU emulators" -- \
docker run --privileged --rm ghcr.io/dockerhub-mirror/tonistiigi__binfmt --install all
fi
# https://docs.docker.com/build/buildkit/configure/#resource-limiting
echo "
[worker.oci]
max-parallelism = 3
" | sudo tee /etc/buildkitd.toml
builder_name="bx-$(date +%s)-$RANDOM"
run_step "Configure buildx builder" -- docker buildx create \
--name "$builder_name" \
--bootstrap \
--config /etc/buildkitd.toml \
--driver-opt network=host `# required for buildx to access the temporary registry` \
--driver docker-container \
--driver-opt image=ghcr.io/dockerhub-mirror/moby__buildkit:latest
trap 'docker buildx rm --force "$builder_name"' EXIT
#################################################
# build the image
#################################################
image_name=image_repo:${tags[0]}
# shellcheck disable=SC2154,SC2046 # base_layer_cache_key is referenced but not assigned / Quote this to prevent word splitting
build_opts=(
--file "image/Dockerfile"
--builder "$builder_name"
--progress=plain
--pull
# using the current date as value for BASE_LAYER_CACHE_KEY, i.e. the base layer cache (that holds system packages with security updates) will be invalidate once per day
--build-arg BASE_LAYER_CACHE_KEY="$base_layer_cache_key"
--build-arg BASE_IMAGE="$base_image"
--build-arg GIT_BRANCH="${GIT_BRANCH:-$(git rev-parse --abbrev-ref HEAD)}"
--build-arg GIT_COMMIT_DATE="$(date -d "@$(git log -1 --format='%at')" --utc +'%Y-%m-%d %H:%M:%S UTC')"
)
for key in "${!image_meta[@]}"; do
build_opts+=(--build-arg "OCI_${key}=${image_meta[$key]}")
if [[ ${build_multi_arch:-} == "true" ]]; then
build_opts+=(--annotation "index:org.opencontainers.image.${key}=${image_meta[$key]}")
fi
done
if [[ ${build_multi_arch:-} == "true" ]]; then
build_opts+=(--push)
build_opts+=(--sbom=true) # https://docs.docker.com/build/metadata/attestations/sbom/#create-sbom-attestations
build_opts+=(--platform "$platforms")
build_opts+=(--tag "$LOCAL_REGISTRY/$image_name")
else
build_opts+=(--output "type=docker,load=true")
build_opts+=(--tag "$image_name")
fi
if [[ $OSTYPE == "cygwin" || $OSTYPE == "msys" ]]; then
project_root=$(cygpath -w "$project_root")
fi
run_step "Building docker image [$image_name]..." -- \
docker buildx build "${build_opts[@]}" "$project_root"
#################################################
# load image into local docker daemon for testing
#################################################
if [[ ${build_multi_arch:-} == "true" ]]; then
run_step "Load image into local daemon for testing" @@ "
docker pull '$LOCAL_REGISTRY/$image_name';
docker tag '$LOCAL_REGISTRY/$image_name' '$image_name'
"
fi
#################################################
# perform security audit
#################################################
if [[ ${DOCKER_AUDIT_IMAGE:-1} == "1" ]]; then
run_step "Auditing docker image [$image_name]" -- \
bash "$shared_lib/cmd/audit-image.sh" "$image_name"
fi
#################################################
# test image
#################################################
run_step "Testing docker image [$image_name]" -- \
docker run --pull=never --rm "$image_name" logrotate --version
#################################################
# push image
#################################################
function regctl() {
run_step "regctl ${*}" -- \
docker run --rm \
-u "$(id -u):$(id -g)" -e HOME -v "$HOME:$HOME" \
-v /etc/docker/certs.d:/etc/docker/certs.d:ro \
--network host `# required to access the temporary registry` \
ghcr.io/regclient/regctl:latest \
--host "reg=$LOCAL_REGISTRY,tls=disabled" \
"${@}"
}
if [[ ${DOCKER_PUSH:-} == "true" ]]; then
for tag in "${tags[@]}"; do
regctl image copy --referrers "$LOCAL_REGISTRY/$image_name" "docker.io/$image_repo:$tag"
done
fi
if [[ ${DOCKER_PUSH_GHCR:-} == "true" ]]; then
for tag in "${tags[@]}"; do
regctl image copy --referrers "$LOCAL_REGISTRY/$image_name" "ghcr.io/$image_repo:$tag"
done
fi