- 新增管理端板块管理页面与后端接口(admin_board) - 新增旧版数据导入:legacyimport 服务、导入面板、importusers 命令行工具 - 聊天用户卡片、板块图标等 UI 组件与界面优化 - 补充 about/公告/1Panel 部署等文档 - gitignore 排除 dist/ 构建产物与 .agents/ 本地工具目录
6.3 KiB
姜十三论坛(jiang13-bbs)Docker 部署教程
前置条件:应用镜像(
jiang13-api、jiang13-web)已推送到你的私有镜像仓库。本教程只讲如何在服务器上用 1Panel 部署、反代与运维。项目架构:Next.js 前端(web)+ Go 后端(api)+ PostgreSQL 17,三者为独立容器。
一、镜像说明
| 服务 | 镜像 | 来源 |
|---|---|---|
| api | <你的用户名>/jiang13-api |
你的私有仓库 |
| web | <你的用户名>/jiang13-web |
你的私有仓库 |
| postgres | postgres:17-alpine |
Docker Hub 官方公共镜像,直接拉取 |
安全说明:api / web 镜像为多阶段构建产物,最终镜像不含源码,密钥运行时注入,不烤进镜像。部署前请确认这两个仓库在 Docker Hub 上已设为 Private。
二、1Panel 部署
1. 配置私有仓库认证(关键)
私有镜像必须先认证,否则拉取报 denied。
1Panel 左侧 容器 → 「仓库」标签 → 创建:
- 仓库地址:
docker.io - 用户名:你的 Docker Hub 用户名
- 密码:Docker Hub 密码或 Access Token(推荐 Token)
2. 用编排一键部署
容器 → 「编排」标签 → 创建编排,名称 jiang13,粘贴以下内容:
name: jiang13
services:
postgres:
image: postgres:17-alpine
restart: unless-stopped
environment:
POSTGRES_USER: jiang13
POSTGRES_PASSWORD: 改成你的强密码
POSTGRES_DB: jiang13
volumes:
- pgdata:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U jiang13 -d jiang13"]
interval: 5s
timeout: 5s
retries: 10
api:
image: <你的用户名>/jiang13-api:0.1.0
restart: unless-stopped
depends_on:
postgres:
condition: service_healthy
environment:
HTTP_PORT: "3001"
DEV_MODE: "false"
JIANG13_WORK_PATH: /var/lib/jiang13
DATA_DIR: /var/lib/jiang13/data
DB_DSN: postgres://jiang13:改成上面同一个密码@postgres:5432/jiang13?sslmode=disable
JWT_SECRET: ""
SITE_URL: https://改成你的域名
SETTINGS_MASTER_KEY: ""
volumes:
- appdata:/var/lib/jiang13/data
web:
image: <你的用户名>/jiang13-web:0.1.0
restart: unless-stopped
depends_on:
api:
condition: service_healthy
environment:
BACKEND_URL: http://api:3001
SITE_URL: https://改成你的域名
NODE_ENV: production
DEV_MODE: "false"
PORT: "3000"
HOSTNAME: 0.0.0.0
ports:
- "13000:3000"
volumes:
pgdata:
appdata:
只需改 3 处:
POSTGRES_PASSWORD的值DB_DSN里的密码(必须与第 1 处完全一致)- 两处
SITE_URL的域名
保存后,在编排列表点 ▶ 启动。会自动:拉镜像 → 起 postgres → 健康后起 api → 健康后起 web。
容器名固定为
postgres/api,因为服务间通过容器名互访(@postgres:5432、http://api:3001)。
3. 验证启动
「容器」标签确认三个容器状态:
- postgres Up (healthy)
- api Up (healthy) ← 健康才说明连库成功
- web Up
接口检查:
curl http://127.0.0.1:13000/healthz # web,返回 ok
docker exec jiang13-api-1 wget -qO- http://127.0.0.1:3001/health # api
三、Nginx 反向代理 + HTTPS
DEV_MODE=false 启用了 __Host- 前缀 cookie,必须 HTTPS。
1Panel 网站 → 创建网站 → 反向代理:
- 目标地址:
http://127.0.0.1:13000 - 申请并开启 SSL(1Panel 可一键 Let's Encrypt)
- 域名 DNS 解析到服务器
访问 https://你的域名,空库下第一个注册的账号自动成为站长(管理员)。
四、配置说明
环境变量
| 变量 | 说明 | 建议 |
|---|---|---|
POSTGRES_PASSWORD |
数据库密码 | 强密码,与 DB_DSN 一致 |
DB_DSN |
后端连库串 | 密码须与上者一致 |
JWT_SECRET |
登录 token 签名密钥 | 留空,自动生成并持久化到 data/.jwt_secret;自填须 ≥32 字符强随机 |
SETTINGS_MASTER_KEY |
加密邮件/S3 凭据(32字节Base64) | 留空=禁用保存凭据功能;需要时用 openssl rand -base64 32 生成 |
SITE_URL |
对外公开 origin | 前后端一致,与浏览器地址栏完全相同(含 https、无尾斜杠)。运行时读取,可后改重启生效 |
JWT_SECRET与SETTINGS_MASTER_KEY不要填同一个值(密钥复用是安全大忌,且两者格式/生命周期不同)。
端口被占用怎么办
- 容器内端口(3000/3001)写死不能改;只改映射的宿主机端口(冒号左边),如
"13000:3000"。 - 用 Nginx 反代时 api 无需暴露端口(web 通过容器名内部访问)。
- 查占用:
ss -tlnp | grep -E ':3000|:3001'
数据卷
pgdata:数据库数据appdata:上传文件 /.jwt_secret
删除编排时不要勾选删除数据卷,否则数据丢失。若换过数据库密码,需先删除旧 pgdata 卷重建(Postgres 只在空数据目录初始化密码)。
五、更新与运维
更新版本
修改编排中镜像的 tag(如 :0.1.0 → :0.2.0),或使用 :latest 标签后点「重新拉取镜像」再重启容器:
docker compose pull
docker compose up -d
:latest不会自动更新,需手动重新拉取才生效;建议同时保留版本号标签以便回滚。
常用命令
docker compose ps # 查看状态
docker compose logs -f # 看日志
docker compose logs api --tail 50
docker compose down # 停止(保留数据)
docker compose down -v # 停止并清空数据(慎用)
六、排障速查
| 现象 | 原因 | 解决 |
|---|---|---|
api 反复 restart,日志 password authentication failed |
密码不一致 / pgdata 残留旧密码 | 统一两处密码;删 pgdata 卷重建 |
api 日志 JWT_SECRET 过弱 |
填了 change-me 或过短 | 留空自动生成,或换 ≥32 字符强随机值 |
拉私有镜像 denied |
未配置仓库认证 | 1Panel 仓库里添加 Docker Hub 凭证 |
| web 不启动 | 等不到 api healthy | 先把 api 弄健康(解决上面问题) |
| 能打开页面但登录异常 | HTTP 下 __Host- cookie 不生效 | 必须走 HTTPS 反代 |