背景

前端项目的Base镜像一直使用的是 Node.js 18.20 版本,最近面临升级需求:

  1. Node.js 18.20 已进入维护末期,后续可能会逐渐出现兼容性问题
  2. CI 中出现大量版本 Warning,提示需要升级
  3. 团队内其他项目已在 3 月中旬完成 Node.js 20 的升级

镜像选型分析

镜像 curl/ca-certificates git 说明
node:20 基于 buildpack-deps,包含常用工具
node:20-bullseye / bookworm Debian 完整版,最稳定
node:20-slim 精简版
node:20-alpine 极简版,需手动安装

为什么选择 Alpine?

  • curlca-certificates 在 AI Code Review 阶段需要用到
  • git 在构建过程中用于给 index.html 打版本信息
  • Alpine 镜像体积最小,可以加快日常构建速度

原 Dockerfile 问题

FROM 旧镜像

ARG APP_DIR="/usr/src/app"

# 更新源列表
COPY ./ci/sources.list /etc/apt/sources.list

COPY package.json .npmrc $APP_DIR/

RUN set -xe \
    # 添加 Google Chrome 仓库的 GPG 密钥
    && wget -q -O - https://dl.google.com/linux/linux_signing_key.pub | apt-key add - \
    # 删除 debian.sources,以完全使用 sources.list 作为唯一源
    && rm /etc/apt/sources.list.d/debian.sources \
    && apt-get update \
    && apt-get install -y \
        default-jre \
        sshpass \
    && (cd $APP_DIR; npm i --verbose --legacy-peer-deps) \
    && (npm cache clean --force)

WORKDIR $APP_DIR

主要问题:

  1. Chrome 仓库密钥在 CI Runner 上会遇到各种网络和版本问题
  2. 使用 Node.js 20+ 的 bookworm 镜像在某些 Runner 上会遇到 node 无法启动的问题
  3. 依赖包过大,构建速度慢

解决方案

考虑到 Chrome 主要是为了 E2E 测试使用,决定暂时先跳过这部分,聚焦核心需求。

构建新镜像

# 拉取基础镜像,选择正确的 platform
docker pull --platform=linux/amd64 node:20-alpine

# Dockerfile
FROM node:20-alpine
RUN apk add --no-cache curl git ca-certificates

# 构建并推送
docker build --pull=false -t your-registry/frontend/build/node:20-alpine-amd64 .
docker push your-registry/frontend/build/node:20-alpine-amd64

注意事项: 拉取基础镜像时一定要选择正确的 platform,否则在 linux/amd64 的 CI Runner 上运行 arm64 镜像会极慢,甚至在 build 阶段卡死。

升级结果

  • ✅ 使用 Node.js 20 正常运行
  • ✅ 构建时间 5-6 分钟
  • ✅ 镜像体积更小,构建速度提升

其他优化

除了升级 Node.js 版本,我们还做了以下优化:

  1. 移除过时的 mkdirp - 使用 fs.mkdirSync 替代
  2. tsconfig.json 添加 isolatedModules - 优化加速构建
  3. 添加 package-lock.json - 锁定依赖版本
  4. ts-node 替换为 tsx - 解决 Node.js 20+ 的性能问题

后续优化方向

  1. 继续调整镜像包大小,进一步加快构建速度
  2. 为 E2E 测试做准备(后续可以考虑添加 Playwright/Cypress)
  3. 关注 Node.js 22,准备按需升级

Node.js 版本参考

Node.js 官方版本维护周期