Waline 评论系统迁移到 Docker 部署

本文最后更新于:2022年8月10日 上午

本博客建站以来一直使用的基于 Valine 衍生的 Waline 评论系统,该评论系统是通过 CloudBase 云开发一键部署的。近期腾讯云对 CloudBase 云开发的计费模式进行了升级,从 2022 年 8 月 8 日开始,CloudBase 云开发统一采用基础套餐+按量计费的模式,要使用必须先购买带有一定配额的基础套餐。这意味着现在我每个月必须给腾讯云缴纳至少 20 元的最低消费,然而我这个小破站没有多少流量,根本用不完 20 元套餐的配额。所以,我需要将 Waline 评论系统进行迁移。

CloudBase 云开发的新计费模式
图1 CloudBase 云开发的新计费模式

虽然 Waline 支持多种数据库,并且可以部署到多个免费平台,但是经过各项对比,我最后决定将 Waline 评论系统迁移到 Docker 部署,数据库使用 LeanCloud。主要原因有:

  • 国内的免费 Serverless 平台随时可能像腾讯云 CloudBase 一样收费
  • 部署在国外免费 Serverless 平台,被国内用户访问时可能像 Github 一样不太稳定,甚至直接被墙。
  • 通过 Docker 部署或更新 Waline 都非常简单,而且不用担心云平台的收费问题。

1. LeanCloud 设置(数据库)

Waline 评论系统的架构如图 2 所示。首先我们需要搭建 Waline 的数据库,用于储存本站评论系统的用户信息和评论内容。

Waline 评价系统架构
图2 Waline 评价系统架构

我选择使用 LeanCloud 作为数据库,主要原因有:

  • 本站的 PV/UV 数据也是使用 LeanCloud 来储存的,便于管理;
  • LeanCloud 的免费版配额足够我这种小站使用,访问速度也很快;
  • Waline 对 LeanCloud 的支持非常完善。

设置 LeanCloud 的具体步骤,可以参考 Waline 官方文档 - 快速上手

虽然文档中推荐使用 LeanCloud 国际版(leancloud.app),但我使用的依然是 LeanCloud 国内版(leancloud.cn)。与国际版相比,国内版只是需要完成域名的备案接入。

因为我的网站域名(vickey.fun)已经完成了备案,所以只需要如图 3 所示为应用绑定已备案的域名,就可以正常使用 LeanCloud 数据存储:

  1. 登录国内版,按照快速上手,创建应用。

  2. 选择 设置 > 域名绑定 > API 访问域名 > 绑定新域名 > 输入域名(xxx.vickey.fun)> 确定,同时勾选 启用SSL强制HTTPS

  3. 按照 域名绑定 页面上的提示要求在 DNS 上完成 CNAME 解析。

  4. 填写绑定域名的备案号。

    域名设置

    图3 域名绑定

2. Docker 部署(服务端)

服务器部署前,我们需要对服务器进行配置,定义一些环境变量,详细说明请参考 Waline 官方文档 - 环境变量

对于数据库部署在 LeanCloud 国内版的用户必须配置以下 4 个环境变量:

环境变量名称 必填 备注
LEAN_ID LeanCloud 应用的 App ID
LEAN_KEY LeanCloud 应用的 App Key
LEAN_MASTER_KEY LeanCloud 应用的 Master Key 用于后台修改数据
LEAN_SERVER ⚠️ LeanCloud 服务地址,国内版用户需要配置此项,地址为 LeanCloud 应用中绑定的域名

使用 Docker 部署 Waline 服务端,我们只需输入以下命令:

1
2
3
4
5
6
7
docker run -d \
-e LEAN_ID=xxx \
-e LEAN_KEY=xxx \
-e LEAN_MASTER_KEY=XXX \
-e LEAN_SERVER=https://xxx.vickey.fun \
-p 8360:8360 \
lizheming/waline

我们也可以使用 docker-compose:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# docker-compose.yml
version: '3'

services:
waline:
container_name: waline
image: lizheming/waline
restart: always
ports:
- "8360:8360"
environment:
- "LEAN_ID=XXX"
- "LEAN_KEY=XXX"
- "LEAN_MASTER_KEY=XXX"
- "LEAN_SERVER=https://xxx.vickey.fun"

推荐添加 SECURE_DOMAINS 环境变量,该变量为安全域名配置,配置后,非安全域名来源的请求会返回 403 状态码。可以支持逗号分隔配置多个域名。

还可以增加 Nginx 的反代。可参考如下配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
server
{
listen 80;
listen 443 ssl http2;
server_name waline.vickey.fun;

if ($server_port !~ 443){
rewrite ^(/.*)$ https://$host$1 permanent;
}

# SSL setting
ssl_certificate fullchain.pem;
ssl_certificate_key privkey.pem;
ssl_protocols TLSv1.1 TLSv1.2 TLSv1.3;
ssl_ciphers EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
add_header Strict-Transport-Security "max-age=31536000";

# proxy to 8360
location / {
proxy_pass http://127.0.0.1:8360;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header REMOTE-HOST $remote_addr;
add_header X-Cache $upstream_cache_status;
# cache
add_header Cache-Control no-cache;
expires 12h;
}
}

3. 设置客户端

本站使用 Hexo 博客框架和 Fluid 主题。我们只需打开博客目录下的 _config.fluid.yml 文件,修改有关 Waline 的配置即可。

首先,开启文章页中的评论插件,并将启用的评论插件修改为 Waline:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#---------------------------
# 文章页
# Post Page
#---------------------------
post:

# 评论插件
# Comment plugin
comments:
enable: true
# 指定的插件,需要同时设置对应插件的必要参数
# The specified plugin needs to set the necessary parameters at the same time
# Options: utterances | disqus | gitalk | valine | waline | changyan | livere | remark42 | twikoo | cusdis | giscus
type: waline

_config.fluid.yml 中有两个开启评论插件的地方,注意选择 post (文章页)下面的一个,而不是 links (友链页)下面的。

接着,配置 Waline 评论插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# Waline
# 从 Valine 衍生而来,额外增加了服务端和多种功能
# Derived from Valine, with self-hosted service and new features
# See: https://waline.js.org/
waline:
serverURL: 'https://waline.vickey.fun'
path: window.location.pathname
meta: ['nick', 'mail', 'link']
requiredMeta: ['nick']
lang: 'zh-CN'
emoji: ['https://cdn.jsdelivr.net/gh/walinejs/emojis/weibo']
dark: 'html[data-user-color-scheme="dark"]'
wordLimit: 0
pageSize: 10

通常,Waline 插件的配置中,我们只需要修改 serverURL,所填入的是服务端被 nginx 反向代理后的地址。

经过以上的设置,重新生成网页,Waline 插件应该可以被正常加载。通过在文章中留下测试评论,应该能在 LeanCloud “数据存储”的 Comment 项中查看到你所留下的评论。

4. 数据库迁移

Waline 迁移到 Docker 部署后,用户和评论的数据也需要从 CloudBase 迁移到 LeanCloud。从 CloudBase 中导出的 json 文件不能直接导入到 LeanCloud。

CloudBase 导出后的 json 文件中数据格式如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
{
"_id":"62f1d5134f3ec7216e0c8959",
"link":"vickey.fun",
"mail":"vickeyrao@live.cn",
"nick":"嘻嘻琦琦",
"pid":"62f1d4acde3719172debd2e1",
"rid":"62f1d4acde3719172debd2e1",
"ua":"Mozilla/5.0 (Linux; Android 10; TAS-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Mobile Safari/537.36 EdgA/103.0.1264.51",
"url":"/2022/04/19/how-to-add-your-site-to-the-search-engine/",
"comment":"[@troxler](#62f1d4acde3719172debd2e1): 我也不知道,在网上搜了很多,有说需要等一段时间的,有说不符合Google规范的。我试了xml和txt两种格式,弄了很久也没有弄好。后来手动提交网站,谷歌自己会爬,我就没管它了",
"ip":"111.181.31.125",
"insertedAt":{
"$date":"2022-07-16T01:05:59.137Z"
},
"status":"approved"
}

LeanCloud 数据存储中的数据格式如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
"nick": "嘻嘻琦琦",
"ip": "111.181.31.125",
"objectId": "62f1d5134f3ec7216e0c8959",
"mail": "vickeyrao@live.cn",
"ua": "Mozilla/5.0 (Linux; Android 10; TAS-AN00) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/103.0.5060.114 Mobile Safari/537.36 EdgA/103.0.1264.51",
"insertedAt": {
"__type": "Date",
"iso": "2022-07-15T17:05:00.000Z"
},
"pid": "62f1d4acde3719172debd2e1",
"status": "approved",
"link": "vickey.fun",
"comment": "[@troxler](#62f1d4acde3719172debd2e1): 我也不知道,在网上搜了很多,有说需要等一段时间的,有说不符合Google规范的。我试了xml和txt两种格式,弄了很久也没有弄好。后来手动提交网站,谷歌自己会爬,我就没管它了",
"url": "/2022/04/19/how-to-add-your-site-to-the-search-engine/",
"rid": "62f1d4acde3719172debd2e1"
}

可以看到,两个数据的主要区别在 _idobjectIdinsertedAt 这几个子项。我们只需要在 CloudBase 导出的 json 文件中,按照 LeanCloud 的数据格式修改其中的 _idinsertedAt 这两个子项即可。

修改完毕后就可以通过 LeanCloud 导入修改的 json 文件。当然,如果数据不多,你也可以直接在 LeanCloud 里手动添加行。😁

5. 迁移过程中出现的问题(Error: unable to verify the first certificate)

迁移过程中,出现了一个困扰我很长时间的问题。

在搭建好 LeanCloud 数据库、Docker 部署好 Waline 服务端以及配置好博客的 Waline 评论插件后,我重新生成 Hexo 博客网页,页面可以正常加载 Waline 评论系统。

但是发布测试评论时,页面会弹出 Error: unable to verify the first certificate [N/A GET https://xxx.vickey.fun/1.1/classes/Comment] 错误。而且,注册新用户时,页面一直返回 500 错误码。Docker 的控制台上也显示了 code: 'UNABLE_TO_VERIFY_LEAF_SIGNATURE'rawMessage: 'unable to verify the first certificate' 等错误信息。

通过网上搜索,发现大部分解决的方法都是(1)关闭 Node.js 的 SSL 证书验证;(2)安装 node_extra_ca_certs_mozilla_bundle

之后找到了 node.js – Error: unable to verify the first certificate in nodejs 这篇文章,详细解释了出现这种问题的主要原因是证书链不完整(The certificate chain is incomplete)。问题的根源指向了 LeanCloud 绑定域名(xxx.vickey.fun)的 SSL 证书上,这个域名的 SSL 证书是由腾讯云签发的,被我手动上传到 LeanCloud,恰好该证书没有中间证书(Intermediate certificate),所以证书链不完整。

于是我马上到 What’s My Chain Cert? 网站,将 LeanCloud 绑定域名的 SSL 证书链补齐(记得勾选包含根证书 Include Root Certificate),重新上传到 LeanCloud,问题完美解决。

What's My Chain Cert?
图4 What's My Chain Cert?

Waline 评论系统迁移到 Docker 部署
https://vickey.fun/2022/08/09/Waline-Migration-From-CloudBase-to-Docker/
作者
饶玮琪
发布于
2022年8月9日
许可协议