ci: scope Docker privilege to Jenkins credential
This commit is contained in:
Vendored
+114
-78
@@ -16,6 +16,7 @@ pipeline {
|
||||
WEB_IMAGE_REPO = 'reg.nxsir.cn/live_recorder/app-web'
|
||||
HARBOR_CREDENTIALS = 'harbor_key'
|
||||
OPENLIST_CREDENTIALS = 'openlist_key'
|
||||
NODE_CREDENTIALS = 'bbb939ea-4f01-4b47-aecb-c5ee2a551ef4'
|
||||
OPENLIST_BASE_URL = 'https://openlist.nxsir.cn'
|
||||
OPENLIST_REMOTE_DIR = '/yidongpan/构建产物/liverecorder'
|
||||
|
||||
@@ -72,38 +73,43 @@ pipeline {
|
||||
currentBuild.description = "${env.IMMUTABLE_TAG}"
|
||||
}
|
||||
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
test "$(uname -m)" = x86_64
|
||||
for command_name in git sudo docker curl python3 npm node sha256sum stat tar; do
|
||||
command -v "$command_name" >/dev/null
|
||||
done
|
||||
test -x "$DOTNET"
|
||||
test -x "$FNPACK_BIN"
|
||||
printf '%s %s\n' "$FNPACK_SHA256" "$FNPACK_BIN" | sha256sum --check --status
|
||||
sudo -n true
|
||||
sudo docker version >/dev/null
|
||||
sudo docker buildx version
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: "${NODE_CREDENTIALS}",
|
||||
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||
)]) {
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
test "$(uname -m)" = x86_64
|
||||
for command_name in git sudo docker curl python3 npm node sha256sum stat tar; do
|
||||
command -v "$command_name" >/dev/null
|
||||
done
|
||||
test -x "$DOTNET"
|
||||
test -x "$FNPACK_BIN"
|
||||
printf '%s %s\n' "$FNPACK_SHA256" "$FNPACK_BIN" | sha256sum --check --status
|
||||
./scripts/ci-docker.sh version >/dev/null
|
||||
./scripts/ci-docker.sh buildx version
|
||||
|
||||
available_kb=$(df -Pk "$WORKSPACE" | awk 'NR == 2 { print $4 }')
|
||||
if [ "$available_kb" -lt 2097152 ]; then
|
||||
echo "At least 2 GiB free workspace disk is required; available KiB: $available_kb" >&2
|
||||
exit 1
|
||||
fi
|
||||
available_kb=$(df -Pk "$WORKSPACE" | awk 'NR == 2 { print $4 }')
|
||||
if [ "$available_kb" -lt 2097152 ]; then
|
||||
echo "At least 2 GiB free workspace disk is required; available KiB: $available_kb" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p \
|
||||
"$DOCKER_CONFIG" \
|
||||
"$NUGET_PACKAGES" \
|
||||
"$NUGET_HTTP_CACHE_PATH" \
|
||||
"$NUGET_PLUGINS_CACHE_PATH" \
|
||||
"$DOTNET_CLI_HOME" \
|
||||
"$NPM_CONFIG_CACHE" \
|
||||
"$LIVERECORDER_NUGET_FEED" \
|
||||
"$LIVERECORDER_BUILD_TMPDIR" \
|
||||
"$LIVERECORDER_VERIFY_TMPDIR" \
|
||||
"$(dirname -- "$FPK_PATH")"
|
||||
chmod 700 "$DOCKER_CONFIG"
|
||||
'''
|
||||
mkdir -p \
|
||||
"$DOCKER_CONFIG" \
|
||||
"$NUGET_PACKAGES" \
|
||||
"$NUGET_HTTP_CACHE_PATH" \
|
||||
"$NUGET_PLUGINS_CACHE_PATH" \
|
||||
"$DOTNET_CLI_HOME" \
|
||||
"$NPM_CONFIG_CACHE" \
|
||||
"$LIVERECORDER_NUGET_FEED" \
|
||||
"$LIVERECORDER_BUILD_TMPDIR" \
|
||||
"$LIVERECORDER_VERIFY_TMPDIR" \
|
||||
"$(dirname -- "$FPK_PATH")"
|
||||
chmod 700 "$DOCKER_CONFIG"
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,22 +138,28 @@ pipeline {
|
||||
|
||||
stage('Prepare Docker Builder') {
|
||||
steps {
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
if ! sudo docker run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m 2>/dev/null | grep -q aarch64; then
|
||||
sudo docker run --privileged --rm "$BINFMT_IMAGE" --install arm64
|
||||
fi
|
||||
sudo docker run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m | grep -q aarch64
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: "${NODE_CREDENTIALS}",
|
||||
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||
)]) {
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
if ! ./scripts/ci-docker.sh run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m 2>/dev/null | grep -q aarch64; then
|
||||
./scripts/ci-docker.sh run --privileged --rm "$BINFMT_IMAGE" --install arm64
|
||||
fi
|
||||
./scripts/ci-docker.sh run --rm --platform linux/arm64 "$ARM_TEST_IMAGE" uname -m | grep -q aarch64
|
||||
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx create \
|
||||
--name "$BUILDER_NAME" \
|
||||
--driver docker-container \
|
||||
--driver-opt "image=$BUILDKIT_IMAGE" \
|
||||
--driver-opt network=host \
|
||||
--use
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx inspect "$BUILDER_NAME" --bootstrap
|
||||
'''
|
||||
./scripts/ci-docker.sh buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
||||
./scripts/ci-docker.sh buildx create \
|
||||
--name "$BUILDER_NAME" \
|
||||
--driver docker-container \
|
||||
--driver-opt "image=$BUILDKIT_IMAGE" \
|
||||
--driver-opt network=host \
|
||||
--use
|
||||
./scripts/ci-docker.sh buildx inspect "$BUILDER_NAME" --bootstrap
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,6 +182,11 @@ pipeline {
|
||||
|
||||
stage('Build And Push amd64') {
|
||||
steps {
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: "${NODE_CREDENTIALS}",
|
||||
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||
)]) {
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
arch=amd64
|
||||
@@ -177,7 +194,7 @@ pipeline {
|
||||
api_ref="$API_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||
web_ref="$WEB_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
||||
./scripts/ci-docker.sh buildx build \
|
||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||
--progress=plain --provenance=false --no-cache \
|
||||
--build-arg HTTP_PROXY="$HTTP_PROXY_URL" \
|
||||
@@ -187,10 +204,10 @@ pipeline {
|
||||
--build-arg https_proxy="$HTTP_PROXY_URL" \
|
||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||
-f src/LiveRecorder.WebApi/Dockerfile -t "$api_ref" --load .
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$api_ref"
|
||||
sudo docker rmi "$api_ref" >/dev/null
|
||||
./scripts/ci-docker.sh push "$api_ref"
|
||||
./scripts/ci-docker.sh rmi "$api_ref" >/dev/null
|
||||
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
||||
./scripts/ci-docker.sh buildx build \
|
||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||
--progress=plain --provenance=false --no-cache \
|
||||
--build-arg NODE_IMAGE="$NODE_BUILD_IMAGE" \
|
||||
@@ -203,14 +220,20 @@ pipeline {
|
||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||
--build-arg VITE_API_BASE_URL=/api \
|
||||
-f frontend/Dockerfile -t "$web_ref" --load frontend
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$web_ref"
|
||||
sudo docker rmi "$web_ref" >/dev/null
|
||||
./scripts/ci-docker.sh push "$web_ref"
|
||||
./scripts/ci-docker.sh rmi "$web_ref" >/dev/null
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Build And Push arm64') {
|
||||
steps {
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: "${NODE_CREDENTIALS}",
|
||||
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||
)]) {
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
arch=arm64
|
||||
@@ -218,7 +241,7 @@ pipeline {
|
||||
api_ref="$API_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||
web_ref="$WEB_IMAGE_REPO:$IMMUTABLE_TAG-$arch"
|
||||
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
||||
./scripts/ci-docker.sh buildx build \
|
||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||
--progress=plain --provenance=false --no-cache \
|
||||
--build-arg HTTP_PROXY="$HTTP_PROXY_URL" \
|
||||
@@ -228,10 +251,10 @@ pipeline {
|
||||
--build-arg https_proxy="$HTTP_PROXY_URL" \
|
||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||
-f src/LiveRecorder.WebApi/Dockerfile -t "$api_ref" --load .
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$api_ref"
|
||||
sudo docker rmi "$api_ref" >/dev/null
|
||||
./scripts/ci-docker.sh push "$api_ref"
|
||||
./scripts/ci-docker.sh rmi "$api_ref" >/dev/null
|
||||
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx build \
|
||||
./scripts/ci-docker.sh buildx build \
|
||||
--builder "$BUILDER_NAME" --platform "$platform" --network host \
|
||||
--progress=plain --provenance=false --no-cache \
|
||||
--build-arg NODE_IMAGE="$NODE_BUILD_IMAGE" \
|
||||
@@ -244,34 +267,41 @@ pipeline {
|
||||
--build-arg no_proxy="$NO_PROXY_HOSTS" \
|
||||
--build-arg VITE_API_BASE_URL=/api \
|
||||
-f frontend/Dockerfile -t "$web_ref" --load frontend
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker push "$web_ref"
|
||||
sudo docker rmi "$web_ref" >/dev/null
|
||||
./scripts/ci-docker.sh push "$web_ref"
|
||||
./scripts/ci-docker.sh rmi "$web_ref" >/dev/null
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
stage('Publish Multi-arch Manifests') {
|
||||
steps {
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: "${NODE_CREDENTIALS}",
|
||||
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||
)]) {
|
||||
sh '''
|
||||
set -euo pipefail
|
||||
for repository in "$API_IMAGE_REPO" "$WEB_IMAGE_REPO"; do
|
||||
immutable_ref="$repository:$IMMUTABLE_TAG"
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools create \
|
||||
./scripts/ci-docker.sh buildx imagetools create \
|
||||
--tag "$immutable_ref" \
|
||||
"$immutable_ref-amd64" "$immutable_ref-arm64"
|
||||
|
||||
manifest=$(sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools inspect --raw "$immutable_ref")
|
||||
manifest=$(./scripts/ci-docker.sh buildx imagetools inspect --raw "$immutable_ref")
|
||||
printf '%s' "$manifest" | grep -q '"architecture"[[:space:]]*:[[:space:]]*"amd64"'
|
||||
printf '%s' "$manifest" | grep -q '"architecture"[[:space:]]*:[[:space:]]*"arm64"'
|
||||
done
|
||||
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools create \
|
||||
./scripts/ci-docker.sh buildx imagetools create \
|
||||
--tag "$API_IMAGE_REPO:$APP_VERSION" --tag "$API_IMAGE_REPO:latest" \
|
||||
"$API_IMAGE_REPO:$IMMUTABLE_TAG"
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx imagetools create \
|
||||
./scripts/ci-docker.sh buildx imagetools create \
|
||||
--tag "$WEB_IMAGE_REPO:$APP_VERSION" --tag "$WEB_IMAGE_REPO:latest" \
|
||||
"$WEB_IMAGE_REPO:$IMMUTABLE_TAG"
|
||||
'''
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,23 +349,29 @@ pipeline {
|
||||
echo 'LiveRecorder pipeline failed; stable Docker tags were only updated if all architecture builds succeeded.'
|
||||
}
|
||||
always {
|
||||
sh '''
|
||||
set +e
|
||||
if [ -n "${BUILDER_NAME:-}" ]; then
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [ -n "${IMMUTABLE_TAG:-}" ]; then
|
||||
for repository in "$API_IMAGE_REPO" "$WEB_IMAGE_REPO"; do
|
||||
for suffix in amd64 arm64; do
|
||||
sudo docker rmi "$repository:$IMMUTABLE_TAG-$suffix" >/dev/null 2>&1 || true
|
||||
done
|
||||
sudo env DOCKER_CONFIG="$DOCKER_CONFIG" docker manifest rm "$repository:$IMMUTABLE_TAG" >/dev/null 2>&1 || true
|
||||
done
|
||||
fi
|
||||
if [ -f "$DOCKER_CONFIG/config.json" ]; then
|
||||
: >"$DOCKER_CONFIG/config.json"
|
||||
fi
|
||||
'''
|
||||
withCredentials([usernamePassword(
|
||||
credentialsId: "${NODE_CREDENTIALS}",
|
||||
usernameVariable: 'JENKINS_NODE_USERNAME',
|
||||
passwordVariable: 'JENKINS_NODE_PASSWORD'
|
||||
)]) {
|
||||
sh '''
|
||||
set +e
|
||||
if [ -x ./scripts/ci-docker.sh ] && [ -n "${BUILDER_NAME:-}" ]; then
|
||||
./scripts/ci-docker.sh buildx rm -f "$BUILDER_NAME" >/dev/null 2>&1 || true
|
||||
fi
|
||||
if [ -x ./scripts/ci-docker.sh ] && [ -n "${IMMUTABLE_TAG:-}" ]; then
|
||||
for repository in "$API_IMAGE_REPO" "$WEB_IMAGE_REPO"; do
|
||||
for suffix in amd64 arm64; do
|
||||
./scripts/ci-docker.sh rmi "$repository:$IMMUTABLE_TAG-$suffix" >/dev/null 2>&1 || true
|
||||
done
|
||||
./scripts/ci-docker.sh manifest rm "$repository:$IMMUTABLE_TAG" >/dev/null 2>&1 || true
|
||||
done
|
||||
fi
|
||||
if [ -f "$DOCKER_CONFIG/config.json" ]; then
|
||||
: >"$DOCKER_CONFIG/config.json"
|
||||
fi
|
||||
'''
|
||||
}
|
||||
cleanWs(deleteDirs: true, notFailBuild: true)
|
||||
}
|
||||
}
|
||||
|
||||
Executable
+9
@@ -0,0 +1,9 @@
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
: "${JENKINS_NODE_PASSWORD:?JENKINS_NODE_PASSWORD is required}"
|
||||
|
||||
printf '%s\n' "$JENKINS_NODE_PASSWORD" | \
|
||||
sudo -S -p '' -- \
|
||||
/usr/bin/env "DOCKER_CONFIG=${DOCKER_CONFIG:-}" \
|
||||
/usr/bin/docker "$@"
|
||||
Reference in New Issue
Block a user