GitLab Pages, работающие в Docker, недоступны извне контейнера

GitLab Pages, работающие в Docker, недоступны извне контейнера

У меня есть экземпляр GitLab, работающий в docker. GitLab работает нормально, но я не могу получить доступСтраницы GitLab.

Установка

Обзор

           +------------+
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.rb1

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_urlи gitlab_pages['enable'].

Отслеживание проблемы

  1. Запрос к pages.example.com не удался с кодом 502 (неверный шлюз) от CF
  2. Проверил журнал Nginx, нашел указанную выше запись в журнале.
  3. Сделано несколько запросов от хоста к контейнеру
    1. # curl 172.17.0.1:8090 -> curl: (7) Failed to connect to 172.17.0.1 port 8090: Connection refused
    2. # curl 172.17.0.7:8090 -> curl: (7) Failed to connect to 172.17.0.7 port 8090: Connection refused
  4. Сделал запрос из контейнера
    # curl localhost:8090 -> 404 error page

Из этого я делаю вывод, что что-то блокирует входящий трафик для 8090.(Страницы GitLab), но запросы на 80(GitLab)успешно завершены. Я потратил пару дней на гугление этой проблемы, но ничего не нашел.


1 Усечено; удалены настройки SMTP, LDAP и omniauth

решение1

Только что нашел причину своей проблемы после многих часов поисков не того (но об этом позже).

TL;DR

Мне пришлось изменить gitlab_pages['listen_proxy']значение для прослушивания на каждом интерфейсе, поэтому это выглядит так:

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

Подробный

Я искал эту проблему по ключевым словам, связанным с страницами gitlab, и только сейчас подумал, что, возможно, мне нужно мыслить нестандартно, что если это более общая проблема и даже не связанная с страницами GitLab. После первого поиска в Google я нашелхорошая статьяоб этом.

Я получил сообщение "connection denied", потому что порт 8090 не прослушивался, так как localhostссылается на адрес обратной связи, т. е. 127.0.0.1, но открытые порты перенаправляются для IP контейнера, в моем случае на динамический IP, который при написании вопроса был 172.17.0.7. Поэтому решение заключается в прослушивании каждого интерфейса, который возможно использовать 0.0.0.0в качестве IP-адреса.

Две фигуры, наглядно иллюстрирующие проблему и ее решение

(Рисунки из упомянутой статьи, но немного изменены для лучшего соответствия вопросу и сделаны только текстовыми для улучшения читабельности при использовании принудительного темного режима)
Когда используешь 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           |
                 +-------------------------------------+

решение2

Моя последняя конфигурация для gitlab 16.xx

GITLAB_OMNIBUS_CONFIG: |
        ### Web interace settings
        external_url "https://gitlab.domain.org"
        nginx['listen_port'] = 80
        nginx['listen_https'] = false

        ### Pages
        gitlab_pages['enable'] = true
        pages_external_url "https://pages.domain.org"
        pages_nginx['ssl'] = false
        pages_nginx['listen_https'] = false
        gitlab_pages['listen_proxy'] = '0.0.0.0:8090'
        gitlab_pages['internal_gitlab_server'] = 'http://localhost:8080'

Это конфигурация для 1 контейнера docker, который находится за обратным прокси-сервером (nginx/traefik/что угодно). Если вы завершаете https(TLS) на балансировщике нагрузки, и он проксирует трафик на порты HTTP: 80 - gitlab, 8090 - pages.

Связанный контент