如何使用主机网络而不是docker网络重建应用程序?

你好,

有时当我通过 Web 界面执行升级时,Discourse 会提示我运行以下命令:

cd /var/discourse
git pull
./launcher rebuild app

由于 rebuild 过程会多次连接 GitHub,而 GitHub 在中国(我的服务器所在地)部分被封锁,因此我必须配置 HTTP/HTTPS 代理以更好地访问 GitHub。以下是未使用代理和使用代理访问 YouTube 的对比:

root@iosre:/var/discourse# wget https://youtube.com
--2021-06-10 23:55:05--  https://youtube.com/
Resolving youtube.com (youtube.com)... 66.220.152.17, 2001::3d6f:fadc
Connecting to youtube.com (youtube.com)|66.220.152.17|:443... ^C
root@iosre:/var/discourse# export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7891
root@iosre:/var/discourse# wget https://youtube.com
--2021-06-10 23:56:12--  https://youtube.com/
Connecting to 127.0.0.1:7890... connected.
Proxy request sent, awaiting response... 301 Moved Permanently
Location: https://www.youtube.com/ [following]
--2021-06-10 23:56:13--  https://www.youtube.com/
Connecting to 127.0.0.1:7890... connected.
Proxy request sent, awaiting response... 200 OK
Length: unspecified [text/html]
Saving to: ‘index.html’

index.html [  <=>  ] 510.58K   813KB/s    in 0.6s    

2021-06-10 23:56:14 (813 KB/s) - ‘index.html’ saved [522830]

然而,当我运行 ./launcher rebuild image 时,脚本会进入容器并在 Docker 内部执行所有操作,而容器内的网络环境与已配置代理的主机不同,导致我无法访问 YouTube,因此重建过程大多数情况下会失败。

root@iosre:/var/discourse# ./launcher enter app
root@iosre-app:/var/www/discourse# wget https://youtube.com
--2021-06-10 15:59:57--  https://youtube.com/
Resolving youtube.com (youtube.com)... 69.171.248.128, 2001::d238:33c1
Connecting to youtube.com (youtube.com)|69.171.248.128|:443... ^C
root@iosre-app:/var/www/discourse# export https_proxy=http://127.0.0.1:7890 http_proxy=http://127.0.0.1:7890 all_proxy=socks5://127.0.0.1:7891
root@iosre-app:/var/www/discourse# wget https://youtube.com
--2021-06-10 16:00:10--  https://youtube.com/
Connecting to 127.0.0.1:7890... failed: Connection refused.

我的问题是:有什么方法可以在 Docker 内部(尤其是在 ./launcher rebuild app 过程中)使用主机的代理设置?

2 个赞

也许可以看看 Replace rubygems.org with taobao mirror to resolve network error in China

此外还有一个中国模板可供包含,你可以在 templates 文件夹中找到它。不过我不太确定它具体起什么作用。

(这不算一个完美的回答,但已经过了两天,你还没有收到任何回复。)

4 个赞

谢谢 Jay!中国的模板通过 gems.ruby-china.com 镜像了 rubygems.org,该站点由 taobao/alibaba 托管。

受这一想法的启发,我计划用国内站点镜像 github.com,希望能由阿里巴巴托管。

3 个赞

@snakeninny,如果我理解对了你的问题,你可能需要类似这样的操作:

/var/discourse/launcher rebuild app --docker-args --net=host --skip-mac-address

在这种情况下,你可能需要修改 app.yml 中的 expose 部分(只需运行 netstat -ltupen 来查找容器实际监听的端口)。

2 个赞

谢谢 Ivan!我已经执行了上述操作,但尚未修改 app.yml 以暴露该部分。该如何操作呢?

1 个赞

用文本编辑器打开 containers app.yml,并查找“expose”。

1 个赞

我在 app.yml 的 expose 部分看到了以下内容:

expose:
  - "30080:80"   # 将主机端口 80 转发到容器端口 80 (http)
  - "2222:22" # 将主机端口 2222 转发到容器端口 22 (ssh)

我是否需要将主机端口 443 (https) 转发到容器端口?应该转发到哪个容器端口?

1 个赞

这之前不是能用的吗?我猜是你的反向代理在处理 HTTPS 相关的事情。

1 个赞

不,并不是这样。正如我所描述的,我可以在宿主机上访问 YouTube,但在 Docker 中无法访问。

1 个赞

您的设置过于复杂,难以判断具体问题所在。建议您先在不使用反向代理的情况下完成配置,然后再参考以下指南:如何在已有 Apache 站点的服务器上安装 Discourse在同一台机器上运行其他网站与 Discourse

2 个赞

@snakeninny,抱歉回复晚了。

按照你在暴露(expose)部分设置的 30080:80,你只需要在你的 Nginx/Apache 等服务器上配置代理请求即可。

例如,我使用的 Nginx 配置(我将 30080 换成了 2080):

/etc/nginx/sites-available/00-default-ssl.conf

server {
...

        location / {
                # 当 Docker 以正常模式(桥接模式)运行时,此配置适用于 Nginx
                proxy_pass      http://example.com:2080/;
                
                # 如果 Docker 网络使用主机模式(--net=host),则使用这两行
                #proxy_pass      http://example.com:3000/;
                #proxy_redirect  http://example.com:2080/ https://example.com;

                proxy_read_timeout 90;
                proxy_http_version 1.1;
                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;
                proxy_set_header X-Forwarded-Proto $scheme;

                proxy_set_header X-Forwarded-Host $host;
                proxy_set_header X-Forwarded-Server $host;

                error_page 502 =502 /errorpages/discourse_offline.html;
                proxy_intercept_errors on;

    # 你可以排除特定 IP 的请求,使其不记录在访问日志中
    if ( $remote_addr = "x.x.x.x" )
    {
        access_log off;
    }
        }

location /errorpages/ {
    alias /var/www/errorpages/;
}
}

当你在主机模式(--net=host)下运行容器时,你应该考虑将代理设置切换为使用 3000 端口,并配置重定向(可能像上面的示例一样使用 https)。

2 个赞