Fold build-tools into this repo
build-tools is the image the pipeline's build pod runs its shell steps in. It was owned by devops-lib, which is an odd home: it is not library code, it is an artefact built by hand and pushed to Harbor, exactly like the mirrors here. devops-lib only ever referenced the result by tag, and it still will. Three deliberate changes from the homelab's version: - Pushed to base-images/build-tools:1, not homelab/. That project is public, so build pods pull it with no credentials — the same reason the language images live there. - FROM the mirrored docker:27-cli rather than Docker Hub, with that tag added to images.txt. Otherwise building the image that exists to remove a Docker Hub dependency would itself depend on Docker Hub. - yq is pinned instead of "releases/latest". An image that resolves a different yq on every build is not reproducible, and that is the kind of drift that surfaces months later as an unexplained pipeline failure. The README gains the build-and-push procedure: the same pod shape as the mirror, with the registry CA mounted into dind so the push is trusted, and DOCKER_BUILDKIT=0, since BuildKit wants to write state under /root/.docker where the push credentials get mounted read-only. Verified the three places that must agree do: images.txt, the README's inlined ConfigMap copy of it, and the Dockerfile's FROM tag. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LEsTefWWifp4ikvhHF5s6N
This commit is contained in:
co-authored by
Claude Opus 5
parent
b38af45c31
commit
2f80cfe288
@@ -1,9 +1,18 @@
|
||||
# devops-base-images (GKE)
|
||||
|
||||
Mirrors minimized base images into Harbor's `base-images` project, so
|
||||
language builds — `devops-lib`'s `buildDocker.groovy` fallback templates —
|
||||
never depend on Docker Hub at build time, and the images that ship are the
|
||||
leanest official variant for each language.
|
||||
Owns every image the build pipeline pulls, in Harbor's `base-images`
|
||||
project:
|
||||
|
||||
- **Mirrored language base images** (`images.txt`), so builds — `devops-lib`'s
|
||||
`buildDocker.groovy` fallback templates — never depend on Docker Hub at
|
||||
build time, and what ships is the leanest official variant per language.
|
||||
- **`build-tools`** (`build-tools.Dockerfile`), the image the build pod runs
|
||||
its own shell steps in.
|
||||
|
||||
Both are built or mirrored by hand from here, and `devops-lib` only ever
|
||||
references the results by tag. `build-tools` lives here rather than in
|
||||
devops-lib because it is the same kind of artefact as the mirrors, and
|
||||
because a Jenkins job cannot build the image its own build pod needs.
|
||||
|
||||
GKE counterpart of the homelab repo of the same name. The manifest and the
|
||||
script are identical; what differs is the registry host and, more
|
||||
@@ -73,6 +82,7 @@ data:
|
||||
maven:3-eclipse-temurin-21-alpine maven:3-eclipse-temurin-21-alpine
|
||||
eclipse-temurin:21-jre-alpine eclipse-temurin:21-jre-alpine
|
||||
php:8.3-cli-alpine php:8.3-cli-alpine
|
||||
docker:27-cli docker:27-cli
|
||||
mirror.sh: |
|
||||
#!/bin/sh
|
||||
set -eu
|
||||
@@ -176,6 +186,98 @@ If the push fails with a certificate error, the mount path is the usual
|
||||
cause: it must be `/etc/docker/certs.d/harbor.35.238.248.203.nip.io/ca.crt`
|
||||
exactly, hostname included, in the dind container.
|
||||
|
||||
## Building `build-tools`
|
||||
|
||||
Do this after the mirror, since it builds `FROM` a mirrored image.
|
||||
|
||||
The pod is the same shape as the mirror pod — privileged dind, the CA
|
||||
mounted so pushes are trusted, a docker-cli sidecar — with the Dockerfile
|
||||
supplied through a ConfigMap. Create it from the file in this repo so the
|
||||
two cannot drift:
|
||||
|
||||
```
|
||||
kubectl -n jenkins create configmap build-tools-src \
|
||||
--from-file=Dockerfile=build-tools.Dockerfile
|
||||
|
||||
cat <<'EOF' | kubectl apply -f -
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: build-tools-build
|
||||
namespace: jenkins
|
||||
spec:
|
||||
restartPolicy: Never
|
||||
containers:
|
||||
- name: docker
|
||||
image: docker:27-dind
|
||||
securityContext:
|
||||
privileged: true
|
||||
env:
|
||||
- name: DOCKER_TLS_CERTDIR
|
||||
value: ""
|
||||
volumeMounts:
|
||||
- name: docker-graph-storage
|
||||
mountPath: /var/lib/docker
|
||||
- name: registry-ca
|
||||
mountPath: /etc/docker/certs.d/harbor.35.238.248.203.nip.io
|
||||
readOnly: true
|
||||
- name: docker-cli
|
||||
image: docker:27-cli
|
||||
command: ["cat"]
|
||||
tty: true
|
||||
env:
|
||||
- name: DOCKER_HOST
|
||||
value: tcp://localhost:2375
|
||||
# The classic builder. BuildKit wants to write its own state under
|
||||
# /root/.docker, which is read-only wherever the push credentials are
|
||||
# mounted as a file — the homelab hit exactly this.
|
||||
- name: DOCKER_BUILDKIT
|
||||
value: "0"
|
||||
volumeMounts:
|
||||
- name: src
|
||||
mountPath: /src
|
||||
volumes:
|
||||
- name: docker-graph-storage
|
||||
emptyDir: {}
|
||||
- name: src
|
||||
configMap:
|
||||
name: build-tools-src
|
||||
- name: registry-ca
|
||||
configMap:
|
||||
name: registry-ca
|
||||
EOF
|
||||
```
|
||||
|
||||
Then log in and build. The tag is deliberate: **bump it rather than
|
||||
overwriting**, because `devops-lib-gcp`'s `dind-pod.yaml` pins this tag and
|
||||
an overwritten tag rolls out silently on the next pod start.
|
||||
|
||||
```
|
||||
kubectl wait --for=condition=Ready pod/build-tools-build -n jenkins --timeout=180s
|
||||
kubectl exec -it -n jenkins build-tools-build -c docker-cli -- sh -c '
|
||||
for i in $(seq 1 30); do docker info >/dev/null 2>&1 && break; sleep 2; done
|
||||
docker login harbor.35.238.248.203.nip.io'
|
||||
|
||||
kubectl exec -n jenkins build-tools-build -c docker-cli -- sh -c '
|
||||
cd /src &&
|
||||
docker build -t harbor.35.238.248.203.nip.io/base-images/build-tools:1 . &&
|
||||
docker push harbor.35.238.248.203.nip.io/base-images/build-tools:1'
|
||||
|
||||
kubectl delete pod build-tools-build -n jenkins
|
||||
kubectl delete configmap build-tools-src -n jenkins
|
||||
```
|
||||
|
||||
Verify it has what the stages expect:
|
||||
|
||||
```
|
||||
kubectl run bt --rm -it --restart=Never \
|
||||
--image=harbor.35.238.248.203.nip.io/base-images/build-tools:1 \
|
||||
-- sh -c 'git --version && yq --version && python3 -V && bash --version | head -1'
|
||||
```
|
||||
|
||||
That pull needs no credentials — `base-images` is public — and the nodes
|
||||
already trust the CA, which is what makes an ordinary pod able to run it.
|
||||
|
||||
## Adding a new image or updating a version
|
||||
|
||||
Add a line to `images.txt`, commit, push, then re-run step 3 — the
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
# The docker-cli image the pipeline's build pod runs its shell steps in.
|
||||
#
|
||||
# Bakes in everything the stages need — git, yq, bash, python3 with pip and
|
||||
# venv for runHooks' python hooks, curl — so nothing is installed on demand
|
||||
# on every single build. Installing tools per build was slow and, worse,
|
||||
# quietly undermined reproducibility: a build's behaviour depended on
|
||||
# whatever the package mirror served that morning.
|
||||
#
|
||||
# Lives here rather than in devops-lib because it is the same kind of thing
|
||||
# as everything else in this repo: an image built by hand, occasionally,
|
||||
# and pushed into Harbor for builds to pull. devops-lib only references the
|
||||
# result by tag.
|
||||
#
|
||||
# Built and pushed manually — never by a Jenkins job, which would need this
|
||||
# image to already exist in order to run. See README.md.
|
||||
#
|
||||
# Pushed to base-images, not homelab: that project is public, so build pods
|
||||
# pull this with no credentials at all, which is the same reason the
|
||||
# mirrored language images live there.
|
||||
#
|
||||
# The tag is pinned explicitly by devops-lib-gcp's dind-pod.yaml, so
|
||||
# rebuilding this does not roll anything out until that pin is bumped too.
|
||||
# Bump the tag when this file changes; do not overwrite an existing tag.
|
||||
FROM harbor.35.238.248.203.nip.io/base-images/docker:27-cli
|
||||
|
||||
# Pinned rather than the homelab's "releases/latest": an image that resolves
|
||||
# a different yq every time it is built is not reproducible, and this is
|
||||
# exactly the sort of thing that changes under you months later. Bump it
|
||||
# deliberately.
|
||||
ARG YQ_VERSION=v4.44.3
|
||||
|
||||
RUN apk add --no-cache git bash python3 py3-pip py3-virtualenv curl \
|
||||
&& curl -sL -o /usr/local/bin/yq \
|
||||
"https://github.com/mikefarah/yq/releases/download/${YQ_VERSION}/yq_linux_amd64" \
|
||||
&& chmod +x /usr/local/bin/yq \
|
||||
&& yq --version \
|
||||
&& git --version
|
||||
@@ -25,3 +25,8 @@ python:3.12-alpine python:3.12-alpine
|
||||
maven:3-eclipse-temurin-21-alpine maven:3-eclipse-temurin-21-alpine
|
||||
eclipse-temurin:21-jre-alpine eclipse-temurin:21-jre-alpine
|
||||
php:8.3-cli-alpine php:8.3-cli-alpine
|
||||
# Not a language runtime: this is what build-tools.Dockerfile builds FROM.
|
||||
# Mirrored for the same reason as everything else here — so building the
|
||||
# build image does not depend on Docker Hub either. Keep the tag in step
|
||||
# with the FROM line in build-tools.Dockerfile.
|
||||
docker:27-cli docker:27-cli
|
||||
|
||||
Reference in New Issue
Block a user