注意:这是我的帖子 (英文)的译文,描述了在原始文档所在的同一站点上使用的评论服务器的实现。
TL; DR版本:我开发了Commento服务器配置,该配置可轻松,简单地以半自动模式进行部署。 从GitHub 将此存储库复制到您自己,并按照README中的说明进行操作。
不久前,我不可抗拒地想将Disqus(可能是向页面添加评论的最常见系统)更改为免费开放的Commento 。
像许多其他“免费”产品一样,Disqus的问题在于,这种情况下的产品是用户-即您。 此外,Disqus“丰富”了使用兆字节脚本和一百多个其他HTTP请求的每个页面。
另外,它的免费版本显示可以“每月仅$ 9”购买的广告(Plus计划)。 仅此一项就足以找到更好的东西。
在某个时候,我偶然发现了这篇文章,并发现了一个名为Commento的免费评论服务器。 碰巧的是,Commento最近才完全开放-在提供两个版本(免费的Community和Commercial Enterprise)之前,Commento完全开放了。 感谢其开发商Adhityaa Chandrasekar。
Commento比Disqus效率高几个数量级 ,附加负载的典型大小约为11 KB ,当然还有注释本身。 与所需的HTTP请求大致相同的情况。
Commento服务器的另一个优点是它非常快,因为它是用Go编写的。
好吧,作为蛋糕上的樱桃,他收到了来自Disqus的大量评论,他还能梦到什么?
对于非高级(技术上)用户,Commento在commento.io上提供了立即可用的云服务。 作者提供您自己选择月租费,但出于技术原因,不能低于$ 3。
Chandrasekar先生还慷慨地在Commento.io上提供了一个免费帐户,以换取该产品的“非重要补丁”。
好吧,我选择了第三个选项:自己提高Commento服务器。 在这种情况下,您不依赖任何人(当然,除了托管人以外),我喜欢独立性。
难点
我是Docker容器的忠实拥护者,并且经常使用Docker Compose (一种用于管理多个相关容器的组的工具)。 Commento在GitLab容器注册表中有一个现成的Docker映像。
因此,决定使用本身成熟的容器-但首先必须确定一些事情。
难题一:PostgreSQL
Commento需要一个相当新的PostgreSQL服务器版本,不幸的是不支持其他SQL服务器。
好吧,我们仍然在容器中运行所有内容,因此非常简单。
难度2:不支持HTTPS
Commento本身是一台Web服务器,但仅支持不安全的HTTP协议。
应当指出,这种做法在当今很普遍:在这种情况下,服务器隐藏在反向代理后面, 反向代理也执行SSL卸载。 事实是,在这种情况下,绝对需要SSL / HTTPS支持,毕竟在院子里2019年,寻找使用不安全的Internet协议授权用户的尝试非常麻烦。
我决定使用Nginx服务器,首先,我在使用它方面有丰富的经验,其次,它非常快速,经济且稳定。 并发布Docker映像的官方版本。
HTTPS配方中的第二个成分是域的SSL证书。 我永远感谢EFF和Mozilla创建了Let's Encrypt证书颁发机构 ,该机构每月颁发数百万个免费证书。
我们加密还提供了一个免费的命令行实用程序certbot ,该实用程序大大简化了获取和更新证书的过程。 好吧,而且-当然-给他的一个Docker映像!
难题3:Certbot鸡蛋问题
但是这个技巧比较棘手。
我们想在Nginx上的反向代理配置中引用SSL证书,这意味着如果没有证书,它只会拒绝启动。 同时,要获得域的 SSL证书,您需要一个正常工作的HTTP服务器,“加密”将证明您对该域的所有权。
我设法解决了这个问题,在我看来,这很优雅:
- 首先,生成一个虚拟的无效证书,其唯一目的是让Nginx启动。
- Nginx和certbot共同获得一个新的,现在有效的证书。
- 根据Let's Encrypt的建议,一旦收到证书,certbot就进入“待机模式”,每12个小时醒来一次,以检查是否需要更新。
- 片刻之后并且证书已被续订,certbot将通知Nginx重新启动。
困难四:必须保留一些东西
我强烈怀疑您要在重新引导或系统更新后保存用户注释。
另外,为了避免由于过于频繁的请求而让我们加密,最好在整个有效期内保留收到的证书。
在建议的配置中,使用Docker的卷解决了这两点,该卷是在Commento首次启动时由systemd自动创建的。 卷被标记为external
卷,因此当使用docker-compose down -v
删除容器时,Docker会跳过它们。
放在一起
现在您可以看到它们如何协同工作。
下图显示了四个容器之间的交互和流量:

我应用了内置的Docker depends_on
选项,以确保容器以正确的顺序启动。
如果您只想启动自己的Commento服务器,则可以跳过本文的其余部分,直接转到GitHub上的代码 。
好吧,稍后我将更详细地讨论此实现。
一切如何运作
撰写档案
如您在上图中所看到的,我的“组合”包含四个服务:
certbot
-EFF的certbot
实用程序nginx
反向代理实现SSL卸载app
-评论服务器postgres
-PostgreSQL数据库
docker-compose.yml
包含其自己的Docker网络的声明(称为commento_network
)和三个卷,其中两个是外部的(即必须在Compose外部创建):
commento_postgres_volume
存储PostgreSQL服务器数据:用户,主持人,注释等。certbot_etc_volume
包含certbot
接收的certbot
。
Nginx的
Nginx容器基于基于Alpine的轻量级官方映像,并使用以下脚本运行:
- 第3行 ( ARRGHHH,Habr不支持在代码中显示行号-大约翻译)。注册了一个中断处理程序,以便Nginx和后台监视过程在容器停止时成功完成工作。
- 第27行调用了wait函数,该函数将暂停Nginx启动过程,直到
certbot
容器创建的SSL配置文件为止。 没有这个,Nginx将拒绝启动。 - 第30行创建了一个后台进程,该进程每十秒钟定期检查一次名为
.nginx-reload
的标志文件的存在,并在检测到该文件后立即指示Nginx重新加载配置。 证书更新时,此文件还会创建certbot。 - 第34行在正常模式下启动Nginx。 在这种情况下,
exec
表示当前的Shell进程已由 Nginx进程代替 。
此图中的另一个重要文件是Commento虚拟服务器配置,该配置强制Nginx将HTTPS请求转发到commento
容器:
server { listen [::]:443 ssl ipv6only=on; listen 443 ssl; server_tokens off; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name __DOMAIN__; location / { proxy_pass http://app:8080/; proxy_set_header Host $http_host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } ssl_certificate /etc/letsencrypt/live/__DOMAIN__/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/__DOMAIN__/privkey.pem; include /etc/letsencrypt/options-ssl-nginx.conf; ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; } server { listen 80 default_server; listen [::]:80 default_server; server_tokens off; server_name __DOMAIN__; location /.well-known/acme-challenge/ { root /var/www/certbot; }
第一个服务器块(第1-21行)描述了如何使用HTTPS和转发规则。 这是提及“加密我们的”证书文件(或使用存根代替)的地方。
构建图像时,将服务器提供的域作为参数传递; 它替换了服务器配置中的__DOMAIN__
行。
第二个块(第23-38行)是HTTP服务器的配置,certbot使用它来确认域所有权(所谓的“ ACME挑战”)。 所有其他请求都会导致通过HTTPS重定向到相应的地址。
证书机器人
我们的certbot映像基于带有以下脚本的官方构建 :
简要介绍以下内容:
- 如上一个脚本中一样,第3行是常规完成容器所必需的。
- 第17-19行检查所需的变量。
- 在第22-25行中-正确安装了certbot工作所需的目录。
- 叉子如下:
- 仅在容器的第一个开始执行第30-50行:
- 复制一个虚拟证书,使Nginx可以正常启动。
- 同时,Nginx正在等待此过程结束,然后继续下载。
- Nginx启动后,certbot将启动从Let's Encrypt获取有效证书的过程。
- 最后,一旦收到证书,就会创建
.nginx-reload
文件,并向Nginx提示是时候重新加载配置了。
- 第54行等待Nginx启动-如果已经有完整的证书。
- 完成所有这些操作后(第58-63行),他继续循环,每12小时检查一次是否需要续订证书,并通知Nginx重新启动。
app
和postgres
容器使用开发人员提供的原始图像,没有任何更改。
系统服务
这个难题的最后一部分是systemd commento.service
单元文件 ,您需要在该文件中在/etc/systemd/system/commento.service
创建一个符号链接,以便在系统启动时适时启动它:
[Unit] Description=Commento server [Service] TimeoutStopSec=30 WorkingDirectory=/opt/commento ExecStartPre=-/usr/bin/docker volume create commento_postgres_volume ExecStartPre=-/usr/bin/docker volume create certbot_etc_volume ExecStartPre=-/usr/local/bin/docker-compose -p commento down -v ExecStart=/usr/local/bin/docker-compose -p commento up --abort-on-container-exit ExecStop=/usr/local/bin/docker-compose -p commento down -v [Install] WantedBy=multi-user.target
行数:
- 第6行表示将项目代码克隆到
/opt/commento
目录-这要简单得多。 - 第7-8行创建外部卷(如果尚未创建)。
- 在第9行中,删除了先前容器的可能剩余部分。 外部卷将保留。
- 第10行标志着Docker Compose的实际发布。 当容器中的任何一个
--abort-on-container-exit
时--abort-on-container-exit
标志将--abort-on-container-exit
整个容器群。 因此,systemd将至少知道该服务已停止。 - 第11行再次清理和删除容器,网络和卷。
源代码
GitHub上提供了一个完全正常的实现,只需要在docker-compose.yml
配置变量docker-compose.yml
。 您只需要仔细按照README中描述的步骤进行操作即可。
该代码受MIT许可证的约束。
感谢您阅读此地方,非常欢迎发表评论!