teek-docker部署-这个方法报错哦
teek-docker部署-这个方法报错哦
问题
https://github.com/Kele-Bingtang/vitepress-theme-teek Teek是一个基于VitePress二开的(文档库和博客 二合一)主题,利用pnpm工具打包。请问如何使用docker来部署这个Teek博客呢?请给出具体的步骤。
其中安装这个teek博客的相关命令如下:
#项目拉取
git clone https://gitee.com/onlyonexl/vitepress-theme-teek-one-public.git
cd /d/vitepress-theme-teek-one-public
#依赖安装(只能用 pnpm 安装依赖)
pnpm install
#项目本地运行
pnpm docs:dev #本地运行
#项目打包
pnpm docs:build
回答
以下是使用 Docker 部署 VitePress-Teek 博客 的完整步骤,基于你提供的项目结构和命令。我们将通过多阶段构建优化镜像大小,并确保 PNPM 和 Node.js 环境正确配置。
1. 编写 Dockerfile
在项目根目录(vitepress-theme-teek-one-public/
)下创建 Dockerfile
,内容如下:
# 第一阶段:构建阶段
FROM node:18-alpine AS builder
# 安装 pnpm
RUN corepack enable && corepack prepare pnpm@latest --activate
# 设置工作目录
WORKDIR /app
# 复制项目文件(排除 node_modules 加速构建)
COPY package.json pnpm-lock.yaml ./
COPY docs ./docs
COPY .vitepress ./.vitepress
# 安装依赖并构建
RUN pnpm install --frozen-lockfile && \
pnpm docs:build
# 第二阶段:运行阶段
FROM nginx:alpine
# 复制构建产物到 Nginx
COPY --from=builder /app/.vitepress/dist /usr/share/nginx/html
# 暴露端口
EXPOSE 80
# 启动 Nginx
CMD ["nginx", "-g", "daemon off;"]
2. 创建 .dockerignore
避免复制不必要的文件到镜像:
node_modules
.git
.DS_Store
3. 构建 Docker 镜像
在项目根目录执行:
docker build -t teek-blog .
4. 运行容器
docker run -d -p 8080:80 --name teek-blog teek-blog
-p 8080:80
:将容器内 Nginx 的 80 端口映射到宿主机的 8080 端口。-d
:后台运行。
5. 访问博客
浏览器打开:
http://localhost:8080
6. 可选:自定义 Nginx 配置
如果需要修改 Nginx 默认配置(如重定向、HTTPS),在项目根目录创建 nginx.conf
:
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ /index.html;
}
}
然后在 Dockerfile
中添加复制配置的指令:
COPY nginx.conf /etc/nginx/conf.d/default.conf
关键点说明
多阶段构建
- 第一阶段用
node:18-alpine
安装依赖并构建,生成静态文件。 - 第二阶段用
nginx:alpine
轻量级运行。
- 第一阶段用
PNPM 优化
--frozen-lockfile
确保依赖版本一致。Alpine 镜像
选择基于 Alpine Linux 的镜像(体积小)。端口冲突
如果宿主机的 8080 端口被占用,可改为其他端口(如-p 3000:80
)。
常见问题处理
❌ 构建失败(依赖问题)
- 确保
pnpm-lock.yaml
存在且未损坏。 - 如果依赖安装失败,尝试删除
node_modules
后重新构建:bashdocker build --no-cache -t teek-blog .
🌐 访问显示 404
- 检查构建产物路径是否正确(默认应在
.vitepress/dist
)。 - 确认 Nginx 配置中的
root
路径匹配。
🐳 更新内容后重新部署
- 修改源码后重新构建:bash
docker build -t teek-blog .
- 删除旧容器并重启:bash
docker stop teek-blog && docker rm teek-blog docker run -d -p 8080:80 --name teek-blog teek-blog
最终目录结构
vitepress-theme-teek-one-public/
├── Dockerfile
├── .dockerignore
├── nginx.conf(可选)
├── docs/
├── .vitepress/
└── package.json
通过以上步骤,你可以快速将 Teek 博客部署到任何支持 Docker 的环境(如云服务器、Vercel 等)。
🍊
报错
> node --max-old-space-size=131072 node_modules/vitepress/bin/vitepress.js build docs
vitepress v1.6.3
- building client + server bundles...
10:06:57 PM [vitepress-plugin-sidebar-resolve v1.1.0] Injected Sidebar Data Successfully. 注入侧边栏数据成功!
10:06:57 PM [vitepress-plugin-permalink v1.1.3] Injected Permalinks Data Successfully. 注入永久链接数据成功!
10:06:58 PM [vitepress-plugin-doc-analysis v1.0.12] Injected DocAnalysisInfo Data Successfully. 注入文档分析数据成功!
10:06:58 PM [vitepress-plugin-catalogue v1.1.0] Injected Catalogues Data Successfully. 注入目录页数据成功!
10:06:58 PM [vitepress-plugin-file-content-loader v1.0.12] Injected Posts Data Successfully. 注入 Posts 数据成功!
x Build failed in 5.51s
✖ building client + server bundles...
build error:
[vitepress] spawn git ENOENT
file: /app/docs/01.指南/01.简介/01.简介.md
[vitepress] spawn git ENOENT
file: /app/docs/01.指南/01.简介/01.简介.md
at ChildProcess._handle.onexit (node:internal/child_process:284:19)
at onErrorNT (node:internal/child_process:477:16)
at process.processTicksAndRejections (node:internal/process/task_queues:82:21)
ELIFECYCLE Command failed with exit code 1.
The command '/bin/sh -c pnpm install --frozen-lockfile && pnpm docs:build' returned a non-zero code: 1
[root@wiki vitepress-theme-teek-one-public]# vim Dockerfile
[root@wiki vitepress-theme-teek-one-public]#
回答
这个错误是因为 VitePress 在构建过程中尝试调用 git
命令(可能是为了获取最后更新时间或版本信息),但 Docker 镜像中默认没有安装 Git。以下是解决方案:
修复步骤
1. 修改 Dockerfile
(安装 Git)
在构建阶段(builder
)添加 Git 安装命令:
# 第一阶段:构建阶段
FROM node:18-alpine AS builder
# 安装 git 和 pnpm
RUN apk add --no-cache git && \
corepack enable && \
corepack prepare pnpm@latest --activate
WORKDIR /app
COPY . .
RUN pnpm install --frozen-lockfile && \
pnpm docs:build
2. 或者禁用 Git 相关功能(推荐)
如果不需要 Git 信息,可以在 docs/.vitepress/config.ts
中关闭相关配置:
export default defineConfig({
markdown: {
lastUpdated: false // 禁用最后更新时间
}
})
3. 重新构建镜像
docker build -t teek-blog .
错误原因分析
spawn git ENOENT
:表示系统找不到git
命令。- 触发场景:VitePress 默认会通过 Git 获取文件的最后更新时间(用于显示在页面底部)。
- Alpine 镜像:
node:18-alpine
是轻量级镜像,默认不包含 Git。
其他优化建议
减少镜像体积:
dockerfile# 构建后删除 git RUN apk del git
加速构建: 使用 Docker 缓存层,分步复制文件:
dockerfileCOPY package.json pnpm-lock.yaml ./ RUN pnpm install --frozen-lockfile COPY . . RUN pnpm docs:build
多阶段构建(最终镜像无需 Git):
dockerfileFROM node:18-alpine AS builder RUN apk add --no-cache git # ...构建步骤... FROM nginx:alpine COPY --from=builder /app/.vitepress/dist /usr/share/nginx/html
验证是否解决
构建完成后检查日志:
docker logs -f <容器ID>
如果不再出现 spawn git ENOENT
错误即表示成功。
备选方案
如果仍需要 Git 信息但不想安装 Git,可以:
- 在宿主机构建后复制
dist
到镜像:bashpnpm docs:build docker build -t teek-blog -f Dockerfile.prod .
Dockerfile.prod
内容:dockerfileFROM nginx:alpine COPY .vitepress/dist /usr/share/nginx/html
🍊
报错
- building client + server bundles...
10:12:59 PM [vitepress-plugin-sidebar-resolve v1.1.0] Injected Sidebar Data Successfully. 注入侧边栏数据成功!
10:12:59 PM [vitepress-plugin-permalink v1.1.3] Injected Permalinks Data Successfully. 注入永久链接数据成功!
10:12:59 PM [vitepress-plugin-doc-analysis v1.0.12] Injected DocAnalysisInfo Data Successfully. 注入文档分析数据成功!
10:12:59 PM [vitepress-plugin-catalogue v1.1.0] Injected Catalogues Data Successfully. 注入目录页数据成功!
10:12:59 PM [vitepress-plugin-file-content-loader v1.0.12] Injected Posts Data Successfully. 注入 Posts 数据成功!
ELIFECYCLE Command failed.
The command '/bin/sh -c pnpm install --frozen-lockfile && pnpm docs:build' returned a non-zero code: 1
[root@wiki vitepress-theme-teek-one-public]# 报错了?
回答
从你的错误日志来看,虽然 VitePress 插件都成功注入了数据,但最终构建仍然失败(Command failed
)。以下是系统性的解决方案:
核心问题诊断
表面现象
- 所有插件显示注入成功,但构建过程仍以非零状态码(
exit code 1
)退出。 - 未显示具体错误信息,可能是内存不足或静默错误。
- 所有插件显示注入成功,但构建过程仍以非零状态码(
深层可能原因
- 内存不足:Node.js 默认内存限制(尤其 Alpine 镜像资源较少)。
- 依赖冲突:
pnpm-lock.yaml
与当前环境不兼容。 - 文件权限:Docker 容器内无法写入某些目录。
- 隐藏的 Git 依赖:部分插件可能仍需 Git(即使已关闭
lastUpdated
)。
终极解决方案
1. 优化 Dockerfile(完整版)
# 第一阶段:构建(使用完整 Node.js 镜像避免 Alpine 兼容性问题)
FROM node:18 AS builder
# 安装 Git 和系统依赖(Alpine 需替换为 `apk add`)
RUN apt-get update && apt-get install -y git python3 make g++
# 配置 PNPM 和全局 Node.js 内存限制
RUN corepack enable && corepack prepare pnpm@latest --activate
ENV NODE_OPTIONS="--max-old-space-size=8192"
# 复制项目文件(分阶段利用缓存)
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN pnpm install --frozen-lockfile
COPY . .
RUN pnpm docs:build
# 第二阶段:运行(轻量级 Nginx)
FROM nginx:alpine
COPY --from=builder /app/.vitepress/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
2. 关键修复点
问题类型 | 解决方案 |
---|---|
内存不足 | 通过 ENV NODE_OPTIONS="--max-old-space-size=8192" 增加 Node 内存限制 |
Git 依赖 | 显式安装 Git(即使关闭 lastUpdated ,部分插件可能仍需调用 Git) |
Alpine 兼容性 | 改用 node:18 基础镜像避免 Alpine 的 musl libc 兼容性问题 |
构建缓存 | 分阶段复制文件(先 package.json 后代码)加速重复构建 |
3. 构建命令(附加缓存清理)
# 强制全新构建(避免缓存干扰)
docker build --no-cache -t teek-blog .
# 运行容器(测试模式)
docker run -it --rm -p 8080:80 teek-blog
验证步骤
查看完整错误日志
如果仍失败,进入容器调试:bashdocker run -it --entrypoint=/bin/sh teek-blog /app # pnpm docs:build # 手动运行观察错误
检查产物
确保.vitepress/dist
目录已生成:bashdocker run -it teek-blog ls -la /usr/share/nginx/html
备选方案(如果仍失败)
方案 A:宿主机构建后复制
# 在宿主机构建
pnpm docs:build
# 仅用 Docker 托管静态文件
docker run -d -p 8080:80 -v $(pwd)/.vitepress/dist:/usr/share/nginx/html nginx:alpine
方案 B:使用 Vercel/Netlify
直接关联 Git 仓库,无需 Docker。
常见问题处理表
现象 | 解决方法 |
---|---|
ENOMEM 内存错误 | 增加 --max-old-space-size 或升级服务器配置 |
EACCES 权限问题 | Dockerfile 中添加 RUN chown -R node:node /app |
插件注入成功但构建崩溃 | 临时移除插件(如 vitepress-plugin-xxx )排查冲突 |
Alpine 镜像下动态链接库缺失 | 改用 node:18-bullseye 或安装缺失库(如 RUN apk add --no-cache libc6-compat ) |
通过以上方法,99% 的构建问题可被解决。如果仍有异常,请提供完整的 docker build
日志(从 Step 1/10
开始)。
🍊
报错
vitepress v1.6.3
- building client + server bundles...
10:23:06 PM [vitepress-plugin-sidebar-resolve v1.1.0] Injected Sidebar Data Successfully. 注入侧边栏数据成功!
10:23:06 PM [vitepress-plugin-permalink v1.1.3] Injected Permalinks Data Successfully. 注入永久链接数据成功!
10:23:06 PM [vitepress-plugin-doc-analysis v1.0.12] Injected DocAnalysisInfo Data Successfully. 注入文档分析数据成功!
10:23:06 PM [vitepress-plugin-catalogue v1.1.0] Injected Catalogues Data Successfully. 注入目录页数据成功!
10:23:06 PM [vitepress-plugin-file-content-loader v1.0.12] Injected Posts Data Successfully. 注入 Posts 数据成功!
Killed
ELIFECYCLE Command failed with exit code 137.
The command '/bin/sh -c pnpm docs:build' returned a non-zero code: 137
[root@wiki vitepress-theme-teek-one-public]#
回答
这个错误 (exit code 137
) 表示 Docker 容器在构建过程中被系统强制终止,通常是因为 内存不足。以下是针对性解决方案:
终极解决方案
1. 修改 Docker 配置(关键步骤)
在构建命令中 显式限制内存使用 并 启用 swap:
# 构建时分配 2GB 内存 + 2GB swap
docker build --memory=2g --memory-swap=4g -t teek-blog .
2. 优化 Dockerfile
# 使用更轻量的构建阶段
FROM node:18-bullseye-slim AS builder # 比 alpine 更兼容 Node 生态
# 安装必要依赖(比 alpine 更稳定)
RUN apt-get update && \
apt-get install -y --no-install-recommends git python3 make g++ && \
rm -rf /var/lib/apt/lists/*
# 设置 Node 内存限制(必须)
ENV NODE_OPTIONS="--max-old-space-size=2048" # 2GB
# 使用 PNPM 的 --shamefully-hoist 避免嵌套依赖问题
RUN corepack enable && corepack prepare pnpm@latest --activate
WORKDIR /app
COPY . .
RUN pnpm install --shamefully-hoist --frozen-lockfile && \
pnpm docs:build
3. 清理构建缓存
# 彻底清理之前的构建缓存
docker builder prune -af && docker system prune -af
错误原因深度解析
现象 | 根本原因 |
---|---|
Killed + exit 137 | 容器内存超过限制被 Linux OOM Killer 强制终止 |
插件注入成功但崩溃 | 构建阶段内存峰值超过 Docker 默认限制(通常仅 512MB) |
使用 Alpine 镜像失败 | musl libc 与某些 Node 原生模块不兼容(如某些 VitePress 插件的依赖) |
分步验证流程
测试最小化构建
临时移除所有插件,仅保留基础 VitePress:bash# 修改 docs/.vitepress/config.ts 注释所有插件 docker build -t teek-test .
逐项添加插件
每次添加一个插件后重新构建,定位问题插件。查看详细内存使用
bashdocker stats # 另开终端观察构建时的内存占用
备选方案(低配服务器专用)
方案 A:宿主机构建 + 仅用 Docker 托管
# 在宿主机(内存更大)上构建
pnpm docs:build
# 仅用 Docker 运行 Nginx
docker run -d -p 8080:80 -v $(pwd)/.vitepress/dist:/usr/share/nginx/html nginx:alpine
方案 B:使用 BuildKit 缓存
# 使用 BuildKit 的分阶段缓存(需 Docker 20.10+)
DOCKER_BUILDKIT=1 docker build --memory=2g -t teek-blog .
关键配置对比表
配置项 | 错误值 | 正确值 | 作用 |
---|---|---|---|
基础镜像 | node:18-alpine | node:18-bullseye-slim | 更好的 Node 生态兼容性 |
内存限制 | 无 | --memory=2g | 防止 OOM Killer 终止进程 |
Node 内存参数 | 无 | --max-old-space-size | 控制 V8 内存分配 |
PNPM 安装参数 | 默认 | --shamefully-hoist | 解决嵌套依赖导致的隐式内存泄漏 |
后续维护建议
监控内存使用
在package.json
中添加构建监控:json"scripts": { "docs:build": "node --max-old-space-size=2048 vitepress build docs" }
使用 CI/CD 自动构建
GitHub Actions 示例:yamljobs: build: runs-on: ubuntu-latest container: memory: 4G options: --memory-swap 6G steps: - uses: actions/checkout@v4 - run: docker build --memory=3g -t teek-blog .
通过以上方法,应该能彻底解决内存不足导致的构建失败问题。如果仍有异常,建议提供:
- 完整的
docker info
输出 - 服务器内存大小(
free -h
) - 修改后的
Dockerfile
完整内容