使用 Docker 和 Traefik 搭建 GitLab (前篇)

蘇洋發表於2019-04-10

本文使用「署名 4.0 國際 (CC BY 4.0)」許可協議,歡迎轉載、或重新修改使用,但需要註明來源。 署名 4.0 國際 (CC BY 4.0)

本文作者: 蘇洋

建立時間: 2019年04月10日 統計字數: 6199字 閱讀時間: 13分鐘閱讀 本文連結: soulteary.com/2019/04/10/…


使用 Docker 和 Traefik 搭建 GitLab (前篇)

之前曾不止一次的介紹過 GitLab 在容器中的安裝使用。考慮到多數使用場景都是在內網環境下,所以也未曾過多的進行過安全配置。最近在幫研究院進行系統搭建,其中一個述求是“公網環境下使用”。

本篇將介紹如何更好的使用容器中的 GitLab ,並搭配 Traefik 實現自動掛載 HTTPS 。

編寫 Traefik 配置規則

Traefik 的詳細使用,可以參考以往的文章,比如:使用服務發現改善開發體驗更完善的 Docker + Traefik 使用方案 等,更多內容可以翻看歷史內容標籤,這裡不過多贅述。

本文依舊只需要關注編排檔案中的 labelsnetworks 欄位配置就足夠啦。

對 GitLab 容器服務的 networks 欄位設定全域性使用的網路卡 traefik(本例),就可以讓 Traefik 自動接管 GitLab 對外的 Web 服務請求

networks:
  - traefik
複製程式碼

編排檔案中的 labels 欄位,宣告瞭 Traefik 如何對流量進行轉發。假設我們要對外提供三種訪問能力:

  • https://gitlab.${DOMAIN}
    • 訪問 GitLab Web 頁面和 Web API
  • https://registry.${DOMAIN}
    • 使用終端訪問容器倉庫
  • https://page.${DOMAIN}
    • 使用瀏覽器訪問一些倉庫的預覽頁面(類似 GitHub Page)

那麼我們可以這樣配置:

labels:
  - "traefik.enable=true"
  # GitLab Web 服務
  - "traefik.gitlab.port=80"
  - "traefik.gitlab.frontend.rule=Host:gitlab.${BASEHOST}"
  - "traefik.gitlab.frontend.entryPoints=http,https"
  - "traefik.gitlab.frontend.headers.SSLProxyHeaders=X-Forwarded-For:https"
  - "traefik.gitlab.frontend.headers.STSSeconds=315360000"
  - "traefik.gitlab.frontend.headers.browserXSSFilter=true"
  - "traefik.gitlab.frontend.headers.contentTypeNosniff=true"
  - "traefik.gitlab.frontend.headers.customrequestheaders=X-Forwarded-Ssl:on"
  - "traefik.gitlab.frontend.passHostHeader=true"
  - "traefik.gitlab.frontend.passTLSCert=false"
  # Registry 服務
  - "traefik.registry.port=5100"
  - "traefik.registry.frontend.rule=Host:registry.${BASEHOST}"
  - "traefik.registry.frontend.entryPoints=http,https"
  # Pages 服務
  - "traefik.pages.port=5201"
  - "traefik.pages.frontend.rule=Host:page.${BASEHOST}"
  - "traefik.pages.frontend.entryPoints=http,https"
複製程式碼

RegistryPages 這裡,為了節約篇幅,我就不重複貼上相同的內容了,你可以參考 GitLab Web 服務補全響應頭處理。

當然,如果你覺得容器編排檔案寫的內容太多了,想放到 GitLab 中進行處理也是可以的,稍後我會講。

編寫 GitLab 配置

配置 GitLab 還是需要一些額外的耐心,不過好在坑我都替你趟完了。

配置 GitLab Nginx 服務

在給出參考程式碼之前,我們需要先知道 GitLab 的一個“Tricks”:

如果你設定的 external_url 內容包含 https,那麼服務預設會使用 SSL 方式對外提供服務。如果你的 external_url 宣告為 http://gitlab.${DOMAIN} ,當系統執行起來後(預設埠為 80),當我們使用 https 進行訪問,又會出現各種問題,官方文件寫的也是不清不楚。

搜尋 reddit 上的討論歷史,發現有個老外都自暴自棄放棄使用 https,改用 http了,令人哭笑不得。

遇到問題解決問題就好了鴨,逃避是什麼鬼。

使用容器方式搭建 GitLab ,所有的配置都需要宣告在編排檔案的 environment欄位內,下面是 GitLab Web 服務的使用配置。

environment:
  GITLAB_OMNIBUS_CONFIG: |
    external_url 'https://gitlab.${BASEHOST}'
    nginx['enable'] = true
    nginx['listen_port'] = 80
    nginx['listen_https'] = false
    nginx['http2_enabled'] = false
    nginx['client_max_body_size'] = '250m'
    nginx['redirect_http_to_https'] = true
複製程式碼

需要注意的是,宣告的外部連結地址 external_url 需要使用 HTTPS 協議。而監聽埠需要設定為 80,另外也要配置Nginx不進行 https 監聽,不使用 HTTP2,至於 HTTP 自動轉向 HTTPS 可配可不配,因為 Traefik 側我預設開啟了 HTTP 轉向 HTTPS 功能。

前文提到,如果我們不想使用 Traefik 進行響應頭的修改,那麼該如何在 GitLab 中進行配置呢,也很簡單,多新增一個 proxy_set_headers 的配置即可:

nginx['proxy_set_headers'] = {
  "Host" => "$$http_host",
  "X-Real-IP" => "$$remote_addr",
  "X-Forwarded-For" => "$$proxy_add_x_forwarded_for",
  "X-Forwarded-Proto" => "https",
  "X-Forwarded-Ssl" => "on"
}
複製程式碼

這裡有一點需要額外注意,所有出現在 environment 欄位內的變數,都需要使用 雙$ 符號宣告,而非 單個$,否則結果不會如願以償。

前端提到了,我們要同時提供 Web 訪問容器倉庫頁面預覽三個功能,所以配置還需要加上其他兩項。

registry['enable'] = true
registry_external_url 'https://registry.${BASEHOST}/'
registry_nginx['listen_port'] = 5100
registry_nginx['listen_https'] = false
registry_nginx['redirect_http_to_https'] = true

pages_external_url "https://page.${BASEHOST}/"
pages_nginx['listen_port'] = 5200
pages_nginx['listen_https'] = false
pages_nginx['redirect_http_to_https'] = true

gitlab_pages['enable'] = true
gitlab_pages['inplace_chroot'] = true
gitlab_pages['external_http'] = ['gitlab:5201']
gitlab_pages['dir'] = "/var/opt/gitlab/gitlab-pages"
gitlab_pages['log_directory'] = "/var/log/gitlab/gitlab-pages"
gitlab_pages['artifacts_server'] = true
gitlab_pages['artifacts_server_timeout'] = 10
複製程式碼

可以看到,除了 gitlab_pages 欄位比較特殊外,配置和剛剛大同小異。

另外提一點,我原本的習慣是將所有的流量都配置到 80 埠,再讓 Traefik 進行轉發可讀性會更好一些,但是看到了另外一位國外同學的配置後,我覺得讓埠保持在預設埠也是不錯的選擇,比如 51005200

配置檔案最上面的監控需要額外配置,我們回頭細聊,為了減少影響,這裡將這部分功能進行關閉。

配置 GitLab SSH 埠

這裡我選擇讓 GitLab 的 SSH 埠保持預設,而修改宿主機的 SSH 埠到其他位置,這樣做的好處是:

  • 可以減少對 GitLab 的配置。
  • 倉庫訪問地址顯得更美觀了,避免了使用者使用軟體過程中需要解決的額外問題。

使用編排檔案,將 GitLab 埠對映到宿主機中。

version: '3'

services:

  gitlab:
    expose:
      - 80
      - 443
    ports:
      - '0.0.0.0:22:22'
複製程式碼

這裡有一個小細節,如果你不在 labels 中對你的服務埠進行宣告,Traefik 會使用你暴露的第一個埠作為服務發現的埠。所以將你所有依賴的內容都顯式宣告,是一個好的習慣。

完整的配置檔案

比較重要的細節都講完了,這裡給出完整的配置參考(容器倉庫和頁面預覽服務的響應頭有刪減,有需求可以自行新增):

version: '3'

services:

  gitlab:
    restart: always
    image: ${GITLAB_IMAGE}
    hostname: ${HOSTNAME}
    healthcheck:
      disable: true
    expose:
      - 80
      - 443
    ports:
      - '0.0.0.0:22:22'
    # 解決搜尋引擎搜尋不出小於3字元問題
    # https://gitbaai.ac.cn/gitlab-org/gitlab-ce/issues/40379
    entrypoint: |
      bash -c 'sed -i "s/MIN_CHARS_FOR_PARTIAL_MATCHING = 3/MIN_CHARS_FOR_PARTIAL_MATCHING = 1/g" /opt/gitlab/embedded/service/gitlab-rails/lib/gitlab/sql/pattern.rb && /assets/wrapper'
    volumes:
      - ./config:/etc/gitlab
      - ./data:/var/opt/gitlab
      - ./logs:/var/log/gitlab
      - ./embedded-logs:/opt/gitlab/embedded/logs/
    labels:
      - "traefik.enable=true"
      # GitLab Web 服務
      - "traefik.gitlab.port=80"
      - "traefik.gitlab.frontend.rule=Host:gitlab.${BASEHOST}"
      - "traefik.gitlab.frontend.entryPoints=http,https"
      - "traefik.gitlab.frontend.headers.SSLProxyHeaders=X-Forwarded-For:https"
      - "traefik.gitlab.frontend.headers.STSSeconds=315360000"
      - "traefik.gitlab.frontend.headers.browserXSSFilter=true"
      - "traefik.gitlab.frontend.headers.contentTypeNosniff=true"
      - "traefik.gitlab.frontend.headers.customrequestheaders=X-Forwarded-Ssl:on"
      - "traefik.gitlab.frontend.passHostHeader=true"
      - "traefik.gitlab.frontend.passTLSCert=false"
      # Registry 服務
      - "traefik.registry.port=5100"
      - "traefik.registry.frontend.rule=Host:registry.${BASEHOST}"
      - "traefik.registry.frontend.entryPoints=http,https"
      # Pages 服務
      - "traefik.pages.port=5201"
      - "traefik.pages.frontend.rule=Host:page.${BASEHOST}"
      - "traefik.pages.frontend.entryPoints=http,https"
    networks:
      - traefik
networks:
  traefik:
    external: true
複製程式碼

光有編排配置,不能夠愉快使用,這裡還需要建立一個 .env 環境配置檔案:

GITLAB_IMAGE=gitlab/gitlab-ce:11.8.6-ce.0
BASEHOST=lab.com
HOSTNAME=gitlab.lab.com
複製程式碼

兩個配置檔案都準備好之後,使用 docker-compose up 啟動你的應用,然後就可以開始使用了。

如果你還不熟悉 docker-compose 的使用,可以翻閱之前的文章,查閱 “一些額外的小技巧”一節。

最後

下一篇,我將著重介紹一些安全配置上的問題。


我現在有一個小小的折騰群,裡面聚集了一些喜歡折騰的小夥伴。

在不發廣告的情況下,我們在裡面會一起聊聊軟體、HomeLab、程式設計上的一些問題,也會在群裡不定期的分享一些技術沙龍的資料。

喜歡折騰的小夥伴歡迎掃碼新增好友。(請註明來源和目的,否則不會通過稽核)

關於折騰群入群的那些事

相關文章