惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

博客园_首页
Security Archives - TechRepublic
Security Archives - TechRepublic
Application and Cybersecurity Blog
Application and Cybersecurity Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
C
CERT Recently Published Vulnerability Notes
S
Security @ Cisco Blogs
S
Security Affairs
D
Darknet – Hacking Tools, Hacker News & Cyber Security
L
Lohrmann on Cybersecurity
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Hacker News: Ask HN
Hacker News: Ask HN
Forbes - Security
Forbes - Security
H
Heimdal Security Blog
A
Arctic Wolf
NISL@THU
NISL@THU
P
Proofpoint News Feed
W
WeLiveSecurity
S
Schneier on Security
AI
AI
Schneier on Security
Schneier on Security
N
News and Events Feed by Topic
L
LINUX DO - 最新话题
Cisco Talos Blog
Cisco Talos Blog
AWS News Blog
AWS News Blog
Hacker News - Newest:
Hacker News - Newest: "LLM"
Know Your Adversary
Know Your Adversary
Scott Helme
Scott Helme
V
Vulnerabilities – Threatpost
Cyberwarzone
Cyberwarzone
I
Intezer
S
Securelist
Help Net Security
Help Net Security
Microsoft Security Blog
Microsoft Security Blog
量子位
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
小众软件
小众软件
Last Week in AI
Last Week in AI
Jina AI
Jina AI
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
WordPress大学
WordPress大学
罗磊的独立博客
月光博客
月光博客
雷峰网
雷峰网
A
About on SuperTechFans
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
MongoDB | Blog
MongoDB | Blog
大猫的无限游戏
大猫的无限游戏
博客园 - 司徒正美
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events

博客园 - lizhigang

DBeaver 打开 utf8的sql文件 SMT 贴片机与 MES 系统集成指南 容器访问外部服务(10.100.1.90:9090)防火墙规则配置总结 Docker 容器间通信故障排查与修复操作总结 Docker 容器部署与运维总结报告 Nginx Docker 容器白名单配置操作总结 使用 pnpm 构建 Vue2 项目操作总结(Node 16 → Node 22) Windows 11 下使用 MySQL Workbench 还原多数据库备份文件操作指南 在 WSL2 + Docker Desktop 环境下构建前后端 Docker 镜像 从内网私有仓库迁移镜像到阿里云 ACR 完整指南 wsl网络设置允许访问ssh(端口22) 在 Windows 11 上安装 Docker Nginx配置 访问数据库报错 Windows系统运行RuoYi-Vue完整指南 RuoYi-Vue 项目结构分析 win11 报错 windows 11 如何使用 Microsoft Hyper-V VMware 替代产品 IntelliJ IDEA 社区版支持 Spring Boot 开发说明文档 imes开发部署(IDEA社区版 差异) IntelliJ IDEA 社区版默认支持 Spring Boot 吗? imes开发部署 IDEA 端口被占用 解决办法 使用MySQL Workbench进行数据库备份 ruoyi-nbcio ktg-mes、ktm-mes-ui部署 Widows下安装和配置Redis Windows下Redis安装与配置全攻略 mes开源 imes:注意 若依框架:开源
前端项目 Docker 镜像构建完整操作总结
lizhigang · 2026-05-25 · via 博客园 - lizhigang

https://chat.deepseek.com/share/ig4uqvz52enmzv2fj1

前端项目 Docker 镜像构建完整操作总结

一、背景与问题

1.1 初始现象

在 CI 环境中使用 Docker 构建前端项目(Vue + pnpm)时,出现两种错误:

  1. JavaScript heap out of memory
    日志:FATAL ERROR: Ineffective mark-compacts near heap limit Allocation failed
  2. destination cannot be a symlink /bin
    日志:destination cannot be a symlink /bin(通常发生在 COPY . . 时)

1.2 原因分析

错误 直接原因 解决方案
堆内存溢出 Node.js 默认堆内存上限仅 1.4GB,前端构建需要更大内存(峰值 > 2GB) 通过环境变量增加内存限制
符号链接错误 工作目录变为根目录 /,导致复制文件时与系统目录冲突 使用绝对路径作为工作目录(如 /app-pnpm),避免变量失效

二、解决方案总览

  1. 使用官方 node:22-slim 基础镜像(Debian 精简版,兼容性好,体积适中)。
  2. 在 Dockerfile 中设置 Node.js 堆内存上限(4GB 或 8GB)。
  3. 采用硬编码工作目录/app-pnpm),避免使用 ARG 变量可能引发的作用域问题。
  4. node:22-slim 推送至公司私有仓库,供 CI 使用。

三、详细操作步骤

3.1 获取并推送 node:22-slim 到私有仓库

如果 CI 服务器无法直接访问 Docker Hub,需要先在有外网的机器上获取镜像,再推送到公司私有仓库。

步骤 1:拉取官方镜像

docker pull node:22-slim

步骤 2:打标签(指向私有仓库)

假设私有仓库地址为 devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/base

docker tag node:22-slim devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/base/node:22-slim

步骤 3:登录私有仓库(如需认证)

docker login devops.inspur.com:80
# 输入用户名和密码

步骤 4:推送镜像

docker push devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/base/node:22-slim

步骤 5:在 CI 服务器上验证

docker pull devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/base/node:22-slim
docker run --rm -it devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/base/node:22-slim node -v
# 应输出 v22.22.3 或更高版本

备选方案(离线传输)
如果 CI 服务器完全隔离,可使用 docker save 导出 tar 包,通过 scp 传输后 docker load 导入。


3.2 编写最终的 Dockerfile

以下 Dockerfile 采用硬编码绝对路径,无任何 ARG 变量依赖,可直接用于构建。

# 定义基础镜像来源(可根据需要修改为私有仓库地址)
ARG build_from=devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/base/node:22-slim
ARG run_from=devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/base/nginx:alpine

# ========== 阶段一:构建前端产物 ==========
FROM ${build_from} AS build

# 设置绝对路径工作目录
WORKDIR /app-pnpm

# 复制项目所有文件
COPY . .

# 【关键】增加 Node.js 堆内存上限(解决 OOM)
ENV NODE_OPTIONS="--max-old-space-size=4096"   # 可改为 8192

# 启用 pnpm,设置镜像源,安装依赖并构建
RUN corepack enable && corepack prepare pnpm@latest --activate && \
    pnpm config set registry https://registry.npmmirror.com && \
    pnpm install && \
    pnpm run build:prod

# ========== 阶段二:Nginx 运行静态文件 ==========
FROM ${run_from}

# 从构建阶段复制编译产物(使用绝对路径)
COPY --from=build /app-pnpm/dist /usr/share/nginx/html

# 复制 Nginx 配置模板(支持环境变量替换)
COPY nginx.conf.template /etc/nginx/nginx.conf.template
WORKDIR /etc/nginx/

EXPOSE 80

# 启动 Nginx,并替换 ${BACKEND_SERVICE} 变量
ENTRYPOINT envsubst '$BACKEND_SERVICE' < nginx.conf.template > ./conf.d/default.conf && \
    cat ./conf.d/default.conf && \
    nginx -g 'daemon off;'

说明

  • 工作目录固定为 /app-pnpm,复制和引用时均使用此绝对路径。
  • ENV NODE_OPTIONS="--max-old-space-size=4096" 确保 Node.js 构建时内存充足。
  • 若项目需要 --openssl-legacy-provider,可合并设置:
    ENV NODE_OPTIONS="--max-old-space-size=4096 --openssl-legacy-provider"

3.3 构建镜像

在项目根目录(包含 Dockerfile)执行:

# 本地构建测试
docker build -t frontend:latest .

# 推送到私有仓库(可选)
docker tag frontend:latest devops.inspur.com:80/your-project/frontend:tag
docker push devops.inspur.com:80/your-project/frontend:tag

CI 流水线集成:将上述构建命令直接放入 CI 脚本即可,无需额外调整。


四、验证与常见问题

4.1 验证内存设置是否生效

在 Dockerfile 中临时添加一行诊断(位于 ENV NODE_OPTIONS 之后):

RUN node -e "console.log('Heap limit:', require('v8').getHeapStatistics().heap_size_limit / 1024 / 1024, 'MB')"

构建时输出应显示 4096 MB8192 MB

4.2 常见问题排查

问题 可能原因 解决方法
仍然 OOM 分配的内存不够 --max-old-space-size 提高到 8192,并确保 Docker 容器内存 ≥ 8GB(docker run --memory=8g
COPY --from=build 找不到 /app-pnpm/dist 构建阶段未成功生成 dist 目录 检查构建命令 pnpm run build:prod 是否正常输出到 dist
envsubst: command not found 基础镜像缺少 envsubst nginx:alpine 默认包含,若使用其他镜像需安装 gettext
构建时网络超时 镜像源访问慢 已配置淘宝镜像源,若仍需代理可设置 HTTP_PROXY
私有仓库证书错误 自签名证书 在 Docker 客户端配置 insecure-registries

五、最终总结

5.1 核心修改点

原问题 修复措施
Node.js 堆内存溢出 添加 ENV NODE_OPTIONS="--max-old-space-size=4096"
工作目录错误导致符号链接冲突 使用硬编码绝对路径 WORKDIR /app-pnpm,避免变量依赖
基础镜像不稳定 统一使用官方 node:22-slim 并推送至私有仓库

5.2 操作清单

  • 获取 node:22-slim 镜像并推送至私有仓库
  • 编写上述 Dockerfile(已包含 OOM 修复)
  • 执行 docker build 构建
  • 推送到镜像仓库(如需)
  • 在 CI 流水线中验证构建成功

5.3 构建结果示例

### 镜像构建成功 ...
Pushed image to devops.inspur.com:80/ite/mes/repo/local_repo/imes-docker/imes/imes-ui-pnpm:develop-pnpm-9-...

本总结可直接交付给开发或运维团队,作为标准操作文档使用。