fix(deploy,docs): 修好 Docker 构建(缺 prisma generate)+ 新增 SQLite 单容器 compose
- Dockerfile:构建阶段补 `pnpm --filter @classhelper/server run db:generate`。生成产物 packages/server/src/generated/prisma 是 gitignored 的,而 pnpm install 用了 --ignore-scripts 跳过 postinstall,少了这一步 tsc 会报 "Cannot find module ../generated/prisma/client.js"(从 git clone 构建必踩) - 新增 deploy/docker-compose.sqlite.yml + deploy/.env.sqlite.example:只跑服务端一个容器(DATABASE_URL=file:/app/data/classhelper.db + 数据卷),首次启动靠 AUTO_MIGRATE=true 自动建表与建管理员。适合内存小的机器或与别的服务共用一台机器(MySQL 变体会多一个数据库进程) - docs/production.md:补 2.1 单容器变体说明(用法、适用场景、端口/生产自检注意事项、备份命令)
This commit is contained in:
1 parent
5c27586af9
commit
9c678b3730
4 files changed
+119
No files matched your search
@@ -0,0 +1,36 @@
|
||||
# ---------------------------------------------------------------------------
|
||||
# 班级小助手 · Docker 单容器(SQLite)环境变量
|
||||
# 复制为 deploy/.env.sqlite 后填写:cp deploy/.env.sqlite.example deploy/.env.sqlite
|
||||
# 配合 deploy/docker-compose.sqlite.yml 使用
|
||||
# ---------------------------------------------------------------------------
|
||||
|
||||
# 服务端对外端口(宿主机)。注意与同机其他服务错开:80/443 常被反代占用
|
||||
SERVER_PORT=4000
|
||||
|
||||
# 应用版本(镜像标签)
|
||||
APP_VERSION=0.1.0
|
||||
|
||||
# JWT 签名密钥(必填,必须 ≥32 位;不能包含 secret / change-me 等示例词)
|
||||
# 生成:node -e "console.log(require('crypto').randomBytes(48).toString('hex'))"
|
||||
JWT_SECRET=
|
||||
|
||||
# 令牌有效期
|
||||
JWT_EXPIRES_IN=7d
|
||||
|
||||
# 允许的跨域来源;用域名访问时建议写成具体来源,例如 https://class.example.com
|
||||
CORS_ORIGIN=*
|
||||
|
||||
# 首次启动创建的管理员账号(**部署后请立即登录修改密码**)
|
||||
INITIAL_ADMIN_USERNAME=admin
|
||||
INITIAL_ADMIN_PASSWORD=admin123
|
||||
|
||||
# 各类账号的默认初始密码(新增/重置时使用)
|
||||
DEFAULT_STUDENT_PASSWORD=123456
|
||||
DEFAULT_CLASS_PASSWORD=123456
|
||||
DEFAULT_TEACHER_PASSWORD=123456
|
||||
|
||||
# 第 1 教学周的周一(用于"当前周次")
|
||||
TERM_START_DATE=2026-08-31
|
||||
|
||||
# 日志级别:debug | info | warn | error
|
||||
LOG_LEVEL=info
|
||||
@@ -33,7 +33,12 @@ RUN pnpm install --frozen-lockfile --ignore-scripts
|
||||
# 再拷贝源码并构建(只构建服务端与 Web 管理端,桌面客户端不参与)
|
||||
COPY packages ./packages
|
||||
COPY scripts ./scripts
|
||||
|
||||
# 必须先生成 Prisma Client:`pnpm install --ignore-scripts` 跳过了 postinstall,
|
||||
# 而生成产物 `packages/server/src/generated/prisma` 是 gitignored 的(clone 下来没有),
|
||||
# 少了这一步下面的 tsc 会报 "Cannot find module '../generated/prisma/client.js'"。
|
||||
RUN pnpm build:shared \
|
||||
&& pnpm --filter @classhelper/server run db:generate \
|
||||
&& pnpm --filter @classhelper/server build \
|
||||
&& pnpm --filter @classhelper/web-admin build
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
# 班级小助手 · Docker 单容器部署(SQLite + 数据卷)
|
||||
#
|
||||
# 适用:云服务器 / 与别的服务共用一台机器。相比 deploy/docker-compose.yml(MySQL 变体)
|
||||
# 少跑一个数据库容器,内存占用小很多;数据落在 Docker 卷 classhelper-data 里。
|
||||
#
|
||||
# 使用:
|
||||
# 1) cp deploy/.env.sqlite.example deploy/.env.sqlite 并填 JWT_SECRET / 管理员密码
|
||||
# (生成密钥:node -e "console.log(require('crypto').randomBytes(48).toString('hex'))")
|
||||
# 2) docker compose -f deploy/docker-compose.sqlite.yml --env-file deploy/.env.sqlite up -d --build
|
||||
# 3) 访问:http://<服务器IP>:${SERVER_PORT}/
|
||||
#
|
||||
# 首次启动(AUTO_MIGRATE=true)会自动执行 prisma/migrations 里的建表语句并创建管理员账号,
|
||||
# 见 packages/server/src/lib/db-bootstrap.ts("Docker 挂载空数据卷"就是它的目标场景之一)。
|
||||
#
|
||||
# 备份:docker run --rm -v classhelper-sqlite_classhelper-data:/data -v "$PWD":/backup alpine \
|
||||
# tar czf /backup/classhelper-db.tar.gz -C /data .
|
||||
|
||||
name: classhelper-sqlite
|
||||
|
||||
services:
|
||||
server:
|
||||
build:
|
||||
context: ..
|
||||
dockerfile: deploy/Dockerfile
|
||||
target: runtime
|
||||
image: classhelper-server:${APP_VERSION:-0.1.0}
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
NODE_ENV: production
|
||||
HOST: 0.0.0.0
|
||||
PORT: 4000
|
||||
DATABASE_PROVIDER: sqlite
|
||||
# 必须写绝对路径:容器里 serverRoot 是 /app/server,相对路径会解析到别处
|
||||
DATABASE_URL: file:/app/data/classhelper.db
|
||||
# 首启动自动建表 + 建管理员;生产自检会拒绝 dev.db 与过短的 JWT_SECRET
|
||||
AUTO_MIGRATE: 'true'
|
||||
STARTUP_DB_CHECK: 'true'
|
||||
JWT_SECRET: ${JWT_SECRET:?请在 deploy/.env.sqlite 中设置(≥32 位随机串)}
|
||||
JWT_EXPIRES_IN: ${JWT_EXPIRES_IN:-7d}
|
||||
CORS_ORIGIN: ${CORS_ORIGIN:-*}
|
||||
TRUST_PROXY: '1'
|
||||
RATE_LIMIT_ENABLED: 'true'
|
||||
LOG_LEVEL: ${LOG_LEVEL:-info}
|
||||
TERM_START_DATE: ${TERM_START_DATE:-}
|
||||
INITIAL_ADMIN_USERNAME: ${INITIAL_ADMIN_USERNAME:-admin}
|
||||
INITIAL_ADMIN_PASSWORD: ${INITIAL_ADMIN_PASSWORD:-admin123}
|
||||
DEFAULT_STUDENT_PASSWORD: ${DEFAULT_STUDENT_PASSWORD:-123456}
|
||||
DEFAULT_CLASS_PASSWORD: ${DEFAULT_CLASS_PASSWORD:-123456}
|
||||
DEFAULT_TEACHER_PASSWORD: ${DEFAULT_TEACHER_PASSWORD:-123456}
|
||||
ports:
|
||||
- '${SERVER_PORT:-4000}:4000'
|
||||
volumes:
|
||||
- classhelper-data:/app/data
|
||||
|
||||
volumes:
|
||||
classhelper-data:
|
||||
@@ -125,6 +125,28 @@ docker compose -f deploy/docker-compose.yml --env-file deploy/.env up -d --build
|
||||
- 反向代理上启用 HTTPS:见 `deploy/nginx.conf`,并在服务端环境变量中设置
|
||||
`TRUST_PROXY=1`、`CORS_ORIGIN=https://你的域名`。
|
||||
|
||||
### 2.1 单容器变体(SQLite,推荐给内存小的机器 / 与别的服务共用一台机器)
|
||||
|
||||
`deploy/docker-compose.sqlite.yml` 只跑**服务端一个容器**,不额外起 MySQL:数据落在 Docker 卷
|
||||
`classhelper-data` 的 `/app/data/classhelper.db`,首次启动由 `AUTO_MIGRATE=true` 自动建表并创建管理员
|
||||
(`packages/server/src/lib/db-bootstrap.ts` 的"空数据卷"分支)。
|
||||
|
||||
```bash
|
||||
cp deploy/.env.sqlite.example deploy/.env.sqlite # 填 JWT_SECRET、管理员密码、端口
|
||||
docker compose -f deploy/docker-compose.sqlite.yml --env-file deploy/.env.sqlite up -d --build
|
||||
```
|
||||
|
||||
适用场景与注意点:
|
||||
|
||||
- 机器内存紧张(比如 2G 小机器上还跑着别的服务)时,比 MySQL 变体少一个数据库进程;
|
||||
- 端口用 `SERVER_PORT` 指定,**别抢占 80/443**(那通常是同机反代占用的);
|
||||
- 生产自检会拒绝 `dev.db` 与过短的 `JWT_SECRET`,因此 `DATABASE_URL` 必须是绝对路径且不含 `dev.db`;
|
||||
- 备份就是整个卷:`docker run --rm -v classhelper-sqlite_classhelper-data:/data -v "$PWD":/backup alpine tar czf /backup/classhelper-db.tar.gz -C /data .`
|
||||
|
||||
> `deploy/Dockerfile` 的构建阶段会先跑 `pnpm --filter @classhelper/server run db:generate`:
|
||||
> 生成产物 `packages/server/src/generated/prisma` 是 gitignored 的,而 `--ignore-scripts` 跳过了
|
||||
> postinstall,少了这一步 `tsc` 会直接编译失败。
|
||||
|
||||
---
|
||||
|
||||
## 三、Linux 原生部署(形态 C,systemd + SQLite)
|
||||
|
||||
Reference in new issue
Block a user