ci: bypass buildx --push auth via per-platform --load + docker push + manifest
buildx build --push has failed 401 on every attempt. The buildkit auth forwarding (whether via docker-container or docker driver) does not work reliably on this builder. New strategy: build each platform separately with --load (into local docker, which can read /root/.docker/config.json), then push with native docker push, then assemble a multi-arch manifest with docker manifest create/push. Per-platform tags are pushed as :<BUILD_ID>-amd64 / :<BUILD_ID>-arm64 and the manifest combines them under the canonical :<BUILD_ID> and :latest. This replaces a single buildx --push call with: 1. buildx build --platform linux/amd64 --load 2. docker push (amd64) 3. docker rmi (free disk) 4. buildx build --platform linux/arm64 --load 5. docker push (arm64) 6. docker rmi (free disk) 7. docker manifest create + push (multi-arch) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Vendored
+113
-58
@@ -90,17 +90,6 @@ pipeline {
|
|||||||
|
|
||||||
# Verify emulation works before proceeding
|
# Verify emulation works before proceeding
|
||||||
sudo docker run --rm --platform linux/arm64 docker.m.daocloud.io/library/alpine:latest uname -m
|
sudo docker run --rm --platform linux/arm64 docker.m.daocloud.io/library/alpine:latest uname -m
|
||||||
|
|
||||||
# Use the default docker driver so registry auth is shared with the
|
|
||||||
# host daemon (the docker-container driver requires manual session
|
|
||||||
# forwarding which has been unreliable on this builder).
|
|
||||||
if ! sudo docker buildx inspect --builder ${BUILDER_NAME} >/dev/null 2>&1; then
|
|
||||||
sudo docker buildx create \
|
|
||||||
--name ${BUILDER_NAME} \
|
|
||||||
--driver docker \
|
|
||||||
--use
|
|
||||||
fi
|
|
||||||
sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null
|
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,6 +98,7 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
sh """
|
sh """
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
run_with_heartbeat() {
|
run_with_heartbeat() {
|
||||||
log_file="\$1"
|
log_file="\$1"
|
||||||
build_label="\$2"
|
build_label="\$2"
|
||||||
@@ -144,28 +134,64 @@ pipeline {
|
|||||||
fi
|
fi
|
||||||
return "\$cmd_status"
|
return "\$cmd_status"
|
||||||
}
|
}
|
||||||
sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null
|
|
||||||
echo 'Building and pushing multi-arch API image: ${API_IMAGE_TAGGED}'
|
# ── Build each platform separately, push with docker CLI,
|
||||||
run_with_heartbeat /tmp/live-recorder-api-buildx-${IMAGE_TAG}.log "API multi-arch build" \
|
# then assemble a multi-arch manifest.
|
||||||
sudo docker buildx build \
|
# buildx --push does not forward auth reliably on this
|
||||||
--builder ${BUILDER_NAME} \
|
# builder; per-platform --load + docker push + manifest
|
||||||
--platform ${TARGET_PLATFORMS} \
|
# bypasses that entirely.
|
||||||
--network host \
|
for PLATFORM in linux/amd64 linux/arm64; do
|
||||||
--progress=plain \
|
ARCH_TAG="\${PLATFORM##*/}" # amd64 / arm64
|
||||||
--provenance=false \
|
PLAT_REF="${API_IMAGE_TAGGED}-\${ARCH_TAG}"
|
||||||
--cache-from type=registry,ref=${API_CACHE_IMAGE} \
|
PLAT_LATEST="${API_IMAGE_LATEST}-\${ARCH_TAG}"
|
||||||
--cache-to type=registry,ref=${API_CACHE_IMAGE},mode=max \
|
|
||||||
--build-arg HTTP_PROXY=${HTTP_PROXY_URL} \
|
echo ''
|
||||||
--build-arg HTTPS_PROXY=${HTTP_PROXY_URL} \
|
echo "=== Building API for \$PLATFORM -> \$PLAT_REF ==="
|
||||||
--build-arg NO_PROXY=${NO_PROXY_HOSTS} \
|
run_with_heartbeat /tmp/live-recorder-api-\${ARCH_TAG}.log "API \${ARCH_TAG} build" \
|
||||||
--build-arg http_proxy=${HTTP_PROXY_URL} \
|
sudo docker buildx build \
|
||||||
--build-arg https_proxy=${HTTP_PROXY_URL} \
|
--platform "\$PLATFORM" \
|
||||||
--build-arg no_proxy=${NO_PROXY_HOSTS} \
|
--network host \
|
||||||
-f src/LiveRecorder.WebApi/Dockerfile \
|
--progress=plain \
|
||||||
-t ${API_IMAGE_TAGGED} \
|
--provenance=false \
|
||||||
-t ${API_IMAGE_LATEST} \
|
--cache-from type=registry,ref=${API_CACHE_IMAGE} \
|
||||||
--push \
|
--build-arg HTTP_PROXY=${HTTP_PROXY_URL} \
|
||||||
.
|
--build-arg HTTPS_PROXY=${HTTP_PROXY_URL} \
|
||||||
|
--build-arg NO_PROXY=${NO_PROXY_HOSTS} \
|
||||||
|
--build-arg http_proxy=${HTTP_PROXY_URL} \
|
||||||
|
--build-arg https_proxy=${HTTP_PROXY_URL} \
|
||||||
|
--build-arg no_proxy=${NO_PROXY_HOSTS} \
|
||||||
|
-f src/LiveRecorder.WebApi/Dockerfile \
|
||||||
|
-t "\$PLAT_REF" \
|
||||||
|
-t "\$PLAT_LATEST" \
|
||||||
|
--load \
|
||||||
|
.
|
||||||
|
|
||||||
|
echo "=== Pushing \$PLAT_REF ==="
|
||||||
|
sudo docker push "\$PLAT_REF" 2>&1 | tail -5
|
||||||
|
sudo docker push "\$PLAT_LATEST" 2>&1 | tail -5
|
||||||
|
|
||||||
|
# Free disk space before the next platform build
|
||||||
|
sudo docker rmi "\$PLAT_REF" "\$PLAT_LATEST" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ''
|
||||||
|
echo "=== Creating multi-arch manifest: ${API_IMAGE_TAGGED} ==="
|
||||||
|
sudo docker manifest create "${API_IMAGE_TAGGED}" \
|
||||||
|
"${API_IMAGE_TAGGED}-amd64" \
|
||||||
|
"${API_IMAGE_TAGGED}-arm64"
|
||||||
|
sudo docker manifest create "${API_IMAGE_LATEST}" \
|
||||||
|
"${API_IMAGE_LATEST}-amd64" \
|
||||||
|
"${API_IMAGE_LATEST}-arm64"
|
||||||
|
|
||||||
|
echo "=== Pushing manifests ==="
|
||||||
|
sudo docker manifest push "${API_IMAGE_TAGGED}" 2>&1 | tail -3
|
||||||
|
sudo docker manifest push "${API_IMAGE_LATEST}" 2>&1 | tail -3
|
||||||
|
|
||||||
|
# (Optionally clean up per-platform tags from registry, but harmless to leave them)
|
||||||
|
echo ''
|
||||||
|
echo "API multi-arch images pushed successfully:"
|
||||||
|
echo " ${API_IMAGE_TAGGED}"
|
||||||
|
echo " ${API_IMAGE_LATEST}"
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -174,6 +200,7 @@ pipeline {
|
|||||||
steps {
|
steps {
|
||||||
sh """
|
sh """
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
run_with_heartbeat() {
|
run_with_heartbeat() {
|
||||||
log_file="\$1"
|
log_file="\$1"
|
||||||
build_label="\$2"
|
build_label="\$2"
|
||||||
@@ -209,31 +236,59 @@ pipeline {
|
|||||||
fi
|
fi
|
||||||
return "\$cmd_status"
|
return "\$cmd_status"
|
||||||
}
|
}
|
||||||
sudo docker buildx inspect --builder ${BUILDER_NAME} --bootstrap >/dev/null
|
|
||||||
echo 'Building and pushing multi-arch Web image: ${WEB_IMAGE_TAGGED}'
|
for PLATFORM in linux/amd64 linux/arm64; do
|
||||||
run_with_heartbeat /tmp/live-recorder-web-buildx-${IMAGE_TAG}.log "Web multi-arch build" \
|
ARCH_TAG="\${PLATFORM##*/}"
|
||||||
sudo docker buildx build \
|
PLAT_REF="${WEB_IMAGE_TAGGED}-\${ARCH_TAG}"
|
||||||
--builder ${BUILDER_NAME} \
|
PLAT_LATEST="${WEB_IMAGE_LATEST}-\${ARCH_TAG}"
|
||||||
--platform ${TARGET_PLATFORMS} \
|
|
||||||
--network host \
|
echo ''
|
||||||
--progress=plain \
|
echo "=== Building Web for \$PLATFORM -> \$PLAT_REF ==="
|
||||||
--provenance=false \
|
run_with_heartbeat /tmp/live-recorder-web-\${ARCH_TAG}.log "Web \${ARCH_TAG} build" \
|
||||||
--cache-from type=registry,ref=${WEB_CACHE_IMAGE} \
|
sudo docker buildx build \
|
||||||
--cache-to type=registry,ref=${WEB_CACHE_IMAGE},mode=max \
|
--platform "\$PLATFORM" \
|
||||||
--build-arg NODE_IMAGE=${WEB_NODE_IMAGE} \
|
--network host \
|
||||||
--build-arg NGINX_IMAGE=${WEB_NGINX_IMAGE} \
|
--progress=plain \
|
||||||
--build-arg HTTP_PROXY=${HTTP_PROXY_URL} \
|
--provenance=false \
|
||||||
--build-arg HTTPS_PROXY=${HTTP_PROXY_URL} \
|
--cache-from type=registry,ref=${WEB_CACHE_IMAGE} \
|
||||||
--build-arg NO_PROXY=${NO_PROXY_HOSTS} \
|
--build-arg NODE_IMAGE=${WEB_NODE_IMAGE} \
|
||||||
--build-arg http_proxy=${HTTP_PROXY_URL} \
|
--build-arg NGINX_IMAGE=${WEB_NGINX_IMAGE} \
|
||||||
--build-arg https_proxy=${HTTP_PROXY_URL} \
|
--build-arg HTTP_PROXY=${HTTP_PROXY_URL} \
|
||||||
--build-arg no_proxy=${NO_PROXY_HOSTS} \
|
--build-arg HTTPS_PROXY=${HTTP_PROXY_URL} \
|
||||||
-f frontend/Dockerfile \
|
--build-arg NO_PROXY=${NO_PROXY_HOSTS} \
|
||||||
--build-arg VITE_API_BASE_URL=/api \
|
--build-arg http_proxy=${HTTP_PROXY_URL} \
|
||||||
-t ${WEB_IMAGE_TAGGED} \
|
--build-arg https_proxy=${HTTP_PROXY_URL} \
|
||||||
-t ${WEB_IMAGE_LATEST} \
|
--build-arg no_proxy=${NO_PROXY_HOSTS} \
|
||||||
--push \
|
-f frontend/Dockerfile \
|
||||||
frontend
|
--build-arg VITE_API_BASE_URL=/api \
|
||||||
|
-t "\$PLAT_REF" \
|
||||||
|
-t "\$PLAT_LATEST" \
|
||||||
|
--load \
|
||||||
|
frontend
|
||||||
|
|
||||||
|
echo "=== Pushing \$PLAT_REF ==="
|
||||||
|
sudo docker push "\$PLAT_REF" 2>&1 | tail -3
|
||||||
|
sudo docker push "\$PLAT_LATEST" 2>&1 | tail -3
|
||||||
|
sudo docker rmi "\$PLAT_REF" "\$PLAT_LATEST" 2>/dev/null || true
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ''
|
||||||
|
echo "=== Creating multi-arch manifest: ${WEB_IMAGE_TAGGED} ==="
|
||||||
|
sudo docker manifest create "${WEB_IMAGE_TAGGED}" \
|
||||||
|
"${WEB_IMAGE_TAGGED}-amd64" \
|
||||||
|
"${WEB_IMAGE_TAGGED}-arm64"
|
||||||
|
sudo docker manifest create "${WEB_IMAGE_LATEST}" \
|
||||||
|
"${WEB_IMAGE_LATEST}-amd64" \
|
||||||
|
"${WEB_IMAGE_LATEST}-arm64"
|
||||||
|
|
||||||
|
echo "=== Pushing manifests ==="
|
||||||
|
sudo docker manifest push "${WEB_IMAGE_TAGGED}" 2>&1 | tail -3
|
||||||
|
sudo docker manifest push "${WEB_IMAGE_LATEST}" 2>&1 | tail -3
|
||||||
|
|
||||||
|
echo ''
|
||||||
|
echo "Web multi-arch images pushed successfully:"
|
||||||
|
echo " ${WEB_IMAGE_TAGGED}"
|
||||||
|
echo " ${WEB_IMAGE_LATEST}"
|
||||||
"""
|
"""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user