Add Docker deployment as the recommended production setup.
Include Dockerfile, docker-compose on port 3130, npm mirror config, deploy scripts, and DOCKER.md; keep PM2 docs as fallback. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
node_modules
|
||||
.next
|
||||
.git
|
||||
.gitignore
|
||||
.env
|
||||
.env.local
|
||||
.env*.local
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
.DS_Store
|
||||
coverage
|
||||
.cursor
|
||||
README.md
|
||||
docs
|
||||
content/zhouyi/scripts
|
||||
ecosystem.config.cjs
|
||||
scripts/deploy.sh
|
||||
+1
-1
@@ -13,7 +13,7 @@ OPENAI_BASE_URL=https://op.bz121.com/v1
|
||||
# AI 模型
|
||||
OPENAI_MODEL=huihui_ai/gemma-4-abliterated:e4b
|
||||
|
||||
# 服务端口(生产 PM2 默认 3130;本地 dev 仍用 3000)
|
||||
# 服务端口(Docker / PM2 默认 3130;本地 dev 仍用 3000)
|
||||
PORT=3130
|
||||
|
||||
# 运行环境
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
registry=https://registry.npmmirror.com
|
||||
fetch-timeout=600000
|
||||
fetch-retries=5
|
||||
audit=false
|
||||
fund=false
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
# 知命阁(zhimingge)— Next.js standalone 生产镜像
|
||||
FROM node:20-alpine AS base
|
||||
RUN apk add --no-cache libc6-compat
|
||||
|
||||
FROM base AS deps
|
||||
WORKDIR /app
|
||||
COPY package.json package-lock.json .npmrc ./
|
||||
RUN npm ci
|
||||
|
||||
FROM base AS builder
|
||||
WORKDIR /app
|
||||
COPY --from=deps /app/node_modules ./node_modules
|
||||
COPY . .
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
RUN npm run build
|
||||
|
||||
FROM base AS runner
|
||||
WORKDIR /app
|
||||
ENV NODE_ENV=production
|
||||
ENV NEXT_TELEMETRY_DISABLED=1
|
||||
ENV PORT=3130
|
||||
ENV HOSTNAME=0.0.0.0
|
||||
|
||||
RUN addgroup --system --gid 1001 nodejs \
|
||||
&& adduser --system --uid 1001 nextjs
|
||||
|
||||
# standalone 产物
|
||||
COPY --from=builder /app/.next/standalone ./
|
||||
COPY --from=builder /app/.next/static ./.next/static
|
||||
# 卦辞 Markdown(运行时读取)
|
||||
COPY --from=builder /app/content ./content
|
||||
|
||||
RUN mkdir -p public && chown -R nextjs:nodejs /app
|
||||
|
||||
USER nextjs
|
||||
EXPOSE 3130
|
||||
|
||||
CMD ["node", "server.js"]
|
||||
@@ -16,7 +16,8 @@
|
||||
## 文档
|
||||
|
||||
- [产品说明文档(SPEC)](./docs/SPEC.md) — 功能规格、架构、实施分期
|
||||
- [Ubuntu 部署文档(DEPLOY)](./docs/DEPLOY.md) — PM2 部署至 `/opt/zhimingge`
|
||||
- [Docker 部署文档(DOCKER)](./docs/DOCKER.md) — **推荐** 生产部署
|
||||
- [Ubuntu PM2 部署文档(DEPLOY)](./docs/DEPLOY.md) — 备选方案
|
||||
|
||||
## 环境变量
|
||||
|
||||
@@ -40,22 +41,22 @@ pnpm run dev
|
||||
|
||||
访问 http://localhost:3000(`pnpm run dev` 默认端口;生产 PM2 为 **3130**)
|
||||
|
||||
## 生产部署(摘要)
|
||||
## 生产部署(Docker,推荐)
|
||||
|
||||
```bash
|
||||
cd /opt/zhimingge
|
||||
cp .env.example .env.local && nano .env.local # 填写 OPENAI_API_KEY,PORT=3130
|
||||
npm install --frozen-lockfile
|
||||
npm run build
|
||||
pm2 start ecosystem.config.cjs
|
||||
pm2 save && pm2 startup
|
||||
cp .env.example .env.local && nano .env.local # 填写 OPENAI_API_KEY
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
服务监听 **3130** 端口:`http://服务器IP:3130`
|
||||
服务监听 **3130** 端口。完整说明见 [docs/DOCKER.md](./docs/DOCKER.md)。
|
||||
|
||||
日常更新:`bash scripts/deploy.sh`
|
||||
日常更新:`bash scripts/docker-deploy.sh`
|
||||
|
||||
完整步骤见 [docs/DEPLOY.md](./docs/DEPLOY.md)。
|
||||
### PM2 部署(备选)
|
||||
|
||||
见 [docs/DEPLOY.md](./docs/DEPLOY.md)。
|
||||
|
||||
## 目录说明
|
||||
|
||||
@@ -66,8 +67,11 @@ zhimingge/
|
||||
├── content/zhouyi/ # 64 卦 Markdown 原文
|
||||
├── docs/ # 项目文档
|
||||
├── lib/ # 工具与数据
|
||||
├── ecosystem.config.cjs # PM2 配置
|
||||
└── scripts/deploy.sh # 服务器更新脚本
|
||||
├── Dockerfile # Docker 生产镜像
|
||||
├── docker-compose.yml # Docker Compose 配置
|
||||
├── ecosystem.config.cjs # PM2 配置(备选)
|
||||
├── scripts/docker-deploy.sh # Docker 更新脚本
|
||||
└── scripts/deploy.sh # PM2 更新脚本(备选)
|
||||
```
|
||||
|
||||
## 技术栈
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
services:
|
||||
zhimingge:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile
|
||||
image: zhimingge:latest
|
||||
container_name: zhimingge
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "3130:3130"
|
||||
env_file:
|
||||
- .env.local
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
PORT: "3130"
|
||||
HOSTNAME: "0.0.0.0"
|
||||
+34
-1
@@ -1,7 +1,9 @@
|
||||
# 知命阁(zhimingge)Ubuntu 部署文档
|
||||
# 知命阁(zhimingge)Ubuntu 部署文档(PM2 备选)
|
||||
|
||||
> 仓库:[https://git.bz121.com/dekun/zhimingge.git](https://git.bz121.com/dekun/zhimingge.git)
|
||||
|
||||
> **推荐改用 Docker 部署**,见 [DOCKER.md](./DOCKER.md)。本文档保留 PM2 手动部署说明。
|
||||
|
||||
本文档说明在 **Ubuntu 服务器**上使用 **root 用户**、**PM2** 将知命阁部署到 **`/opt/zhimingge`** 的完整流程。
|
||||
|
||||
---
|
||||
@@ -391,6 +393,37 @@ pm2 logs zhimingge --lines 100
|
||||
| 构建 OOM | 内存不足 | 增加 swap 或升级内存 |
|
||||
| 流式输出中断 | Nginx 缓冲 | 设置 `proxy_buffering off` |
|
||||
| Git pull 失败 | 凭据过期 | 重新配置 Token 或 SSH |
|
||||
| `npm install` 长时间无输出 | 官方 npm 源慢 / 下载 `@next/swc` 等大包 | 见下方「npm 安装卡住」 |
|
||||
|
||||
### npm 安装卡住
|
||||
|
||||
国内服务器访问 `registry.npmjs.org` 常极慢,表现为 `npm install` 只有转圈、无进度。
|
||||
|
||||
**1. 先 Ctrl+C 中断,改用国内镜像:**
|
||||
|
||||
```bash
|
||||
cd /opt/zhimingge
|
||||
npm config set registry https://registry.npmmirror.com
|
||||
npm config set fetch-timeout 600000
|
||||
npm install --no-audit --no-fund --loglevel=info
|
||||
```
|
||||
|
||||
项目根目录已包含 `.npmrc`(`git pull` 后自动生效),也可直接:
|
||||
|
||||
```bash
|
||||
git pull origin main
|
||||
npm install --loglevel=info
|
||||
```
|
||||
|
||||
**2. 看卡在哪一步**(可选):
|
||||
|
||||
```bash
|
||||
npm install --loglevel=verbose 2>&1 | tee /tmp/npm-install.log
|
||||
```
|
||||
|
||||
若长时间停在 `@next/swc-*` 或 `sharp`,属正常现象,多等几分钟;超 10 分钟仍无进展再换镜像重试。
|
||||
|
||||
**3. 内存不足时**(构建阶段 OOM)见下方 Swap 配置。
|
||||
|
||||
### 构建内存不足时增加 Swap
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# 知命阁 Docker 部署
|
||||
|
||||
> 推荐生产部署方式,端口 **3130**
|
||||
|
||||
## 前置条件
|
||||
|
||||
```bash
|
||||
# Ubuntu 安装 Docker
|
||||
apt update
|
||||
apt install -y docker.io docker-compose-v2
|
||||
systemctl enable docker --now
|
||||
docker --version
|
||||
docker compose version
|
||||
```
|
||||
|
||||
## 首次部署
|
||||
|
||||
```bash
|
||||
cd /opt
|
||||
git clone https://git.bz121.com/dekun/zhimingge.git zhimingge
|
||||
cd /opt/zhimingge
|
||||
|
||||
# 环境变量(必填 OPENAI_API_KEY)
|
||||
cp .env.example .env.local
|
||||
nano .env.local
|
||||
chmod 600 .env.local
|
||||
|
||||
# 构建并启动
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
访问:`http://服务器IP:3130`
|
||||
|
||||
## 日常更新
|
||||
|
||||
```bash
|
||||
cd /opt/zhimingge
|
||||
bash scripts/docker-deploy.sh
|
||||
```
|
||||
|
||||
或手动:
|
||||
|
||||
```bash
|
||||
git pull origin main
|
||||
docker compose build
|
||||
docker compose up -d
|
||||
```
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
docker compose ps # 状态
|
||||
docker compose logs -f zhimingge # 日志
|
||||
docker compose restart zhimingge # 重启
|
||||
docker compose down # 停止并删除容器
|
||||
docker compose up -d --build # 重建并启动
|
||||
```
|
||||
|
||||
## 环境变量
|
||||
|
||||
通过 `.env.local` 注入容器(见 `docker-compose.yml` 的 `env_file`):
|
||||
|
||||
| 变量 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `OPENAI_API_KEY` | 是 | AI 接口密钥 |
|
||||
| `OPENAI_BASE_URL` | 否 | 默认 `https://op.bz121.com/v1` |
|
||||
| `OPENAI_MODEL` | 否 | 默认 `huihui_ai/gemma-4-abliterated:e4b` |
|
||||
| `PORT` | 否 | 容器内 3130 |
|
||||
|
||||
## 防火墙
|
||||
|
||||
```bash
|
||||
ufw allow 3130
|
||||
# 或使用 Nginx 反代 80/443 → 3130
|
||||
```
|
||||
|
||||
## 从 PM2 迁移
|
||||
|
||||
```bash
|
||||
pm2 stop zhimingge
|
||||
pm2 delete zhimingge
|
||||
cd /opt/zhimingge
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
## 排错
|
||||
|
||||
| 现象 | 处理 |
|
||||
|------|------|
|
||||
| 构建慢 / 超时 | Dockerfile 使用 `.npmrc` 国内镜像;重试 `docker compose build` |
|
||||
| 容器反复重启 | `docker compose logs zhimingge` 查看报错 |
|
||||
| AI 失败 | 检查 `.env.local` 中 `OPENAI_API_KEY` |
|
||||
| 卦辞 404 | 确认镜像内 `/app/content/zhouyi/docs` 存在 |
|
||||
|
||||
构建在镜像内完成,**无需**在宿主机单独 `npm install` / `npm run build`。
|
||||
+9
-1
@@ -16,13 +16,21 @@ git pull origin main
|
||||
echo "==> 安装依赖..."
|
||||
npm ci || npm install
|
||||
|
||||
echo "==> 停止 PM2(避免无构建产物时反复重启)..."
|
||||
pm2 stop "$APP_NAME" 2>/dev/null || true
|
||||
|
||||
echo "==> 生产构建..."
|
||||
npm run build
|
||||
|
||||
if [[ ! -f .next/BUILD_ID ]]; then
|
||||
echo "ERROR: 构建失败,未找到 .next/BUILD_ID,请先解决 npm run build 报错后再启动。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> 确保日志目录存在..."
|
||||
mkdir -p logs
|
||||
|
||||
echo "==> 重启 PM2..."
|
||||
echo "==> 启动 PM2..."
|
||||
if pm2 describe "$APP_NAME" > /dev/null 2>&1; then
|
||||
pm2 restart "$APP_NAME"
|
||||
else
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
#!/usr/bin/env bash
|
||||
# 知命阁 Docker 部署脚本
|
||||
# 用法:cd /opt/zhimingge && bash scripts/docker-deploy.sh
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
APP_DIR="/opt/zhimingge"
|
||||
APP_PORT="${PORT:-3130}"
|
||||
|
||||
cd "$APP_DIR"
|
||||
|
||||
if [[ ! -f .env.local ]]; then
|
||||
echo "ERROR: 缺少 .env.local,请先:cp .env.example .env.local && nano .env.local"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "==> 拉取最新代码..."
|
||||
git pull origin main
|
||||
|
||||
echo "==> 停止旧 PM2 进程(若存在)..."
|
||||
pm2 stop zhimingge 2>/dev/null || true
|
||||
pm2 delete zhimingge 2>/dev/null || true
|
||||
|
||||
echo "==> 构建 Docker 镜像..."
|
||||
docker compose build
|
||||
|
||||
echo "==> 启动容器..."
|
||||
docker compose up -d
|
||||
|
||||
echo "==> 状态"
|
||||
docker compose ps
|
||||
sleep 2
|
||||
curl -s -o /dev/null -w "HTTP %{http_code}\n" "http://127.0.0.1:${APP_PORT}" || true
|
||||
|
||||
echo "==> 部署完成。日志:docker compose logs -f zhimingge"
|
||||
Reference in New Issue
Block a user