使用 Traefik 進行 HTTP 路由

簡介

在本地開發期間,通常需要執行多個 HTTP 服務。您可能同時擁有 API 和前端應用程式、用於模擬資料端點的 WireMock 服務或資料庫視覺化程式(例如 phpMyAdmin 或 pgAdmin)。在許多開發設定中,這些服務會公開在不同的埠上,這需要您記住哪個服務在哪个埠上,但也可能導致其他問題(例如 CORS)。

反向代理可以大幅簡化此設定,方法是成為單一公開服務,然後根據請求 URL(透過路徑或主機名稱)將請求路由至適當的服務。Traefik先決條件

遵循本操作指南需要具備以下先決條件

  • 使用以下命令啟動 Traefik 容器。該命令將 Traefik 公開在端口 80 上,掛載 Docker 套接字(用於監控容器以更新設定),並傳遞 --providers.docker 參數以將 Traefik 設定為使用 Docker 提供者。

  • 現在,啟動一個簡單的 Nginx 容器,並定義 Traefik 監控的標籤以設定 HTTP 路由。請注意,Nginx 容器沒有公開任何端口。

    容器啟動後,在瀏覽器中開啟 http://nginx.localhost

  • 容器啟動後,在瀏覽器中開啟 http://welcome.localhost在開發中使用 Traefik

    現在您已體驗過 Traefik,接下來嘗試在開發環境中使用它。在此範例中,您將使用一個具有分離式前端和後端的範例應用程式。此應用程式堆疊具有以下設定:

    1. 所有對 /api 的請求都將轉到 API 服務
    2. 所有其他對 localhost 的請求都將轉到前端客戶端
    3. 由於應用程式使用 MySQL,db.localhost 應該提供 phpMyAdmin 以便在開發過程中輕鬆存取資料庫
    Architecture diagram showing Traefik routing requests to other containers based on the path of the request

    您可以在 GitHub 上的 dockersamples/easy-http-routing-with-traefik

    services:
      proxy:
        image: traefik:v3.1.2
        command: --providers.docker
        ports:
          - 80:80
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock

    請注意,這與先前使用的設定基本相同,但現在採用 Compose 語法。

  • 客戶端服務具有以下設定,該設定將啟動容器並為其提供標籤以在 localhost 接收請求。

  • api 服務具有類似的設定,但您會注意到路由規則有兩個條件 - 主機必須是「localhost」,且 URL 路徑必須具有「/api」的前綴。由於此規則更具體,因此 Traefik 會優先評估它,而不是客戶端規則。

  • 最後,phpmyadmin 服務設定為接收主機名稱「db.localhost」的請求。該服務還定義了環境變數以自動登入,使其更容易進入應用程式。

  • 在啟動堆疊之前,請停止 Nginx 容器(如果它仍在執行中)。

  • 就這樣。現在,您只需要使用 docker compose up 啟動 Compose 堆疊,所有服務和應用程式都將準備好進行開發。

    將流量傳送至非容器化工作負載

    在某些情況下,您可能希望將請求轉發到未在容器中執行的應用程式。在以下架構圖中,使用了與先前相同的應用程式,但 API 和 React 應用程式現在在本機主機上執行。

    An architecture diagram showing several components and the routing between them. Traefik is able to send requests to both non-containerized and containerized workloads

    為達成此目標,Traefik 將需要使用其他方法來設定自身。檔案提供者

    http:
      routers:
        native-api:
          rule: "Host(`localhost`) && PathPrefix(`/api`)"
          service: native-api
        native-client:
          rule: "Host(`localhost`)"
          service: native-client
    
      services:
        native-api:
          loadBalancer:
            servers:
              - url: "http://host.docker.internal:3000/"
        native-client:
          loadBalancer:
            servers:
              - url: "http://host.docker.internal:5173/"

    此設定表示,針對 localhost/api 的請求將會被轉發到名為 native-api 的服務,該服務接著會將請求轉發到 http://host.docker.internal:3000。主機名稱 host.docker.internal 是 Docker Desktop 提供用於將請求發送到主機電腦的名稱。

    使用此檔案,唯一的變更在於 Traefik 的 Compose 設定。具體來說,有兩件事情發生了變化

    1. 設定檔被掛載到 Traefik 容器中(確切的目標路徑由您決定)
    2. command 已更新,以新增檔案提供者並指向設定檔的位置
    services:
      proxy:
        image: traefik:v3.1.2
        command: --providers.docker --providers.file.filename=/config/traefik-config.yaml --api.insecure
        ports:
          - 80:80
          - 8080:8080
        volumes:
          - /var/run/docker.sock:/var/run/docker.sock
          - ./dev/traefik-config.yaml:/config/traefik-config.yaml

    啟動範例應用程式

    要執行將請求從 Traefik 轉發到原生執行應用程式的範例應用程式,請使用下列步驟

    1. 如果您仍在執行 Compose 堆疊,請使用以下指令將其停止

      $ docker compose down
      
    2. 使用提供的 compose-native.yaml 檔案啟動應用程式

      $ docker compose -f compose-native.yaml up
      

      開啟 http://localhost 將會返回 502 Bad Gateway 錯誤,因為其他應用程式尚未執行。

    3. 透過執行下列步驟來啟動 API

      cd api
      yarn install
      yarn dev
      
    4. 在新終端機中執行下列步驟來啟動前端(從專案的根目錄開始)

      cd client
      yarn install
      yarn dev
      
    5. http://localhosthttp://localhost/api/messageshttp://db.localhost摘要

      執行多個服務不需要複雜的埠設定和良好的記憶力。使用 Traefik 之類的工具,可以輕鬆啟動所需的服務並輕鬆存取它們——無論它們是用於應用程式本身(例如前端和後端),還是用於額外的開發工具(例如 phpMyAdmin)。