Nginx

無法從容器外部訪問在 Docker 中執行的 GitLab 頁面

  • December 26, 2020

我有一個在 docker 中執行的 GitLab 實例。GitLab 工作正常,但我無法訪問GitLab Pages

設置

概述

          +------------+
Request+-->+ Cloudflare |
          +-----+------+
                |
                v       +---------+
              Nginx+--->+Docker   |
                        |  +------+
                        |  |GitLab|
                        +---------+

問題是 Nginx 無法將請求傳遞給 GitLab Pages 伺服器(請注意 GitLab 它自己工作)。

Nginx 錯誤日誌條目

[error] 14932#14932: *30505 connect() failed (111: Connection refused) while connecting to upstream, [...]

碼頭工人

image: gitlab/gitlab-ce
version: 13.7.1 (latest)
ip: 172.17.0.7 (dynamic)
published ports:
   172.17.0.1:8080 -> 80
   172.17.0.1:8090 -> 8090

Nginx

頁面的伺服器條目

server {
       listen 80 default_server;
       listen 443 default_server;
       server_name _;
       
       location / {
               proxy_pass      http://172.17.0.1:8090;
       }
}

GitLab

grep -v ‘^ # | ^ $’ gitlab.rb 1

nginx['listen_port'] = 80
nginx['listen_https'] = false
pages_external_url "http://pages.example.com/"
gitlab_pages['enable'] = true
gitlab_pages['external_http'] = []
gitlab_pages['listen_proxy'] = "localhost:8090"
gitlab_pages['inplace_chroot'] = true
gitlab_pages['metrics_address'] = ":9235"
pages_nginx['enable'] = true
pages_nginx['listen_https'] = false
pages_nginx['redirect_http_to_https'] = false

還嘗試了絕對最小配置,僅定義pages_external_urland gitlab_pages['enable']

追查問題

  1. 對 pages.example.com 的請求失敗,來自 CF 的 502(錯誤網關)

  2. 查看Nginx日誌,發現上面提到的日誌條目

  3. 從主機向容器發出多個請求

  4. # curl 172.17.0.1:8090 -> curl: (7) Failed to connect to 172.17.0.1 port 8090: Connection refused

  5. # curl 172.17.0.7:8090 -> curl: (7) Failed to connect to 172.17.0.7 port 8090: Connection refused

  6. 從容器發出請求

# curl localhost:8090 -> 404 error page

據此,我假設某些東西阻止了 8090 (GitLab Pages)的傳入流量,但對 80 *(GitLab)*的請求已成功完成。我花了幾天時間在Google上搜尋這個問題,但我找不到任何東西。


1截斷;已刪除 SMTP、LDAP 和omniauth 設置

經過數小時搜尋錯誤的事情后,才找到了我的問題的原因(但稍後會詳細介紹)。

TL;博士

我不得不改變gitlab_pages['listen_proxy']值來監聽每個介面,所以它看起來像這樣:

gitlab_pages['listen_proxy'] = "0.0.0.0:8090"

詳細的

我正在使用與 gitlab 頁面相關的關鍵字搜尋這個問題,剛才我覺得我可能需要跳出框框思考,如果這是一個更普遍的問題,甚至與 GitLab 頁面無關怎麼辦。在第一次Google搜尋後,我發現了一篇關於這個的好文章

我收到“連接被拒絕”消息,因為埠 8090 上沒有任何內容正在偵聽,因為localhost它指的是環回地址,即127.0.0.1,但暴露的埠被轉發給容器的 IP,在我的情況下,它是一個動態 IP,寫問題時是172.17.0.7。所以解決方案是監聽每個可能0.0.0.0用作 IP 地址的介面。

將問題和解決方案形象化的兩張圖

(來自上述文章的數字,但稍作修改以更好地匹配問題,並且在使用 force-darkmode 時僅將其變為文本以提高可讀性)

使用時localhost:8090

  Request      +--------------------------------------+
     +         | Default network namespace            |
     |         |                                      |
     |         |               +-------+              |
     v         |        +----->+ Nginx +------+       |
+-----+------+  |        |      +-------+      |       |
| Cloudflare |  |        |                     |       |
+-----+------+  |        |                     v       |
     |         +--------+-----------+-+-------+-------+
     |         | Physical interface | | Docker bridge |
     +-------->+ 10.0.0.1           | | 172.17.0.1    |
               +--------------------+ +-------+-------+
                                              |
                                              |
                                              v
                                      +-------+-------+
                                      | Docker bridge |
                                      | 172.17.0.7    |
                +-------+-----------+-+---------------+
                |       | Loopback  |                 |
                |       | 127.0.0.1 |                 |
                |       +-----+-----+                 |
                |             |                       |
                |             |      +--------------+ |
                |             +----->+ Pages server | |
                |                    +--------------+ |
                |GitLab's Network namespace           |
                +-------------------------------------+

監聽每個介面,使用0.0.0.0:8090

  Request      +--------------------------------------+
     +         | Default network namespace            |
     |         |                                      |
     |         |               +-------+              |
     v         |        +----->+ Nginx +------+       |
+-----+------+  |        |      +-------+      |       |
| Cloudflare |  |        |                     |       |
+-----+------+  |        |                     v       |
     |         +--------+-----------+-+-------+-------+
     |         | Physical interface | | Docker bridge |
     +-------->+ 10.0.0.1           | | 172.17.0.1    |
               +--------------------+ +-------+-------+
                                              |
                                              |
                                              v
                                      +-------+-------+
                                      | Docker bridge |
                                      | 172.17.0.7    |
                +-------+-----------+-+-------+-------+
                |       | Loopback  |         |       |
                |       | 127.0.0.1 |         |       |
                |       +-----+-----+         |       |
                |             |               v       |
                |             |      +--------+-----+ |
                |             +----->+ Pages server | |
                |                    +--------------+ |
                |GitLab's Network namespace           |
                +-------------------------------------+

引用自:https://serverfault.com/questions/1047390