docker-publish: use BuildKit (buildx) instead of legacy builder
The runners share one host Docker daemon across replicas; the legacy builder corrupts layers under that concurrency. buildx builds in an isolated buildkitd container. buildx is installed as a static binary, keeping the no-marketplace-actions property. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
8b0ef6d709
commit
f2a58b2fb3
1 changed files with 45 additions and 12 deletions
|
|
@ -1,9 +1,15 @@
|
|||
name: Build & publish Docker image
|
||||
description: >-
|
||||
Build a Docker image and push it to this Forgejo instance's container
|
||||
registry. Reimplements docker/login-action + docker/metadata-action +
|
||||
docker/build-push-action in plain shell using the docker CLI — no
|
||||
marketplace actions are fetched or run.
|
||||
Build a Docker image with BuildKit (buildx) and push it to this Forgejo
|
||||
instance's container registry. Reimplements docker/login-action +
|
||||
docker/metadata-action + docker/setup-buildx-action + docker/build-push-action
|
||||
in plain shell using the docker CLI and a statically-installed buildx plugin —
|
||||
no marketplace actions are fetched or run.
|
||||
|
||||
BuildKit (not the legacy builder) is required: the runners share one host
|
||||
Docker daemon across replicas, and the legacy builder corrupts layers under
|
||||
that concurrency ("failed to get layer ... layer does not exist"). buildx
|
||||
builds in an isolated buildkitd container, which is robust against it.
|
||||
|
||||
inputs:
|
||||
context:
|
||||
|
|
@ -61,6 +67,30 @@ runs:
|
|||
fi
|
||||
docker --version
|
||||
|
||||
# --- Ensure the buildx plugin exists (static binary, not a marketplace action) ---
|
||||
if ! docker buildx version >/dev/null 2>&1; then
|
||||
case "$(uname -m)" in
|
||||
x86_64) BX_ARCH=amd64 ;;
|
||||
aarch64|arm64) BX_ARCH=arm64 ;;
|
||||
*) BX_ARCH="$(uname -m)" ;;
|
||||
esac
|
||||
mkdir -p /usr/local/lib/docker/cli-plugins
|
||||
curl -fsSL --retry 3 --retry-connrefused \
|
||||
"https://github.com/docker/buildx/releases/download/v0.19.3/buildx-v0.19.3.linux-${BX_ARCH}" \
|
||||
-o /usr/local/lib/docker/cli-plugins/docker-buildx
|
||||
chmod +x /usr/local/lib/docker/cli-plugins/docker-buildx
|
||||
fi
|
||||
docker buildx version
|
||||
|
||||
# A host-networked buildkit builder so it can reach the registry on 127.0.0.1
|
||||
# (buildkit treats loopback registries as insecure/HTTP automatically). A fixed
|
||||
# name lets concurrent jobs share one builder and its cache; the inspect||create
|
||||
# guard tolerates the create race between simultaneous jobs.
|
||||
docker buildx inspect ci >/dev/null 2>&1 \
|
||||
|| docker buildx create --name ci --driver docker-container --driver-opt network=host >/dev/null 2>&1 \
|
||||
|| true
|
||||
docker buildx use ci
|
||||
|
||||
# --- Resolve the registry host (canonical form of the block copy-pasted across repos) ---
|
||||
host="${INPUT_REGISTRY_HOST:-${CONTAINER_REGISTRY_HOST:-$SERVER_URL}}"
|
||||
host="${host#https://}"; host="${host#http://}"; host="${host%/}"
|
||||
|
|
@ -91,16 +121,19 @@ runs:
|
|||
[ -n "$a" ] && extra+=( --build-arg "$a" )
|
||||
done <<< "${INPUT_BUILD_ARGS}"
|
||||
|
||||
# --- Build ---
|
||||
docker build "${extra[@]}" \
|
||||
# --- Log in before building so buildx can push directly (skipped on PRs) ---
|
||||
if [ "${INPUT_PUSH}" = "true" ]; then
|
||||
printf '%s' "${INPUT_TOKEN}" | docker login "$host" -u "$OWNER" --password-stdin
|
||||
output=( --push )
|
||||
else
|
||||
# Pull-request builds validate the Dockerfile without producing/pushing an image.
|
||||
output=()
|
||||
fi
|
||||
|
||||
# --- Build (and push when requested) with BuildKit ---
|
||||
docker buildx build "${extra[@]}" "${output[@]}" \
|
||||
--label "org.opencontainers.image.source=${SERVER_URL}/${REPO}" \
|
||||
--label "org.opencontainers.image.revision=${SHA}" \
|
||||
--label "org.opencontainers.image.created=$(date -u +'%Y-%m-%dT%H:%M:%SZ')" \
|
||||
"${tags[@]}" \
|
||||
"${INPUT_CONTEXT}"
|
||||
|
||||
# --- Push (skipped on pull requests by passing push: false) ---
|
||||
if [ "${INPUT_PUSH}" = "true" ]; then
|
||||
printf '%s' "${INPUT_TOKEN}" | docker login "$host" -u "$OWNER" --password-stdin
|
||||
docker push --all-tags "$image"
|
||||
fi
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue