diff --git a/Jenkinsfile.backend-docker b/Jenkinsfile.backend-docker index c8768df..7a0787a 100644 --- a/Jenkinsfile.backend-docker +++ b/Jenkinsfile.backend-docker @@ -50,6 +50,20 @@ pipeline { env.SMOKE_NETWORK = "jizhi-smoke-net-${env.BUILD_NUMBER}" env.SMOKE_MYSQL = "jizhi-smoke-mysql-${env.BUILD_NUMBER}" env.SMOKE_APP = "jizhi-smoke-app-${env.BUILD_NUMBER}" + env.DOCKER_CMD = sh( + script: ''' + set +x + if docker version >/dev/null 2>&1; then + printf 'docker' + elif sudo -n docker version >/dev/null 2>&1; then + printf 'sudo -n docker' + else + echo 'Jenkins 用户无法访问 Docker;请加入 docker 组或配置免密 sudo docker。' >&2 + exit 1 + fi + ''', + returnStdout: true, + ).trim() currentBuild.displayName = "#${env.BUILD_NUMBER} ${env.IMMUTABLE_TAG}" currentBuild.description = 'linux/amd64 · Admin Web + ASP.NET API' } @@ -59,8 +73,8 @@ pipeline { for command_name in git docker curl gzip sha256sum python3; do command -v "$command_name" >/dev/null done - docker version >/dev/null - docker buildx version + $DOCKER_CMD version >/dev/null + $DOCKER_CMD buildx version test -f Dockerfile.backend test -f admin-web/package-lock.json mkdir -p artifacts @@ -75,7 +89,7 @@ pipeline { retry(2) { sh ''' set -euo pipefail - docker buildx build \ + $DOCKER_CMD buildx build \ --platform linux/amd64 \ --load \ --file Dockerfile.backend \ @@ -88,9 +102,9 @@ pipeline { } sh ''' set -euo pipefail - test "$(docker image inspect "$IMAGE_REF" --format '{{.Os}}/{{.Architecture}}')" = 'linux/amd64' - test "$(docker image inspect "$IMAGE_REF" --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" = "$FULL_SHA" - docker run --rm --entrypoint /bin/sh "$IMAGE_REF" -c \ + test "$($DOCKER_CMD image inspect "$IMAGE_REF" --format '{{.Os}}/{{.Architecture}}')" = 'linux/amd64' + test "$($DOCKER_CMD image inspect "$IMAGE_REF" --format '{{index .Config.Labels "org.opencontainers.image.revision"}}')" = "$FULL_SHA" + $DOCKER_CMD run --rm --entrypoint /bin/sh "$IMAGE_REF" -c \ 'test -s /app/MiaoJiZhang.Api.dll && test -s /app/wwwroot/index.html' ''' } @@ -100,8 +114,8 @@ pipeline { steps { sh ''' set -euo pipefail - docker network create "$SMOKE_NETWORK" >/dev/null - docker run --detach \ + $DOCKER_CMD network create "$SMOKE_NETWORK" >/dev/null + $DOCKER_CMD run --detach \ --name "$SMOKE_MYSQL" \ --network "$SMOKE_NETWORK" \ --env MYSQL_DATABASE=jizhi_smoke \ @@ -112,7 +126,7 @@ pipeline { mysql_ready=0 for attempt in $(seq 1 60); do - if docker exec "$SMOKE_MYSQL" mysqladmin ping \ + if $DOCKER_CMD exec "$SMOKE_MYSQL" mysqladmin ping \ --user=jizhi --password=jizhi-smoke-password --silent; then mysql_ready=1 break @@ -120,11 +134,11 @@ pipeline { sleep 2 done if [ "$mysql_ready" != 1 ]; then - docker logs "$SMOKE_MYSQL" >&2 + $DOCKER_CMD logs "$SMOKE_MYSQL" >&2 exit 1 fi - docker run --detach \ + $DOCKER_CMD run --detach \ --name "$SMOKE_APP" \ --network "$SMOKE_NETWORK" \ --publish 127.0.0.1::8080 \ @@ -139,7 +153,7 @@ pipeline { --env "Build__Version=$IMMUTABLE_TAG" \ "$IMAGE_REF" >/dev/null - host_port=$(docker port "$SMOKE_APP" 8080/tcp | sed -n 's/.*://p' | head -n 1) + host_port=$($DOCKER_CMD port "$SMOKE_APP" 8080/tcp | sed -n 's/.*://p' | head -n 1) test -n "$host_port" app_ready=0 for attempt in $(seq 1 90); do @@ -148,14 +162,14 @@ pipeline { app_ready=1 break fi - if ! docker inspect "$SMOKE_APP" --format '{{.State.Running}}' | grep -qx true; then - docker logs "$SMOKE_APP" >&2 + if ! $DOCKER_CMD inspect "$SMOKE_APP" --format '{{.State.Running}}' | grep -qx true; then + $DOCKER_CMD logs "$SMOKE_APP" >&2 exit 1 fi sleep 2 done if [ "$app_ready" != 1 ]; then - docker logs "$SMOKE_APP" >&2 + $DOCKER_CMD logs "$SMOKE_APP" >&2 exit 1 fi grep -Fq "\"version\":\"$IMMUTABLE_TAG\"" artifacts/smoke-ping.json @@ -169,11 +183,11 @@ pipeline { steps { sh ''' set -euo pipefail - docker save "$IMAGE_REF" | gzip -1 >"$ARCHIVE_PATH" + $DOCKER_CMD save "$IMAGE_REF" | gzip -1 >"$ARCHIVE_PATH" gzip -t "$ARCHIVE_PATH" gzip -dc "$ARCHIVE_PATH" | tar -tf - | grep -q '^manifest.json$' sha256sum "$ARCHIVE_PATH" >"$ARCHIVE_PATH.sha256" - image_id=$(docker image inspect "$IMAGE_REF" --format '{{.Id}}') + image_id=$($DOCKER_CMD image inspect "$IMAGE_REF" --format '{{.Id}}') archive_sha=$(awk '{print $1}' "$ARCHIVE_PATH.sha256") export image_id archive_sha python3 - <<'PY' @@ -221,12 +235,12 @@ PY post { always { script { - if (env.NODE_NAME?.trim()) { + if (env.NODE_NAME?.trim() && env.DOCKER_CMD?.trim()) { sh( script: ''' - docker rm --force "$SMOKE_APP" "$SMOKE_MYSQL" >/dev/null 2>&1 || true - docker network rm "$SMOKE_NETWORK" >/dev/null 2>&1 || true - docker image rm "$IMAGE_REF" >/dev/null 2>&1 || true + $DOCKER_CMD rm --force "$SMOKE_APP" "$SMOKE_MYSQL" >/dev/null 2>&1 || true + $DOCKER_CMD network rm "$SMOKE_NETWORK" >/dev/null 2>&1 || true + $DOCKER_CMD image rm "$IMAGE_REF" >/dev/null 2>&1 || true ''', returnStatus: true, )