在国内顺畅使用 Discourse

Discourse 官方推荐的管理脚本没有考虑到国内糟糕的网络环境,导致使用非常困难,十次构建没有一次能成功。今天打算解决一下这个问题。

在国内顺畅使用 Discourse
Photo by Max van den Oetelaar / Unsplash

Discourse 是国外知名的论坛系统,目前像 ElasticSearch、Docker 这些社区都在使用。由于 Discourse 环境配置非常复杂,官方推荐使用 Docker 镜像来进行安装。然而官方推荐的管理脚本 discourse_docker 并没有考虑到国内糟糕的网络环境,导致使用非常困难,十次构建没有一次能成功。由于手上目前服务器都是国内的,因此打算解决一下这个问题。

基本思路也很简单了,就是本地启动一个 shadowsocks 的 client,然后给构建脚本提供服务。

首先通过 Docker 运行一个 shadowsocks 的 client:

docker run --name shadowsocks-client \
    --restart=always \
    -d \
    -p 0.0.0.0:30000:1080 \
    shadowsocks/shadowsocks-libev:latest ss-local -s [your.server.com] -p [port] -k [password] -m aes-128-gcm -b 0.0.0.0 -l 1080

如果需要使用混淆的话,在命令最后增加如下参数:

--plugin obfs-local --plugin-opts "obfs=http;obfs-host=some.domain.com"

不过这样的话就需要自己 build 一个包含 obfs-local 插件的镜像了,因为默认镜像中是没有这个插件的。

通过上面命令,我们在本机的 30000 端口开启了一个 SOCKS5 协议的代理。为了确保无误,访问 Google 试一下:

HTTPS_PROXY=socks5h://127.0.0.1:30000 curl https://www.google.com

如果很长时间没有返回的话,多半是配置有问题了,反复检查你的网络服务提供商提供的参数与你在上面命令中填写的参数是否一致。


如果测试成功,就可以进入下一个步骤了:将 SOCKS 协议的代理转换为 HTTP 协议的代理。之所以需要这个步骤,是因为经过实测,构建步骤中有一步(看报错内容应该跟 Ruby gem 包管理有关,不过我不熟悉 Ruby 语言,也没必要深究了)并不支持 SOCKS 协议的代理:

I, [2021-11-21T06:18:55.224549 #1]  INFO -- : Error fetching https://gems.ruby-china.com/:
	SocketError: Failed to open TCP connection to socks5h:80 (getaddrinfo: Name or service not known) (https://gems.ruby-china.com/specs.4.8.gz)

为了完成这一步骤,需要安装 privoxy。不同平台流程可能不一样,以下以 CentOS 8 为例:

dnf update -y
dnf install epel-release -y
dnf install privoxy -y

进入到 /etc/privoxy/ 目录中,编辑 config 文件,添加一行

forward-socks5 / 127.0.0.1:30000 .

如果需要的话,可以找到下面这行,将 127.0.0.1 改成 0.0.0.0,将本机监听改为监听所有接口:

listen-address  127.0.0.1:8010

然后启动 privoxy:

systemctl start privoxy

启动后,可以通过 systemctl status privoxy 查看是否正常运行,然后再次通过 curl 检查是否工作正常:

HTTPS_PROXY=http://127.0.0.1:8010 curl https://www.google.com

如果工作正常的话,就可以进入最后一步,修改 Discourse_docker 的配置文件了。由于 Discourse 构建时 git clone 等容易超时的网络操作都是在容器内完成的,因此在当前 shell 中添加 HTTP_PROXY 等环境变量是没有用的,并不会继承到容器中。

在 YAML 配置文件中新增:

env:
  http_proxy: http://host.docker.internal:8010
  https_proxy: http://host.docker.internal:8010

注意这里 IP 需要是宿主机的 IP。在这里我是通过 host.docker.internal 这一方式访问宿主机的,这样的话在启动容器的时候需要增加 --add-host host.docker.internal:host-gateway 参数。如果你容器使用的是 host network 的话,那么直接填 127.0.0.1 就可以了。

最后构建镜像:

./launcher start web_only --docker-args "--add-host host.docker.internal:host-gateway"

大功告成!享受飞快的构建速度吧!

参考资料:

https://wiki.archlinux.org/title/Shadowsocks_(简体中文)

https://www.atlantic.net/vps-hosting/how-to-install-and-configure-privoxy-server-on-centos-8/

https://stackoverflow.com/questions/24319662/from-inside-of-a-docker-container-how-do-i-connect-to-the-localhost-of-the-mach