Isso Docker Compose 部署指南
在 Linux 服务器上以 Docker Compose 部署 Isso 0.14.0 评论系统:isso 评论服务与演示页双服务编排、独立子网固定 IP、配置只读挂载与 SQLite 数据持久化、嵌入演示页评论链路与反垃圾拦截实测、数据备份与等价 docker run 形态,全程实测回显。
Isso Docker Compose 部署指南
本文在真实 Linux 服务器上用 Docker Compose 完成 Isso 0.14.0 评论系统的完整部署与验收:isso 评论服务与演示宿主页双服务编排、独立子网固定 IP、配置只读挂载与 SQLite 数据持久化,并实测嵌入演示页、评论提交、反垃圾拦截、待审评论不可见与数据备份全链路。全程命令与回显均为实测记录(实测日期 2026-10-30)。
目标: 可复现地跑通「部署 → 嵌入 → 提交 → 审核 → 备份」闭环。组件定位与选型背景见《Isso 0.14.0 介绍与选型指南》,参数级配置说明见《Isso 0.14.0 配置参数详解》,接口级实测见《Isso 0.14.0 API 使用详解》。
一、部署前准备
1.1 环境信息
| 项目 | 内容 |
|---|---|
| 组件版本 | Isso 0.14.0(上游最新稳定版,实查 GitHub Releases,查询日期 2026-10-30) |
| 评论服务镜像 | ghcr.io/isso-comments/isso:release(本地实测 119MB,镜像 ID 8e813ff52004) |
| 演示页镜像 | nginx:alpine(仅提供静态演示宿主页) |
| 服务器 | Ubuntu 26.04.1 LTS(x86_64),Docker 引擎 29.9.2,Docker Compose v5.6.1 |
| 端口规划 | 宿主 8141 → isso 服务 8080(评论 API 与管理后台);宿主 8142 → demo-page 服务 80(演示页) |
| 部署目录 | /opt/data/quzuo/tmp/isso(含 config/、db/、page/ 三个子目录与 compose.yaml) |
| 容器命名 | isso-0.14.0(评论服务)、isso-demo-page(演示页) |
| 容器网络 | isso-0.14.0-net,显式子网 10.89.71.0/24;isso 固定 10.89.71.10、演示页固定 10.89.71.11 |
| 管理后台口令 | q1w2e3r4(Isso 管理后台仅口令无用户名,本文按演示账号惯例以 admin / q1w2e3r4 指代) |
1.2 镜像选型说明
- 官方镜像发布于 GHCR 的
ghcr.io/isso-comments/isso。0.14.0 起镜像 tag 语义有明确变更(官方 CHANGES #970)::latest跟随 master 分支每次推送重建,:release指向最新稳定版。本文选择:release——部署时其内容即 0.14.0,后文 3.4 节以/info接口实测确认。 - 容器内运行形态(
docker inspect实测):
docker inspect isso-0.14.0 --format 'Entrypoint={{json .Config.Entrypoint}} Cmd={{json .Config.Cmd}}'
实测回显:
Entrypoint=["/isso/bin/gunicorn","-b","0.0.0.0:8080","-w","4","--preload","--worker-tmp-dir","/dev/shm"] Cmd=["isso.run"]
即官方镜像以 gunicorn 4 worker 预加载模式承载 isso.run 应用,监听容器内 0.0.0.0:8080。
- 拉取镜像(本文为重复执行复核;首次拉取会逐层输出下载进度):
docker pull ghcr.io/isso-comments/isso:release
实测回显:
Status: Image is up to date for ghcr.io/isso-comments/isso:release
1.3 前置条件核查
- 确认 Docker 引擎与 Compose 插件版本:
docker version --format 'Server: {{.Server.Version}}'
docker compose version
实测回显:
Server: 29.9.2
Docker Compose version v5.6.1
- 复核宿主端口 8141、8142 未被占用(动工前必做):
ss -ltn | grep -E ':8141|:8142'
无输出即两端口均空闲;被占用时先定位占用进程,或在编排文件中同步替换为其他空闲端口(并同步修改演示页嵌入地址与配置白名单)。
- 规划独立子网。约定在 10.89.0.0/16 内选槽位,避开宿主局域网段(192.168.0.0/16)与运营商级 NAT 段(100.64.0.0/16)。先列出已被既有自定义网络占用的槽位:
docker network ls --format '{{.Name}}' | xargs -I{} sh -c \
"docker network inspect {} --format '{{.Name}}: {{range .IPAM.Config}}{{.Subnet}}{{end}}'" | grep '10\.89\.' | sort
实测回显(本栈创建后的复核输出;动工前该列表中尚无 10.89.71.0/24,规划时按同法确认目标槽位空闲,被占用则顺延另选):
baikal-0101-stack_baikal-net: 10.89.62.0/24
isso-0.14.0-net: 10.89.71.0/24
librebooking-v710-stack_librebooking-net: 10.89.63.0/24
plakar-net: 10.89.65.0/24
二、编写 Compose 编排文件
2.1 目录结构与配置文件
创建部署目录与三个子目录:
mkdir -p /opt/data/quzuo/tmp/isso/config /opt/data/quzuo/tmp/isso/db /opt/data/quzuo/tmp/isso/page
部署目录最终结构(全部落在宿主机,容器仅挂载引用):
| 路径 | 用途 | 挂载点 |
|---|---|---|
config/isso.cfg | Isso 主配置文件 | /config(只读) |
db/ | SQLite 评论库目录(comments.db) | /db(可写) |
page/index.html | 演示宿主页 | /usr/share/nginx/html(只读) |
compose.yaml | Compose 编排文件 | — |
config/isso.cfg 全文(本文实测所用最终配置,逐节参数含义见本系列配置参数详解篇):
[general]
dbpath = /db/comments.db
host =
http://10.89.71.1:8142/
http://127.0.0.1:8142/
http://localhost:8142/
max-age = 15m
notify = stdout, smtp
reply-notifications = true
gravatar = true
latest-enabled = true
[server]
listen = http://0.0.0.0:8080/
trusted-proxies =
10.89.71.1
samesite = Lax
[admin]
enabled = true
password = q1w2e3r4
[moderation]
enabled = true
approve-if-email-previously-approved = true
purge-after = 30d
[guard]
enabled = true
ratelimit = 4
direct-reply = 3
reply-to-self = true
require-author = false
require-email = false
[smtp]
host = 10.89.71.1
port = 2525
security = none
username =
password =
to = admin@example.com
from = isso@example.com
timeout = 10
[markup]
renderer = mistune
allowed-elements = img
allowed-attributes = src, alt
[hash]
salt = isso-test-salt-2026
algorithm = pbkdf2
[rss]
base = http://127.0.0.1:8142/
limit = 100
[general] host 白名单三个条目的分工:http://10.89.71.1:8142/ 是容器网络的网关地址,即宿主机在 isso-net 中的身份——实测踩坑:当演示页直接跑在宿主机上时,Isso 服务端建线程要按白名单抓取宿主页,此时必须写网关地址(容器内可达),写宿主局域网 IP 会不可达;http://127.0.0.1:8142/ 与 http://localhost:8142/ 服务宿主本机直接访问演示页的场景(本部署演示页由 demo-page 服务提供,宿主经 8142 映射端口访问,命中的就是这两个条目)。
page/index.html 全文(演示宿主页):
<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="utf-8">
<title>Isso 演示宿主页</title>
</head>
<body>
<h1>Isso 演示文章:自托管评论系统实测</h1>
<p>这是一篇用于验证 Isso 评论服务的演示宿主页。</p>
<script data-isso="//127.0.0.1:8141/"
src="//127.0.0.1:8141/js/embed.min.js"></script>
<section id="isso-thread" data-title="Isso 演示文章:自托管评论系统实测"></section>
</body>
</html>
2.2 编排文件全文
在部署目录创建 compose.yaml:
name: isso-0.14.0-stack
services:
isso:
image: ghcr.io/isso-comments/isso:release
container_name: isso-0.14.0
restart: unless-stopped
ports:
- "8141:8080"
volumes:
- ./config:/config:ro
- ./db:/db
networks:
isso-net:
ipv4_address: 10.89.71.10
demo-page:
image: nginx:alpine
container_name: isso-demo-page
restart: unless-stopped
ports:
- "8142:80"
volumes:
- ./page:/usr/share/nginx/html:ro
networks:
isso-net:
ipv4_address: 10.89.71.11
networks:
isso-net:
name: isso-0.14.0-net
driver: bridge
ipam:
config:
- subnet: 10.89.71.0/24
2.3 编排设计逐项解说
- 显式项目名
name: isso-0.14.0-stack:Compose 项目名必须显式指定。多套自托管栈共存于同一台服务器时,同名项目的down操作会误删其他组件的栈——这是多服务共存的硬性纪律。 - 双服务固定 IP:isso 服务
10.89.71.10、演示页10.89.71.11,子网显式10.89.71.0/24。固定 IP 让[general] host白名单、[server] trusted-proxies、[smtp] host等配置项都有稳定明确的对端地址。 - 配置只读挂载
./config:/config:ro:官方镜像通过内置环境变量ISSO_SETTINGS=/config/isso.cfg定位主配置(见第六节),配置文件设为只读可防止容器内进程意外改写;修改配置只需编辑宿主文件后docker compose restart。 - 数据持久化
./db:/db:与配置中[general] dbpath = /db/comments.db对应,全部评论数据落在宿主机db/目录的 SQLite 单文件中(见第五节)。 restart: unless-stopped:宿主机重启后自动拉起,人工停止后不随 Docker 守护进程复活。- 演示页独立成服务:嵌入脚本
data-isso指向//127.0.0.1:8141/(Isso 的宿主映射端口),页面与评论服务同网络但宿主入口端口分离,验证环境贴近真实「博客页面 + 评论服务」的拓扑。
三、启动与首次验证
3.1 启动编排栈
cd /opt/data/quzuo/tmp/isso && docker compose up -d
实测回显:
Container isso-0.14.0 Running
Container isso-demo-page Creating
Container isso-demo-page Created
Container isso-demo-page Starting
Container isso-demo-page Started
(本文环境为增量执行:isso 服务此前已在运行故显示 Running;全新部署时两个服务都会依次经历 Creating → Created → Starting → Started。)
3.2 运行状态与端口监听
docker compose ps
实测回显(CREATED 列为执行时点的相对时间):
NAME IMAGE COMMAND SERVICE CREATED STATUS PORTS
isso-0.14.0 ghcr.io/isso-comments/isso:release "/isso/bin/gunicorn …" isso 3 hours ago Up 10 minutes 0.0.0.0:8141->8080/tcp, [::]:8141->8080/tcp
isso-demo-page nginx:alpine "/docker-entrypoint.…" demo-page 1 second ago Up Less than a second 0.0.0.0:8142->80/tcp, [::]:8142->80/tcp
ss -ltn | grep -E ':8141|:8142'
实测回显:
LISTEN 0 4096 0.0.0.0:8141 0.0.0.0:*
LISTEN 0 4096 0.0.0.0:8142 0.0.0.0:*
LISTEN 0 4096 [::]:8141 [::]:*
LISTEN 0 4096 [::]:8142 [::]:*
3.3 启动日志解读
docker logs isso-0.14.0 2>&1 | head -12
实测回显:
2026-10-30 08:53:05,725:INFO: Loading Mistune with plugins: ['strikethrough', 'subscript', 'superscript'] and parameters: ['escape', 'hard_wrap']
2026-10-30 08:53:05,725:INFO: Using Mistune as Markdown rendering engine
2026-10-30 08:53:05,729:INFO: Using database at '/db/comments.db'
2026-10-30 08:53:05,735:WARNING: unable to connect to your website, Isso will probably not work correctly. Please make sure, Isso can reach your website via HTTP(S).
[2026-10-30 08:53:05 +0000] [1] [INFO] Starting gunicorn 25.2.0
[2026-10-30 08:53:05 +0000] [1] [INFO] Listening at: http://0.0.0.0:8080 (1)
[2026-10-30 08:53:05 +0000] [1] [INFO] Using worker: sync
[2026-10-30 08:53:05 +0000] [7] [INFO] Booting worker with pid: 7
[2026-10-30 08:53:05 +0000] [8] [INFO] Booting worker with pid: 8
[2026-10-30 08:53:05 +0000] [9] [INFO] Booting worker with pid: 9
[2026-10-30 08:53:05 +0000] [10] [INFO] Booting worker with pid: 10
[2026-10-30 08:53:06 +0000] [1] [INFO] Control socket listening at /root/.gunicorn/gunicorn.ctl
逐行含义:前两行确认 0.14.0 的默认 Markdown 渲染引擎为 Mistune(含删除线/上下标插件与 escape 参数);第三行确认数据库落在挂载目录;WARNING 行是启动时对 [general] host 白名单逐项发起 HTTP HEAD 探测、全部不可达时输出(源码 isso/__init__.py)——本文截取日志时演示页尚未就绪,该告警不阻断 API 服务,服务端建线程抓页按需进行;其余为 gunicorn 25.2.0 四个 sync worker 的启动序列。
3.4 服务探活
Isso 提供两个免认证的公开信息端点:
curl -s http://127.0.0.1:8141/info
curl -s http://127.0.0.1:8141/config
实测回显:
{"version": "0.14.0", "host": "http://127.0.0.1:8141", "origin": "http://10.89.71.1:8142", "moderation": true}
{"config": {"reply-to-self": true, "require-email": false, "require-author": false, "reply-notifications": true, "gravatar": true, "avatar": false, "feed": true}}
/info 的 version: "0.14.0" 即版本确认(镜像 :release 标签内容与上游最新稳定版一致);moderation: true 表示审核开启。/config 返回嵌入页可读的公开开关集合,与 isso.cfg 中对应配置项一一映射(详见本系列配置参数详解篇)。
四、嵌入演示页与评论链路验证
4.1 页面嵌入三要素
演示页 index.html 中与 Isso 相关的共三处:
<script data-isso="//127.0.0.1:8141/" src="//127.0.0.1:8141/js/embed.min.js">:data-isso告诉客户端脚本评论服务的地址;embed.min.js由 isso 服务自身静态托管;<section id="isso-thread">:评论区的挂载点,id 固定为isso-thread;data-title="Isso 演示文章:自托管评论系统实测":线程标题来源——客户端以该值作为title参数提交(源码js/app/isso.js)。若不提供,服务端会按请求来源抓取页面标题建线程,此时要求[general] host白名单可从服务端侧访问到页面(排障见第十节第 2 条)。
静态资源与页面可达性验证:
curl -s -o /dev/null -w 'GET http://127.0.0.1:8142/index.html -> %{http_code}\n' http://127.0.0.1:8142/index.html
curl -s -o /dev/null -w 'GET http://127.0.0.1:8141/js/embed.min.js -> %{http_code}\n' http://127.0.0.1:8141/js/embed.min.js
实测回显:
GET http://127.0.0.1:8142/index.html -> 200
GET http://127.0.0.1:8141/js/embed.min.js -> 200
演示页服务的访问日志(来源 10.89.71.1 即宿主机在桥接网络中的网关地址):
docker logs isso-demo-page 2>&1 | grep 'GET /index.html' | tail -3
实测回显:
10.89.71.1 - - [30/Oct/2026:11:52:17 +0000] "GET /index.html HTTP/1.1" 200 454 "-" "curl/8.18.0" "-"
4.2 评论提交冒烟与反垃圾拦截实测
模拟浏览器提交(POST JSON 到 /new,uri 与 title 走查询串,Origin/Referer 头命中白名单)。第一次以「直评」形式提交,返回 403:
curl -s -i -X POST 'http://127.0.0.1:8141/new?uri=%2Findex.html&title=Isso%20%E6%BC%94%E7%A4%BA%E6%96%87%E7%AB%A0%EF%BC%9A%E8%87%AA%E6%89%98%E7%AE%A1%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F%E5%AE%9E%E6%B5%8B' \
-H 'Origin: http://127.0.0.1:8142' -H 'Referer: http://127.0.0.1:8142/index.html' \
-H 'Content-Type: application/json' \
-d '{"text":"部署验收冒烟评论:Compose 双服务栈启动正常,评论链路畅通。","author":"周八","email":"zhouba@example.com"}'
实测回显:
HTTP/1.1 403 FORBIDDEN
Server: gunicorn
Date: Fri, 30 Oct 2026 12:01:23 GMT
Connection: close
Content-Type: text/html; charset=utf-8
Content-Length: 120
Access-Control-Allow-Origin: http://127.0.0.1:8142
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: HEAD, GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Origin, Referer, Content-Type
Access-Control-Expose-Headers: X-Set-Cookie, Date
<!doctype html>
<html lang=en>
<title>403 Forbidden</title>
<h1>Forbidden</h1>
<p>3 direct responses to /index.html</p>
3 direct responses to /index.html 是 guard 反垃圾模块的 direct-reply 限流拦截:同一来源(按匿名化后的 IP 网段聚合)对同一线程的直评累计已达配置上限 3。本文环境该来源配额已被此前的实测评论占满,恰好实证了拦截路径;全新部署环境首次直评不会被拦。改以「回复」形式提交(parent 指向一条既有评论 id 25,回复不受 direct-reply 计数约束):
curl -s -i -X POST 'http://127.0.0.1:8141/new?uri=%2Findex.html&title=Isso%20%E6%BC%94%E7%A4%BA%E6%96%87%E7%AB%A0%EF%BC%9A%E8%87%AA%E6%89%98%E7%AE%A1%E8%AF%84%E8%AE%BA%E7%B3%BB%E7%BB%9F%E5%AE%9E%E6%B5%8B' \
-H 'Origin: http://127.0.0.1:8142' -H 'Referer: http://127.0.0.1:8142/index.html' \
-H 'Content-Type: application/json' \
-d '{"text":"部署验收冒烟回复:审核通过后对外可见。","author":"周八","email":"zhouba@example.com","parent":25}'
实测回显:
HTTP/1.1 202 ACCEPTED
Server: gunicorn
Date: Fri, 30 Oct 2026 12:03:00 GMT
Connection: close
Content-Type: application/json
Content-Length: 436
Set-Cookie: 26=WzI2LCI1NjYzMDdiZjZmZjk4MzJhYTM1NWU5MWJiZGNiMmE2ZmViMmI1M2E2Il0.auSHdA.xgJp2MVDiFr3NaoGRSrhxBSw6JI; Expires=Fri, 30 Oct 2026 12:18:00 GMT; Max-Age=900; Path=/; SameSite=Lax
X-Set-Cookie: isso-26=WzI2LCI1NjYzMDdiZjZmZjk4MzJhYTM1NWU5MWJiZGNiMmE2ZmViMmI1M2E2Il0.auSHdA.xgJp2MVDiFr3NaoGRSrhxBSw6JI; Expires=Fri, 30 Oct 2026 12:18:00 GMT; Max-Age=900; Path=/; SameSite=Lax
Access-Control-Allow-Origin: http://127.0.0.1:8142
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: HEAD, GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Origin, Referer, Content-Type
Access-Control-Expose-Headers: X-Set-Cookie, Date
{"id": 26, "parent": 25, "created": 1793361780.5222783, "modified": null, "mode": 2, "text": "<p>\u90e8\u7f72\u9a8c\u6536\u5192\u70df\u56de\u590d\uff1a\u5ba1\u6838\u901a\u8fc7\u540e\u5bf9\u5916\u53ef\u89c1\u3002</p>", "author": "\u5468\u516b", "website": null, "likes": 0, "dislikes": 0, "notification": null, "hash": "c1905c0f8037", "gravatar_image": "https://www.gravatar.com/avatar/9034ce632c0b6990cfdef207fbdb8149?d=identicon&s=55"}
三个关键信号:202 + mode: 2 表示评论已入库但处于待审核状态([moderation] enabled = true 的预期行为;若配置了「邮箱曾获通过自动放行」且该邮箱命中,则返回 201 + mode: 1 直接入库);响应体同时携带 Set-Cookie 与 X-Set-Cookie 两个头——后者交由嵌入页脚本写入 localStorage,是评论作者 15 分钟内编辑/删除自己评论的凭据([general] max-age = 15m);gravatar_image 字段由 [general] gravatar = true 开启。审核放行操作见本系列配置参数详解篇的审核闭环实测。
4.3 公开列表与计数
拉取公开评论列表(limit=1 仅返回 1 条顶层评论用于演示分页):
curl -s 'http://127.0.0.1:8141/?uri=%2Findex.html&limit=1'
实测回显:
{"id": null, "total_replies": 12, "hidden_replies": 8, "replies": [{"id": 5, "parent": null, "created": 1793359408.7815886, "modified": 1793359871.0028844, "mode": 1, "text": "<p>\u8fd9\u662f\u7b2c\u4e00\u6761\u5b9e\u6d4b\u8bc4\u8bba\uff1aIsso \u90e8\u7f72\u5b8c\u6210\uff0c\u8bc4\u8bba API \u5de5\u4f5c\u6b63\u5e38\u3002\uff08\u5df2\u7f16\u8f91\uff1a\u8865\u5145\u914d\u7f6e\u8def\u5f84\uff09</p>", "author": "\u5f20\u4e09", "website": null, "likes": 0, "dislikes": 0, "notification": null, "hash": "47b6b7a99262", "gravatar_image": "https://www.gravatar.com/avatar/f0c3acd8a5e2b954b76bfd774a667cf1?d=identicon&s=55", "total_replies": 0, "hidden_replies": 0, "replies": []}], "config": {"reply-to-self": true, "require-email": false, "require-author": false, "reply-notifications": true, "gravatar": true, "avatar": false, "feed": true}}
字段口径:total_replies 是该线程对外可见评论总数(mode 计数掩码只含已通过状态,待审评论不计入);hidden_replies 是本次响应未展示的顶层评论数(顶层可见 9 条,limit=1 返回 1 条,故为 8);首条评论的 modified 字段非空即「评论者 15 分钟内编辑自己评论」的留存痕迹。
页面侧计数接口(嵌入页的「N 条评论」角标取数):
curl -s -X POST http://127.0.0.1:8141/count -H 'Content-Type: application/json' -d '["/index.html"]'
实测回显(提交待审评论前后各执行一次,结果不变——待审评论既不进列表也不进计数):
[12]
五、数据持久化说明
宿主机 db/ 目录挂载到容器 /db,与配置 dbpath = /db/comments.db 对应,Isso 的全部落盘内容就是这一个 SQLite 文件:
ls -la /opt/data/quzuo/tmp/isso/db/
实测回显:
total 40
drwxr-xr-x 2 root root 4096 Oct 30 19:52 .
drwxr-xr-x 7 root root 4096 Oct 30 19:19 ..
-rw-r--r-- 1 root root 32768 Oct 30 19:52 comments.db
「Because comments are not Big Data」——官方对 SQLite 后端的定位在实测中也得到印证:十余条评论与线程元数据共 32KB。备份直接打包即可(无需停服,SQLite 单文件一致性在低并发写入下足够;严谨起见可在空闲期备份):
tar czf /opt/data/quzuo/tmp/isso/isso-comments-2026-10-30.tgz -C /opt/data/quzuo/tmp/isso db
ls -la /opt/data/quzuo/tmp/isso/*.tgz
实测回显:
-rw-r--r-- 1 root root 2600 Oct 30 20:01 /opt/data/quzuo/tmp/isso/isso-comments-2026-10-30.tgz
恢复 = 解包回 db/ 目录后 docker compose up -d;整站迁移 = 连同 config/、page/ 一起打包,在新机同构部署后替换目录即可。
六、环境变量说明
Isso 与「环境变量直配运行参数」的路线保持距离,只有一个关键的内置变量:
| 变量 | 镜像内置值 | 作用 |
|---|---|---|
ISSO_SETTINGS | /config/isso.cfg | 指定主配置文件路径,优先级高于命令行 -c 参数 |
- 该变量由官方镜像直接内置(
docker inspect实测):
docker inspect isso-0.14.0 --format '{{range .Config.Env}}{{println .}}{{end}}' | grep ISSO
实测回显:
ISSO_SETTINGS=/config/isso.cfg
- 源码注释明确其优先级(
isso/__init__.py:ISSO_SETTINGS env var takes precedence over -c flag);多站点分发模式(isso.dispatch入口)则强制要求设置该变量。 - 0.14.0 新增配置文件取值的环境变量替换能力(官方 CHANGES #1037,实现于
isso/config.py的IssoParser.get,对每个配置值做路径风格的变量展开),适合把口令类敏感项留存在宿主环境而非写入配置文件。 - 除
ISSO_SETTINGS外没有全量环境变量映射,运行参数一律以isso.cfg为准——这与部分竞品的「大写键映射配置树」环境变量风格不同,迁移评估时需留意。
七、配置参数速览
isso.cfg 共九个配置节,本文部署所用取值与作用速览(逐项实测行为见本系列配置参数详解篇):
| 配置节 | 本文取值要点 | 作用域 |
|---|---|---|
[general] | 数据库路径、host 白名单三来源、max-age 15m、notify stdout+smtp、gravatar、latest-enabled | 全局:存储、站点白名单、通知与扩展开关 |
[server] | 监听 8080、trusted-proxies 10.89.71.1、samesite Lax | HTTP 监听与代理信任链 |
[admin] | enabled + 口令 q1w2e3r4 | Web 管理后台 /admin |
[moderation] | enabled、曾获通过自动放行、purge-after 30d | 评论审核策略 |
[guard] | ratelimit 4、direct-reply 3、reply-to-self true | 反垃圾限流(4.2 节已实测拦截) |
[smtp] | 通知邮箱服务器与收发件人、security none | 邮件通知渠道 |
[markup] | mistune 渲染器、白名单放行 img | Markdown 渲染与元素白名单 |
[hash] | salt、pbkdf2 | 评论者邮箱匿名化指纹 |
[rss] | base、limit 100 | 评论 Atom Feed |
八、等价 docker run 形态
不使用 Compose 时,以下命令与本文编排文件等价(供参考,未重复执行;镜像已内置 ISSO_SETTINGS,无需额外 -e 参数):
docker network create --driver bridge --subnet 10.89.71.0/24 isso-0.14.0-net
docker run -d --name isso-0.14.0 \
--network isso-0.14.0-net --ip 10.89.71.10 \
-p 8141:8080 \
-v /opt/data/quzuo/tmp/isso/config:/config:ro \
-v /opt/data/quzuo/tmp/isso/db:/db \
--restart unless-stopped \
ghcr.io/isso-comments/isso:release
docker run -d --name isso-demo-page \
--network isso-0.14.0-net --ip 10.89.71.11 \
-p 8142:80 \
-v /opt/data/quzuo/tmp/isso/page:/usr/share/nginx/html:ro \
--restart unless-stopped \
nginx:alpine
九、常用运维命令
| 操作 | 命令 |
|---|---|
| 查看栈状态 | docker compose ps(部署目录执行) |
| 评论服务日志 | docker logs -f --tail 100 isso-0.14.0 |
| 演示页日志 | docker logs -f --tail 50 isso-demo-page |
| 改配置后生效 | 编辑 config/isso.cfg 后 docker compose restart |
| 停止 / 启动 | docker compose down / docker compose up -d |
| 数据备份 | tar czf isso-comments-2026-10-30.tgz -C /opt/data/quzuo/tmp/isso db |
| 进入容器排查 | docker exec -it isso-0.14.0 sh |
| 版本确认 | curl -s http://127.0.0.1:8141/info |
| 升级版本 | docker compose pull && docker compose up -d(:release 随上游稳定版前滚;需要锁版本时以镜像摘要固定,升级前先做第五节数据备份) |
十、常见问题
- 启动日志出现
WARNING: unable to connect to your website:启动时 Isso 会对[general] host白名单逐项发 HTTP HEAD 探测,全部不可达即告警(3.3 节实录)。演示页尚未就绪时该告警可忽略;若持续出现,检查白名单地址是否为「从 Isso 服务侧可达」的地址。 - 提交评论返回 400
Cannot create new thread: URI ... is not accessible and no title was provided:嵌入页未提供data-title且服务端按白名单抓取页面失败。两个修法:给<section id="isso-thread">补data-title(推荐,客户端始终带 title 提交);或确保白名单首项是服务端可达地址——实测踩坑:页面跑在宿主机时必须写网关地址10.89.71.1:8142,写宿主局域网 IP 从容器内不可达,必然复现此错。 - 提交成功(202)但页面上看不到评论:
[moderation] enabled = true下新评论一律待审,需管理员在/admin后台放行;待审评论同时不进列表与计数(4.3 节实测)。注意purge-after(本文 30d)会自动清理超期未审的待审评论——审核要及时。 - 浏览器控制台跨域报错:Isso 只向
[general] host白名单内的来源返回Access-Control-Allow-Origin响应头(4.2 节回显可见响应头逐字回显了白名单来源http://127.0.0.1:8142)。页面真实访问来源(协议 + 地址 + 端口)必须与白名单条目完全一致。 - 连发评论被 403 拦截:guard 反垃圾在起作用——
ratelimit限制同一来源每分钟评论数(本文 4 条),direct-reply限制对同一线程的直评累计数(本文 3 条,4.2 节实测命中)。来源按匿名化后的 IP 网段聚合;经代理接入时需配置[server] trusted-proxies并让代理传递X-Forwarded-For,否则所有用户会共享代理出口的配额。 - 端口冲突:
docker compose up报端口占用时用ss -ltnp | grep 端口号定位;换宿主端口后同步修改演示页data-isso指向与 host 白名单条目。 - 管理后台口令遗失:修改
isso.cfg的[admin] password后docker compose restart即生效,无其他恢复路径。
参考链接
- Isso 官网:https://isso-comments.de
- 官方文档:https://isso-comments.de/docs/
- GitHub 仓库:https://github.com/posativ/isso
- Releases 页(0.14.0 版本查证处):https://github.com/posativ/isso/releases
- 官方镜像说明(CHANGES #970 镜像 tag 语义):https://github.com/posativ/isso/blob/master/CHANGES.rst