背景
前端项目的Base镜像一直使用的是 Node.js 18.20 版本,最近面临升级需求:
- Node.js 18.20 已进入维护末期,后续可能会逐渐出现兼容性问题
- CI 中出现大量版本 Warning,提示需要升级
- 团队内其他项目已在 3 月中旬完成 Node.js 20 的升级
镜像选型分析
| 镜像 | curl/ca-certificates | git | 说明 |
|---|---|---|---|
| node:20 | ✅ | ✅ | 基于 buildpack-deps,包含常用工具 |
| node:20-bullseye / bookworm | ✅ | ✅ | Debian 完整版,最稳定 |
| node:20-slim | ✅ | ❌ | 精简版 |
| node:20-alpine | ❌ | ❌ | 极简版,需手动安装 |
为什么选择 Alpine?
curl和ca-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
主要问题:
- Chrome 仓库密钥在 CI Runner 上会遇到各种网络和版本问题
- 使用 Node.js 20+ 的 bookworm 镜像在某些 Runner 上会遇到 node 无法启动的问题
- 依赖包过大,构建速度慢
解决方案
考虑到 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 版本,我们还做了以下优化:
- 移除过时的 mkdirp - 使用
fs.mkdirSync替代 - tsconfig.json 添加
isolatedModules- 优化加速构建 - 添加 package-lock.json - 锁定依赖版本
- ts-node 替换为 tsx - 解决 Node.js 20+ 的性能问题
后续优化方向
- 继续调整镜像包大小,进一步加快构建速度
- 为 E2E 测试做准备(后续可以考虑添加 Playwright/Cypress)
- 关注 Node.js 22,准备按需升级