Fider v0.38.2 Docker Compose 部署指南
Fider v0.38.2 用户反馈板 Docker Compose 双服务(app+PostgreSQL 17)从零部署实测:镜像选型与版本钉定、站点初始化与邮件验证闭环、数据持久化、环境变量表、等价 docker run 与 5 类启动/网络排障实录。
Fider v0.38.2 Docker Compose 部署指南
目标:在一台干净的 Linux 服务器上,用 Docker Compose 以「应用 + PostgreSQL」双服务形态从零部署 Fider v0.38.2 用户反馈板,完成站点初始化(创建站点、管理员邮箱验证登录、发布第一条反馈),并验证数据持久化与常见故障处理。本文全部命令与回显均在实验环境实测照抄(部署日期 2026-11-01)。
一、环境信息
- 操作系统:Ubuntu 22.04 LTS(x86_64)
- Docker Engine:29.x;Docker Compose:v5.6.1(
docker compose version实测回显Docker Compose version v5.6.1) - Fider:官方镜像
getfider/fider:v0.38.2(GitHub Releases 实查最新稳定版,发布于 2026-10-05;镜像内版本横幅实查为v0.38.2-e492af4a30db30c104df3dfb9e0f04e55757ba9e) - PostgreSQL:官方镜像
postgres:17(实测拉取版本 PostgreSQL 17.11,满足官方「PG 12+」要求) - 测试邮件组件:
mailhog/mailhog(官方文档推荐的试用 SMTP,Web UI 端口 8025) - 端口规划:Fider Web 对外
8140(容器内固定监听 3000)、MailHog UI 对外8142 - 部署目录:
/opt/fider(compose 文件、数据目录统一收敛于此) - 示例管理员:站点名
quzuo,邮箱root@quzuo.net;数据库口令q1w2e3r4
二、镜像选型说明
Fider 官方文档明确「不发行 Linux/Windows 二进制,自托管需要 Docker」,官方镜像发布在 Docker Hub:
| 镜像 | 说明 | 选型结论 |
|---|---|---|
getfider/fider:stable | 官方文档示例默认标签,滚动指向最新稳定构建 | 可用,但内容随时间漂移 |
getfider/fider:v0.38.2 | 与 GitHub Release 一一对应的固定标签 | 本文采用,生产可复现 |
ghcr.io/getfider/fider:* | GitHub Container Registry 路径 | 实测 denied(该仓库未公开发布),勿用 |
⚠️ 实测记录:
stable与v0.38.2两个标签的镜像摘要不同(stable为sha256:eb95d0b4bf5d...,v0.38.2为sha256:25d17db73c3d...),即 stable 并不恰好等于 v0.38.2。生产部署请像本文一样钉住版本标签,升级时显式改标签。
⚠️ 网络说明:本次实验宿主 Docker 守护进程配置了国内镜像加速(docker.m.daocloud.io 等)。
getfider/fider经镜像加速实测可直接docker pull成功;ghcr.io路径在本环境返回error from registry: denied。若你的服务器直连 Docker Hub 受阻,优先换国内加速器,而不是 ghcr。
三、前置条件
- Docker 与 Compose 插件已安装并可拉取镜像(
docker info正常返回); - 目标端口空闲:
ss -ltn | grep -E ':8140|:8142' || echo "8140/8142 free"
实测回显(部署前):
8140/8142 free
- 准备一个足够强的 JWT 会话密钥(32 字节随机十六进制即可):
openssl rand -hex 32
实测回显:
f823a9215047a93f21242be82cce6578f9cc882c2b63b2b7f7e51522482ddc6c
💡 说明:
JWT_SECRET用于签发登录会话,改动会使所有人被登出。上面回显只是某一次生成的示例值;本文后续 compose 与 docker run 中使用的密钥是同一方式另生成的另一个 64 位十六进制串(即实验环境实际在用的那把),两者不必相同,各自随机即可。
- 邮件通道:Fider 的注册/登录完全依赖邮件验证链接(v0.38.2 实测
users表无 password 列,即没有本地密码体系,登录走魔法链接或 OAuth)。生产环境配置真实 SMTP/Mailgun/Amazon SES 三选一;本文试用环境用官方文档推荐的 MailHog 假 SMTP。
四、部署步骤
4.1 创建部署目录与 compose 文件
mkdir -p /opt/fider/pg_data
cd /opt/fider
写入 docker-compose.yml(双服务:db + app;name: 显式钉项目名,避免多套栈互扰):
name: fider-v0.38.2-stack
services:
db:
restart: always
image: postgres:17
container_name: fider-v0.38.2-db
hostname: db
volumes:
- /opt/fider/pg_data:/var/lib/postgresql/data
environment:
POSTGRES_USER: fider
POSTGRES_PASSWORD: q1w2e3r4
healthcheck:
test: ["CMD-SHELL", "pg_isready -U fider -d fider"]
interval: 5s
timeout: 3s
retries: 12
app:
restart: always
image: getfider/fider:v0.38.2
container_name: fider-v0.38.2-server
hostname: app
ports:
- "8140:3000"
environment:
BASE_URL: "http://192.168.1.172:8140"
DATABASE_URL: "postgres://fider:***@db:5432/fider?sslmode=disable"
JWT_SECRET: "3f9c2a7e5b1d8c4a6f0e9b2c5d8a1f4e7b0c3d6a9f2e5b8c1d4a7e0f3b6c9d2"
EMAIL_NOREPLY: "noreply@quzuo.net"
EMAIL_SMTP_HOST: "mailhog"
EMAIL_SMTP_PORT: "1025"
LOG_LEVEL: "INFO"
depends_on:
db:
condition: service_healthy
networks:
default:
name: fider-v0382-stack_fider-net
driver: bridge
ipam:
config:
- subnet: 10.89.60.0/24
关键项说明:
BASE_URL必须等于用户实际访问的完整地址(含协议与端口),Fider 用它拼装所有邮件内链接;DATABASE_URL指向服务名db,库名默认与用户同名fider(postgres 镜像以POSTGRES_USER建同名库);depends_on + healthcheck:官方文档的裸 compose 允许 app 先于数据库启动并靠restart: always重试自愈;本文用健康检查门控,首轮即一次成功(见 4.3 日志);- 自定义网段
10.89.60.0/24为实验内网规划,按你的服务器网段替换即可。
4.2 拉取并启动
cd /opt/fider
docker compose pull
docker compose up -d
docker compose up -d 实测回显(节选):
Container fider-v0.38.2-db Creating
Container fider-v0.38.2-db Created
Container fider-v0.38.2-server Creating
Container fider-v0.38.2-server Created
Container fider-v0.38.2-db Starting
Container fider-v0.38.2-db Started
Container fider-v0.38.2-db Waiting
Container fider-v0.38.2-db Healthy
Container fider-v0.38.2-server Starting
Container fider-v0.38.2-server Started
4.3 启动日志验证
docker compose logs app 2>&1 | head -8
实测回显(首轮全新库,自动迁移):
INFO [2026-11-01T12:19:40Z] [MIGRATE] Running migrations...
INFO [2026-11-01T12:19:40Z] [MIGRATE] Found total of 95 migration files.
INFO [2026-11-01T12:19:40Z] [MIGRATE] Current version is 0
INFO [2026-11-01T12:19:40Z] [MIGRATE] Running Version: 201701261850 (201701261850_create_tenants.up.sql)
INFO [2026-11-01T12:19:40Z] [MIGRATE] Running Version: 201701281131 (201701281131_rename_domain.up.sql)
...(95 个迁移文件逐个执行,输出节选)
INFO [2026-11-01T12:19:40Z] [WEB] Environment: production
INFO [2026-11-01T12:19:40Z] [WEB] http server started on :3000
INFO [2026-11-01T12:19:40Z] [BGW] Starting worker 0.
看到 http server started on :3000 与 6 个后台 worker(Starting worker 0..5)即启动成功——这与官方文档「http server started on :3000 means everything is ok」的判据一致。
docker compose ps
实测回显:
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
fider-v0.38.2-db postgres:17 "docker-entrypoint.s…" db 12 minutes ago Up 12 minutes (healthy) 5432/tcp
fider-v0.38.2-server getfider/fider:v0.38.2 "/bin/sh -c './fider…" app 15 seconds ago Up 4 seconds 0.0.0.0:8140->3000/tcp, [::]:8140->3000/tcp
4.4 挂载测试 SMTP(MailHog)
试用环境没有真实 SMTP 时,按官方文档挂一个 MailHog 接进本栈网络(注意:compose 项目名含小数点会被规范化,网络实名是 fider-v0382-stack_fider-net,见「常见问题」11.5):
docker run -d --name fider-v0.38.2-mailhog --hostname mailhog \
--network fider-v0382-stack_fider-net -p 8142:8025 mailhog/mailhog
--hostname mailhog 必须与 app 服务的 EMAIL_SMTP_HOST: "mailhog" 一致,容器内 DNS 按主机名解析。
4.5 服务可达性验证
curl -s -o /dev/null -w "%{redirect_url}\n" http://192.168.1.172:8140/
实测回显:
http://192.168.1.172:8140/signup
全新实例访问根路径自动 307 跳转 /signup(创建第一个站点)。浏览器打开 http://192.168.1.172:8140/signup 即见官方注册页(页标题实测为 Sign up · Fider)。
五、站点初始化(首次运行)
5.1 创建站点与管理员
在 /signup 页面依次填写站点名 quzuo、你的名字 root、邮箱 root@quzuo.net 提交。该表单背后是 POST /_api/tenants,命令行等价操作实测如下:
curl -s -X POST http://192.168.1.172:8140/_api/tenants \
-H 'Content-Type: application/json' \
-d '{"tenantName":"quzuo","name":"root","email":"root@quzuo.net"}'
实测回显:
{}
HTTP 200
⚠️ 排障实录:字段名有讲究——只传
{"name":...}返回{"errors":[{"field":"tenantName","message":"Name is required."}]}(HTTP 400),只传{"tenantName":...}返回{"errors":[{"field":"name","message":"Name is required."}]}(HTTP 400);tenantName(站点名)、name(用户姓名)、
5.2 邮箱验证完成注册
提交后 Fider 发出标题为 Your new Fider site 的验证邮件。MailHog 环境可直接取其 HTTP API 读信:
curl -s http://192.168.1.172:8142/api/v2/messages | python3 -c "
import json,sys,re
d=json.load(sys.stdin)
for it in d.get('items',[]):
for m in set(re.findall(r'http://[^\"<> ]{10,160}', it['Content']['Body'])):
if 'k=' in m: print(m)
"
实测回显(验证链接):
http://192.168.1.172:8140/signup/verify?k=ESlSfs4RM66LJOd8tcEOI9cvcpyfpjg2jLoJ9l6h0Irfy5XMgSSvnYYJWnfjHpU0
浏览器打开该链接即完成注册并自动登录(实测返回 307 跳回站点首页)。此后每次登录都在 /signin 输入邮箱收一次性验证链接——Fider v0.38.2 没有本地密码(实测 users 表无 password 列),这是它安全模型的一部分:
curl -s -X POST http://192.168.1.172:8140/_api/signin -H 'Content-Type: application/json' -d '{"email":"root@quzuo.net"}'
实测回显:
{"userExists":true}
5.3 发布第一条反馈验证业务闭环
登录后创建帖子(内部 API 实测):
curl -s -b cookies.txt -X POST http://192.168.1.172:8140/api/v1/posts \
-H 'Content-Type: application/json' \
-d '{"title":"支持中文全文检索","description":"希望反馈板支持中文分词与全文检索","tags":[]}'
实测回显:
{"id":1,"isApproved":true,"number":1,"slug":"zhi-chi-zhong-wen-quan-wen-jian-suo","title":"支持中文全文检索"}
浏览器首页实测标题为 <title>quzuo</title>,帖子列表可见该条反馈。
六、数据持久化说明
| 数据 | 位置 | 持久化方式 |
|---|---|---|
| 全部业务数据(站点/用户/帖子/评论/投票/上传附件/SQL 日志) | PostgreSQL 单一 fider 库 | bind mount /opt/fider/pg_data |
| 应用配置 | compose environment: | compose 文件本身 |
| 上传文件 | 默认 BLOB_STORAGE=sql 存库内 blobs 表 | 随数据库一起持久化 |
💡 技术拓展:Fider 文件存储有三种——
sql(默认,附件进 PostgreSQL,备份一锅端)、fs(落盘目录,需BLOB_STORAGE_FS_PATH+ 挂载卷)、s3(S3 兼容对象存储)。本文用默认sql,小站附件量不大时最省心;大站建议s3。切换BLOB_STORAGE不会迁移存量文件,选型要趁早(官方文档明示)。
持久化实测:重启应用服务后数据无损——
docker compose restart app
docker exec fider-v0.38.2-db psql -U fider -d fider -tc "select id, title, status from posts;"
实测回显:
1 | 支持中文全文检索 | 0
数据库迁移版本同样落库可查(实测 migrations_history 共 95 行,最高版本 202606121200)。
七、环境变量表
本 compose 实际使用的变量(完整参数面见官方 Configuration Reference:https://docs.fider.io/hosting-instance#configuration-reference ):
| 变量 | 本文取值 | 必填 | 说明 |
|---|---|---|---|
BASE_URL | http://192.168.1.172:8140 | ✅ | 站点公网访问地址,邮件链接基址 |
DATABASE_URL | postgres://fider:***@db:5432/fider?sslmode=disable | ✅ | PG 连接串 |
JWT_SECRET | 64 位十六进制随机串 | ✅ | 会话签名密钥,改动即全员登出 |
EMAIL_NOREPLY | noreply@quzuo.net | ✅ | 发件人地址 |
EMAIL_SMTP_HOST | mailhog | ✅(SMTP 方式时) | 缺它启动 panic(见 11.2) |
EMAIL_SMTP_PORT | 1025 | ✅(SMTP 方式时) | MailHog 默认收件端口 |
LOG_LEVEL | INFO | ❌ | 默认即 INFO |
八、配置文件挂载
Fider 全量配置走环境变量,无独立配置文件;仅一类文件需要挂载进 /app/etc(官方文档 Mounting the etc folder):
SSL_CERT/SSL_CERT_KEY指向的证书与私钥文件;privacy.md、terms.md法律页。
app:
volumes:
- /opt/fider/etc:/app/etc
⚠️ 注意:
/app内其余目录(dist、static、views、migrations、locale共 22 种语言包)都是镜像内置资源,不要挂载覆盖;升级镜像即升级它们。
九、等价 docker run
双服务 compose 中 app 服务的等价单命令形态(数据库先行单独起,或指向外部 PG):
docker run -d --name fider-v0.38.2-server \
-p 8140:3000 \
-e BASE_URL="http://192.168.1.172:8140" \
-e DATABASE_URL="postgres://fider:***@db:5432/fider?sslmode=disable" \
-e JWT_SECRET="3f9c2a7e5b1d8c4a6f0e9b2c5d8a1f4e7b0c3d6a9f2e5b8c1d4a7e0f3b6c9d2" \
-e EMAIL_NOREPLY="noreply@quzuo.net" \
-e EMAIL_SMTP_HOST="mailhog" \
-e EMAIL_SMTP_PORT="1025" \
--network fider-v0382-stack_fider-net \
--restart always \
getfider/fider:v0.38.2
镜像默认启动命令为 ./fider migrate && ./fider(实测 docker inspect 的 Cmd 字段),即先自动迁移再启动服务,与 compose 形态行为一致。
十、常用运维命令
cd /opt/fider
# 查看栈内服务状态
docker compose ps
# 跟踪应用日志(官方口径:docker compose logs app)
docker compose logs -f app
# 改环境变量后重建生效(Fider 只在启动时读取配置)
docker compose up -d
# 只重启应用
docker compose restart app
# 升级到新版本:改 compose 中镜像标签后
docker compose pull && docker compose up -d
# 停止整栈(保留数据目录)
docker compose down
# 健康检查(容器内二进制自带 ping 子命令,退出码 0/1)
docker exec fider-v0.38.2-server /app/fider ping; echo $?
ping 实测回显:退出码 0(内部 GET /_health 返回 200)。
十一、常见问题
11.1 拉取 ghcr.io/getfider/fider 报 denied
实测 docker pull ghcr.io/getfider/fider:stable 返回 error from registry: denied。官方镜像实际发布在 Docker Hub getfider/fider,改用 docker pull getfider/fider:stable 或固定版本标签即可(本文实测 v0.38.2 拉取成功)。
11.2 缺必填环境变量导致启动 panic
实测逐层暴露的校验链(docker run --entrypoint /app/fider getfider/fider:v0.38.2 --help 在缺失对应变量时依次报):
panic: Error Trace:
- failed to parse environment variables (app/pkg/env/env.go:170)
- the environment variable "JWT_SECRET" is missing
补齐 JWT_SECRET 后报 EMAIL_NOREPLY is missing,再补报 DATABASE_URL……最后报:
panic: could not find environment variable named 'EMAIL_SMTP_HOST'
结论:BASE_URL/DATABASE_URL/JWT_SECRET/EMAIL_NOREPLY 四个必填之外,采用 SMTP 邮件方案时 EMAIL_SMTP_HOST/EMAIL_SMTP_PORT 也必须显式设置,否则进程在解析配置阶段直接退出(连 --help 都跑不出来,因为校验发生在 flag 解析之前)。
11.3 [MIGRATE] pq: password authentication failed for user "fider" (28P01)
实测排障实录:DATABASE_URL 连接串口令与 POSTGRES_PASSWORD 不一致时,应用进入重启循环,日志反复刷:
INFO [2026-11-01T12:18:16Z] [MIGRATE] Running migrations...
ERROR [2026-11-01T12:18:16Z] [MIGRATE] Error Trace:
- failed to get last migration record (app/pkg/dbx/migrate.go:57)
- pq: password authentication failed for user "fider" (28P01)
定位方法:docker inspect 对比 app 的 DATABASE_URL 与 db 的 POSTGRES_PASSWORD;或在数据库侧用同串口令验证 psql -h 127.0.0.1 -U fider。修正 compose 后 docker compose up -d 重建即恢复。注意:若 pg_data 已用旧口令初始化过,改 POSTGRES_PASSWORD 环境变量不会改库内口令,需进库执行 ALTER USER fider WITH PASSWORD 'q1w2e3r4';(与 compose 中 POSTGRES_PASSWORD 保持一致)。
11.4 首轮启动报 dial tcp :5432 connection refused
官方文档明示这是预期现象(裸 compose 下 app 先于数据库就绪):靠 restart: always 自动重试到数据库可用。本文用 healthcheck + depends_on: condition: service_healthy 从根上消除该窗口,首轮即一次成功。
11.5 往 compose 网络里挂外部容器报 network not found
实测:compose 项目名 fider-v0.38.2-stack 中的小数点被规范化剥离,实际网络名是 fider-v0382-stack_fider-net(docker network ls | grep fider 可见)。给 MailHog 等旁路组件 --network 时必须用规范化后的实名。
十二、参考链接
- 官方 Docker 部署文档:https://docs.fider.io/hosting-instance
- 官方自托管入口:https://docs.fider.io/self-hosted/
- 项目仓库与 Releases:https://github.com/getfider/fider/releases
- 官方镜像:https://hub.docker.com/r/getfider/fider
- MailHog:https://github.com/mailhog/MailHog
- 相关篇目:《Fider 介绍与选型指南》、《Fider v0.38.2 日常运维手册》、《Fider v0.38.2 故障排查与 FAQ》