01|galgamex 容器化部署实战:从 Dockerfile、Compose 到 Prisma 初始化与首个账号
项目地址:github.com/galgamex/ga...
目标:基于官方开源仓库,本地使用 Docker 与 docker-compose 一键拉起依赖(PostgreSQL、Redis)与 Web 服务;在容器内通过
npx prisma db push
初始化数据库结构,并解决"无初始账号无法登录"的问题。
本文记录我用大模型辅助生成 Dockerfile 与 docker-compose 的完整过程、踩到的坑以及最终的解决方案(包含两条路径:开启邮箱注册 或 直接注入首个管理员账号)。文末附成功截图。
环境与前置
- OS:Ubuntu24(Docker)
- 容器编排:docker-compose v2
- 数据库:PostgreSQL 16
- 缓存:Redis 7
- Node:容器内使用 node:22-slim
项目内关键文件:
projects/galgamex/Dockerfile
projects/galgamex/docker-compose.yml
一、用大模型生成并完善 Dockerfile(要点)
实际产出的 Dockerfile
位于 projects/galgamex/
,关键设计:
- 多阶段构建(deps/builder/runner),最终镜像小、启动快。
- 使用
corepack
启用pnpm@9
,兼容项目脚本中的pnpx
场景。 - 运行阶段使用
node:22-slim
,以非 root 用户启动,安全性更高。 - 启动命令在容器内先执行
npx prisma db push
同步 schema,再npm run build && npm run start -p 3000
。
你可以直接阅读文件:projects/galgamex/Dockerfile
。
二、使用 docker-compose 编排三大服务
projects/galgamex/docker-compose.yml
定义了三个服务:
postgres
:健康检查pg_isready
,数据卷pgdata
持久化。redis
:AOF 开启、健康检查保证就绪。galgamex
:依赖postgres
与redis
健康就绪后再启动,暴露3000:3000
。
其中 Web 服务设置了较完整的环境变量(站点 URL、JWT、邮箱、对象存储、IndexNow 等)。开发阶段可以保留默认值,生产需要按需替换。
启动命令:
bash
# 首次构建并启动
docker compose -f projects/galgamex/docker-compose.yml up -d --build
# 观察启动日志
docker compose -f projects/galgamex/docker-compose.yml logs -f galgamex
三、初始化数据库结构:Prisma db push
该项目采用 Prisma 管理数据库结构。容器启动时,Dockerfile
的 CMD
会先执行:
bash
npx prisma db push
这一步会根据 schema.prisma
将模型同步到数据库。若希望手动重试,也可执行:
bash
# 进入 Web 容器并手动同步(当你修改了 Prisma 模型,或需要二次尝试时)
docker compose -f projects/galgamex/docker-compose.yml exec galgamex sh -lc "npx prisma db push"
注意:db push
只同步结构,不会插入任何初始数据(例如默认管理员)。
四、拦路虎:没有初始账号,无法登录
- 现象:首次启动后,页面可访问,但由于没有默认账号,登录受阻。
- 思路:
- 开启"注册"能力,通过配置邮箱完成注册;
- 直接向数据库注入首个账号(或使用 Prisma 的种子/脚本)。
下面给出两条可行实践路径。
路径 A:配置邮箱,开放注册(适合不急于分配管理员的场景)
-
在
docker-compose.yml
的galgamex.environment
中,按实际 SMTP 服务商填写:KUN_VISUAL_NOVEL_EMAIL_FROM
KUN_VISUAL_NOVEL_EMAIL_HOST
KUN_VISUAL_NOVEL_EMAIL_PORT
KUN_VISUAL_NOVEL_EMAIL_ACCOUNT
KUN_VISUAL_NOVEL_EMAIL_PASSWORD
-
重启服务后,前台可通过邮件验证码完成注册。
-
若系统默认新注册为普通用户,可在后续通过数据库或后台将其提升为管理员(具体字段与角色名以源码/Prisma 模型为准)。
补充:开发阶段也可以引入本地邮件捕获服务(如 Mailpit/MailDev),便于无需真实邮箱即可验证注册流程。
路径 B:直接创建首个管理员(更直接、上线前常用)
思路是保证"密码用项目相同的哈希算法生成",避免无法登录。推荐两种实现:
方案 B-1:容器内执行一次性 Node 脚本(推荐)
优点:
- 直接复用项目依赖(
@prisma/client
、加密库),保证哈希算法一致; - 不需要你自己手写 SQL,避免列名/表名不一致。
步骤:
bash
# 进入 Web 容器
docker compose -f projects/galgamex/docker-compose.yml exec galgamex sh
# 在容器内创建一个临时脚本 scripts/init-admin.js(示例字段按项目实际模型调整)
cat > scripts/init-admin.js <<'EOF'
const { PrismaClient } = require('@prisma/client')
const bcrypt = require('bcryptjs')
async function main() {
const prisma = new PrismaClient()
const email = process.env.ADMIN_EMAIL || 'admin@example.com'
const password = process.env.ADMIN_PASSWORD || 'Admin@12345'
const hash = bcrypt.hashSync(password, 10)
// 注意:user 表名/字段名请以项目的 schema.prisma 为准
const user = await prisma.user.upsert({
where: { email },
update: {},
create: {
email,
password: hash,
role: 'ADMIN', // 如果项目用枚举/位掩码,请对应调整
nickname: 'Admin'
}
})
console.log('Created/Found admin:', user)
await prisma.$disconnect()
}
main().catch(async (e) => { console.error(e); process.exit(1) })
EOF
# 执行这个脚本
node scripts/init-admin.js
exit
执行完成后,用你设置的邮箱和密码登录即可。
方案 B-2:直接 SQL 注入(需要你了解表结构)
- 进入数据库容器:
bash
docker compose -f projects/galgamex/docker-compose.yml exec postgres sh -lc "psql -U postgres -d postgres"
- 在 psql 中查看表:
sql
\dt
- 若项目使用 bcrypt,可在本机或 Web 容器内生成哈希:
bash
node -e "console.log(require('bcryptjs').hashSync('Admin@12345', 10))"
- 按实际表/字段插入(如下仅示例):
sql
INSERT INTO "User" (email, password, role, nickname)
VALUES ('admin@example.com', '$2a$10$<bcrypt-hash>', 'ADMIN', 'Admin');
常见坑与排查记录
- image + build:
docker-compose.yml
同时指定image
与build
是允许的,最终会以给定名字产出镜像。 npx prisma db push
只同步结构,不会生成默认数据;若需要默认管理员,建议引入prisma db seed
或上面的"一次性脚本"。- 邮件注册在开发环境下可用 Mailpit/MailDev 做捕获,避免真实发信配置影响效率。
- 生产环境请替换 JWT/邮箱/对象存储等敏感配置,避免泄露。
成功截图
总结
- 通过 Dockerfile + docker-compose,我们将 Postgres、Redis 与 Web 服务一次性编排起来;
npx prisma db push
负责初始化结构,但不包含默认数据;- 没有默认管理员时,可选择"开注册"或"直接注入"。生产更推荐"一次性脚本/seed"的方式,既可审计,也便于复用。