fix(ci): 消除 preflight Set up job docker pull 卡点,改用宿主机 Node 22 + daemon.json mirrors + Dockerfile ARG 双保险
- preflight:删除 container.image: node:22-bookworm-slim,避免 Runner 在 Set up job 阶段独立 docker pull(国内连 Hub 被限速一直卡) - preflight:改用 runs-on 直出 + actions/setup-node@v4 装 Node 22,npm registry 设 npmmirror - build-image:python3 合法合成 /etc/docker/daemon.json 注入 3 组 docker.io registry mirrors(daocloud/1panel/1ms.run),systemctl→service→失败跳过 三级 non-intrusive 重启 docker - Dockerfile:新增全局 ARG DOCKER_MIRROR / NODE_BUILDER_TAG / NODE_RUNTIME_TAG,FROM 统一前缀化;本地开发 DOCKER_MIRROR 为空时等价原写法,体验不变 - buildx BUILD_ARGS:新增 3 个 --build-arg 把 DOCKER_MIRROR_PREFIX / NODE_BUILDER_TAG / NODE_RUNTIME_TAG 传入,CI 拉 node:22-alpine 必走国内源 - 修复后:workflow 触发时 Preflight 日志不会再出现 Starting job container / docker pull image=node:***-bookworm-slim;前面 system-settings defaults 兜底修复可顺利部署上线
This commit is contained in:
+72
-34
@@ -36,52 +36,45 @@ env:
|
||||
APT_MIRROR_UBUNTU_SECURITY_HTTP: http://mirrors.tuna.tsinghua.edu.cn/ubuntu-security
|
||||
HTTP_PROXY_EXAMPLE: ""
|
||||
HTTPS_PROXY_EXAMPLE: ""
|
||||
# ========== Docker 官方镜像国内加速(Runner 拉 node:alpine / buildkit 等最常见卡点) ==========
|
||||
# 注意:如果你知道哪个镜像源在内网最快,可以在仓库 Variables 里覆盖 DOCKER_REGISTRY_MIRROR_1/2/3
|
||||
DOCKER_REGISTRY_MIRROR_1: https://docker.m.daocloud.io
|
||||
DOCKER_REGISTRY_MIRROR_2: https://docker.1panel.live
|
||||
DOCKER_REGISTRY_MIRROR_3: https://docker.1ms.run
|
||||
# Dockerfile 内 FROM 前缀替换(ARG DOCKER_MIRROR=…),避免 buildx build 内部 FROM node:22-alpine 再被 Hub 限速
|
||||
DOCKER_MIRROR_PREFIX: docker.m.daocloud.io/library/
|
||||
NODE_BUILDER_TAG: "22-alpine"
|
||||
NODE_RUNTIME_TAG: "22-alpine"
|
||||
|
||||
jobs:
|
||||
preflight:
|
||||
name: Preflight 语法与构建检查
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 15
|
||||
container:
|
||||
image: node:22-bookworm-slim
|
||||
# 关键修复:去掉 container.image: node:22-bookworm-slim
|
||||
# 原因:Runner 在 Set up job 阶段会先 docker pull 这个镜像,国内连 Docker Hub 被限速会一直卡转圈。
|
||||
# 直接在 Runner 宿主机上执行(通常自带 node 20+);为保证 Node 22 一致性,用 actions/setup-node 主动安装。
|
||||
steps:
|
||||
- name: 安装基础运行依赖(git/ca-certificates,已换清华 TUNA 源)
|
||||
- name: 安装基础运行依赖(git/curl/ca-certificates,Runner 自带)
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
# ========== Step 0:先用 HTTP 清华源装 ca-certificates(解鸡生蛋:HTTPS 需要证书,证书得先用 HTTP 装) ==========
|
||||
SOURCES_FILE="/etc/apt/sources.list.d/debian.sources"
|
||||
if [ -f "${SOURCES_FILE}" ]; then
|
||||
sed -i "s|http://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" "${SOURCES_FILE}"
|
||||
sed -i "s|http://deb.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" "${SOURCES_FILE}"
|
||||
sed -i "s|https://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" "${SOURCES_FILE}"
|
||||
sed -i "s|https://deb.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" "${SOURCES_FILE}"
|
||||
else
|
||||
if [ -f /etc/apt/sources.list ]; then
|
||||
sed -i "s|http://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" /etc/apt/sources.list
|
||||
sed -i "s|https://deb.debian.org/debian|${APT_MIRROR_DEBIAN_HTTP}|g" /etc/apt/sources.list
|
||||
sed -i "s|http://security.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" /etc/apt/sources.list
|
||||
sed -i "s|https://security.debian.org/debian-security|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|g" /etc/apt/sources.list
|
||||
fi
|
||||
fi
|
||||
apt-get update -qq
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends ca-certificates
|
||||
update-ca-certificates 2>/dev/null || true
|
||||
command -v git || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends git ca-certificates)
|
||||
command -v curl || (apt-get update -qq && DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends curl)
|
||||
command -v node && node -v || true
|
||||
command -v npm && npm -v || true
|
||||
|
||||
# ========== Step 1:现在有了证书,换成 HTTPS 清华源(更安全)+ 装 git/curl ==========
|
||||
if [ -f "${SOURCES_FILE}" ]; then
|
||||
sed -i "s|${APT_MIRROR_DEBIAN_HTTP}|${APT_MIRROR_DEBIAN}|g" "${SOURCES_FILE}"
|
||||
sed -i "s|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|${APT_MIRROR_DEBIAN_SECURITY}|g" "${SOURCES_FILE}"
|
||||
else
|
||||
if [ -f /etc/apt/sources.list ]; then
|
||||
sed -i "s|${APT_MIRROR_DEBIAN_HTTP}|${APT_MIRROR_DEBIAN}|g" /etc/apt/sources.list
|
||||
sed -i "s|${APT_MIRROR_DEBIAN_SECURITY_HTTP}|${APT_MIRROR_DEBIAN_SECURITY}|g" /etc/apt/sources.list
|
||||
fi
|
||||
fi
|
||||
apt-get update -qq
|
||||
DEBIAN_FRONTEND=noninteractive apt-get install -yqq --no-install-recommends git curl
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
- name: 使用 Node.js 22(若 Runner 自带版本不足 22 则自动下载)
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "22"
|
||||
|
||||
- name: 校验 Node + npm + git 可用
|
||||
run: |
|
||||
set -euxo pipefail
|
||||
# 全局 git 代理:任何 git clone/fetch/pull https://github.com/... 自动走 gh-proxy 前缀
|
||||
git config --system url."${GH_PROXY_PREFIX}https://github.com/".insteadOf "https://github.com/" || true
|
||||
# npm registry 走 npmmirror,避免后续 npm ci 也卡
|
||||
npm config set registry https://registry.npmmirror.com >/dev/null 2>&1 || true
|
||||
git --version
|
||||
node -v
|
||||
npm -v
|
||||
@@ -166,6 +159,48 @@ jobs:
|
||||
sudo git config --system url."${GH_PROXY_PREFIX}https://github.com/".insteadOf "https://github.com/" || true
|
||||
# npm:强制用 npmmirror(与 preflight 对齐)
|
||||
npm config set registry https://registry.npmmirror.com >/dev/null 2>&1 || true
|
||||
|
||||
# ========== 关键修复:宿主机 Docker daemon 先注入国内 registry mirrors ==========
|
||||
# 原因:Runner 任何 docker pull / buildx create(moby/buildkit 拉基础镜像)都要先经过 daemon
|
||||
# 如果直接连 docker.io,国内会被限速到 <200KB/s,导致 Setup / BuildKit 拉镜像一直卡。
|
||||
DOCKER_DAEMON_CONF="/etc/docker/daemon.json"
|
||||
if command -v docker >/dev/null 2>&1 && command -v sudo >/dev/null 2>&1; then
|
||||
sudo mkdir -p /etc/docker 2>/dev/null || true
|
||||
OLD_MIRRORS_JSON="{}"
|
||||
if [ -f "${DOCKER_DAEMON_CONF}" ]; then
|
||||
OLD_MIRRORS_JSON="$(sudo cat "${DOCKER_DAEMON_CONF}" 2>/dev/null || echo "{}")"
|
||||
fi
|
||||
# 用 python3 合成合法 JSON(避免 bash 手搓 JSON 转义坑)
|
||||
NEW_DAEMON_JSON="$(
|
||||
python3 - "$OLD_MIRRORS_JSON" \
|
||||
"${DOCKER_REGISTRY_MIRROR_1}" "${DOCKER_REGISTRY_MIRROR_2}" "${DOCKER_REGISTRY_MIRROR_3}" <<'PY'
|
||||
import json, sys
|
||||
try:
|
||||
data = json.loads(sys.argv[1] or "{}")
|
||||
except Exception:
|
||||
data = {}
|
||||
mirrors_envs = [m for m in sys.argv[2:5] if m]
|
||||
existing = data.get("registry-mirrors") or []
|
||||
if isinstance(existing, list):
|
||||
combined = list(dict.fromkeys([*mirrors_envs, *existing]))
|
||||
else:
|
||||
combined = mirrors_envs
|
||||
if combined:
|
||||
data["registry-mirrors"] = combined
|
||||
data.setdefault("log-driver", "json-file")
|
||||
print(json.dumps(data, ensure_ascii=False, indent=2))
|
||||
PY
|
||||
)"
|
||||
echo "${NEW_DAEMON_JSON}" | sudo tee "${DOCKER_DAEMON_CONF}" >/dev/null
|
||||
echo "[Docker] daemon.json 已注入 registry-mirrors:"
|
||||
sudo cat "${DOCKER_DAEMON_CONF}" 2>/dev/null || true
|
||||
# 非侵入式重启 docker;runner 没 systemd 时用 service 兜底;失败也跳过(buildkitd.toml 内部仍有 mirrors)
|
||||
sudo systemctl restart docker 2>/dev/null \
|
||||
|| sudo service docker restart 2>/dev/null \
|
||||
|| echo "[Docker] systemctl/service 重启失败,跳过(后续 buildx builder 内部仍有 registry mirrors)"
|
||||
sleep 3 2>/dev/null || true
|
||||
fi
|
||||
|
||||
echo "环境准备完成"
|
||||
cat /etc/os-release 2>/dev/null | head -4 || true
|
||||
docker --version
|
||||
@@ -307,6 +342,9 @@ jobs:
|
||||
BUILD_ARGS=(
|
||||
--build-arg BUILDKIT_INLINE_CACHE=1
|
||||
--build-arg NODE_ENV=production
|
||||
--build-arg DOCKER_MIRROR="${DOCKER_MIRROR_PREFIX}"
|
||||
--build-arg NODE_BUILDER_TAG="${NODE_BUILDER_TAG}"
|
||||
--build-arg NODE_RUNTIME_TAG="${NODE_RUNTIME_TAG}"
|
||||
)
|
||||
# 说明:暂时关闭 registry 分层缓存(buildkitd 推 buildcache 也要认证,同样会触发 Gitea 1.27 OAuth2 空 token)
|
||||
# 改为本地 Docker daemon 缓存,已构建的层会自动复用,下次 build 速度几乎相同
|
||||
|
||||
Reference in New Issue
Block a user