開發與維運

一文搞定快速使用 Docker Compose 玩轉 Traefik v2(一)

Traefik 路由到 Docker 容器


微信圖片_20220611112804.png

創建一個新的 docker 網絡


docker network create traefik_net

Traefik 和 containers(容器)需要在同一網絡上。Compose 會自動創建一個,但事實是隱藏的,以後可能會發生混亂。最好僅創建自己的網絡並將其設置為每個 compose 文件中的默認網絡。


使用 docker network inspect traefik_net 查看連接到該網絡的容器


創建 traefik.yml

該文件包含所謂的靜態 traefik 配置。

在此基本示例中,只有很少的關於 settings(設置)的解釋。

因為 exposedbydefault 被設置為 false,標籤 "traefik.enable=true" 將需要用於應該由 traefik 路由的容器。


這個文件將通過 bind mount 傳遞給 docker 容器,這將在我們為 traefik 使用 docker-compose.yml 時完成。


traefik.yml


## STATIC CONFIGURATION
log:
  level: INFO
api:
  insecure: true
  dashboard: true
entryPoints:
  web:
    address: ":80"
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

稍後,當 traefik 容器運行時,使用命令 docker logs traefik, 檢查是否有提示:"Configuration loaded from file: /traefik.yml"。您不想成為對 traefik.yml 進行更改的 moron,並且它什麼也不做,因為實際上並未使用該文件。


創建 .env


它包含一些環境變量。

域名,API密鑰,IP地址,密碼…… 無論是針對一種情況的特定情況,還是針對另一種情況的不同情況,所有這些都理想地放在了這裡。運行 docker-compose up 命令時,這些變量可用於 docker-compose。

這使得編寫文件可以更自由地從一個系統移動到另一個系統,並且可以對 .env 文件進行更改, 因此,在大型編寫文件或類似文件中忘記更改某些主機規則中的域名的錯誤可能性更小。


.env


MY_DOMAIN=example.com
DEFAULT_NETWORK=traefik_net

命令 docker-compose config 顯示了填充變量後的 compose 狀態。

這些變量僅在容器的初始構建期間填寫。如果一個 env 變量也應該在運行的容器中可用,則需要在 compose 文件的 environment 部分聲明它。


創建 traefik-docker-compose.yml


這是一個簡單的典型 compose 文件。

端口 80 已映射,因為我們希望 traefik 負責端口上的內容-將其用作 entrypoint(入口點)。端口 8080 用於 traefik 顯示信息的儀表板。需要掛載 docker.sock,因此它實際上可以完成與 docker 交互的工作。 traefik.yml 的掛載是給出靜態 traefik 配置的原因。默認網絡被設置為第一步中創建的網絡,因為它將在所有其他 compose 文件中設置。


traefik-docker-compose.yml


version: "3.7"
services:
  traefik:
    image: "traefik:v2.1"
    container_name: "traefik"
    hostname: "traefik"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/traefik.yml:ro"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK

運行 traefik-docker-compose.yml


docker-compose -f traefik-docker-compose.yml up -d 將會啟動 traefik 容器。

traefik 正在運行,您可以在 ip:8080 上檢查它,在那裡您可以得到儀表板。

也可以用 docker logs traefik 檢查日誌。

通常你會看到指南只有一個名為 docker-compose.yml 文件。其中包含多個服務/容器。然後只需 docker-compose up -d 就可以開始了。當所有都是一個 compose 時,你甚至不需要費心去定義網絡。但這一次,我更喜歡在學習新東西時採取小而獨立的步驟。這就是為什麼使用自定義命名的 docker-compose 文件,因為它允許更容易的分離。


您在教程中還可以看到沒有提及 traefik.yml,而東西只是使用 traefik 的命令或標籤從 docker-compose 傳遞的。


如: command: --api.insecure=true --providers.docker

但是這樣一來,組合文件看起來會更加混亂,您仍然無法從那裡進行任何操作,有時您仍然需要 traefik.yml。


所以...現在,使用結構良好的可讀 traefik.yml

在 traefik 應該路由的容器上添加標籤

以下是 whoami,nginx,apache,portainer 的示例。


- "traefik.enable=true"


啟用 traefik


- "traefik.http.routers.whoami.entrypoints=web"


定義名為 whoami 的路由,該路由在入口點 Web(端口80)上偵聽


- "traefik.http.routers.whoami.rule=Host(whoami.$MY_DOMAIN)"


定義此 whoami 路由規則,特別是當 url 等於 whoami.example.com(域名來自 .env 文件)時, 這意味著路由可以完成其工作並將其路由到服務。


不需要其他任何東西,traefik 可以從這些標籤來自 docker 容器的上下文中瞭解其餘信息。


whoami-docker-compose.yml


version: "3.7"
services:
  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    hostname: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.rule=Host(`whoami.$MY_DOMAIN`)"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK

nginx-docker-compose.yml


version: "3.7"
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    hostname: nginx
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.entrypoints=web"
      - "traefik.http.routers.nginx.rule=Host(`nginx.$MY_DOMAIN`)"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK

apache-docker-compose.yml


version: "3.7"
services:
  apache:
    image: httpd:latest
    container_name: apache
    hostname: apache
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.apache.entrypoints=web"
      - "traefik.http.routers.apache.rule=Host(`apache.$MY_DOMAIN`)"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK

portainer-docker-compose.yml


version: "3.7"
services:
  portainer:
    image: portainer/portainer
    container_name: portainer
    hostname: portainer
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - portainer_data:/data
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.portainer.entrypoints=web"
      - "traefik.http.routers.portainer.rule=Host(`portainer.$MY_DOMAIN`)"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK
volumes:
  portainer_data:

運行容器


docker-compose -f whoami-docker-compose.yml up -d
docker-compose -f nginx-docker-compose.yml up -d
docker-compose -f apache-docker-compose.yml up -d
docker-compose -f portainer-docker-compose.yml up -d

停止所有容器運行:docker stop $(docker ps -q)


Traefik 路由到本地 IP 地址


當 url 應該瞄準其他東西而不是 docker 容器。


微信圖片_20220611113342.png

定義 file provider,添加所需的路由和服務


所需要的是一個能夠捕獲某些 url 並將其路由到某些 IP 的 router。前面的示例顯示瞭如何在端口 80 上捕獲任何 url,但是沒有人告訴它在符合規則的情況下該怎麼做。Traefik 只是知道,因為它是在容器的上下文中使用標籤完成的, 而且由於 docker 在 traefik.yml 中被設置為提供程序。


對於這種 “在某些 IP 上發送流量”,需要 traefik 服務, 並且要定義 traefik 服務,需要一個新的提供程序, 即 file provider - 只是一個(fucking stupid)文件,告訴 traefik 該怎麼做。


某種常見的做法是將 traefik.yml 本身設置為 file provider,以便進行處理。

在提供者下有一個新的 file 部分,並設置了 traefik.yml 本身。

然後添加動態配置的東西。


一個名為 route-to-local-ip 的 router,有一個簡單的子域主機名規則。符合該規則(在本例中為確切的網址 test.example.com)的內容將發送到 loadbalancer 服務, 該服務會將其路由到特定的 IP 和特定的端口。

traefik.yml


## STATIC CONFIGURATION
log:
  level: INFO
api:
  insecure: true
  dashboard: true
entryPoints:
  web:
    address: ":80"
providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false
  file:
    filename: "traefik.yml"
## DYNAMIC CONFIGURATION
http:
  routers:
    route-to-local-ip:
      rule: "Host(`test.example.com`)"
      service: route-to-local-ip-service
      priority: 1000
      entryPoints:
        - web
  services:
    route-to-local-ip-service:
      loadBalancer:
        servers:
          - url: "http://10.0.19.5:80"

路由的優先級設置為 1000,這是一個非常高的值,超過了任何其他可能的路由。

不幸的是 .env 變量在這裡不起作用,否則主機規則中的域名和 IP 將來自變量。因此,抬起頭來,您肯定會忘記更改這些。


運行 traefik-docker-compose


測試是否有效


docker-compose -f traefik-docker-compose.yml up -d

Traefik 中間件


任何容器的身份驗證中間件的示例。

微信圖片_20220611113414.png

創建一個新文件 users_credentials

包含 username:passwords 對,htpasswd 格式

在下面的示例中,密碼 krakatoa 設置為下面所有3個帳戶

users_credentials


me:$apr1$L0RIz/oA$Fr7c.2.6R1JXIhCiUI1JF0
admin:$apr1$ELgBQZx3$BFx7a9RIxh1Z0kiJG0juE/
bastard:$apr1$gvhkVK.x$5rxoW.wkw1inm9ZIfB0zs1

掛載 users_credentials

traefik-docker-compose.yml


version: "3.7"
services:
  traefik:
    image: "traefik:v2.1"
    container_name: "traefik"
    hostname: "traefik"
    ports:
      - "80:80"
      - "8080:8080"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/traefik.yml:ro"
      - "./users_credentials:/users_credentials:ro"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK

在應該進行身份驗證的任何容器中添加兩個標籤


  • 第一個標籤將名為 auth-middleware 的新中間件附加到已存在的 whoami 路由器上。
  • 第二個標籤為該中間件提供了 basicauth 類型,並告訴它用於認證用戶的文件在哪裡。

無需在此處安裝 users_credentials,它是 traefik 所需的文件, 這些標籤是一種將信息傳遞給 traefik 的方式,它應該在容器的上下文中進行操作。


whoami-docker-compose.yml


version: "3.7"
services:
  whoami:
    image: "containous/whoami"
    container_name: "whoami"
    hostname: "whoami"
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.whoami.entrypoints=web"
      - "traefik.http.routers.whoami.rule=Host(`whoami.$MY_DOMAIN`)"
      - "traefik.http.routers.whoami.middlewares=auth-middleware"
      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=/users_credentials"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK

nginx-docker-compose.yml


version: "3.7"
services:
  nginx:
    image: nginx:latest
    container_name: nginx
    hostname: nginx
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.nginx.entrypoints=web"
      - "traefik.http.routers.nginx.rule=Host(`nginx.$MY_DOMAIN`)"
      - "traefik.http.routers.nginx.middlewares=auth-middleware"
      - "traefik.http.middlewares.auth-middleware.basicauth.usersfile=/users_credentials"
networks:
  default:
    external:
      name: $DEFAULT_NETWORK

運行容器,現在需要登錄名和密碼


docker-compose -f traefik-docker-compose.yml up -d
docker-compose -f whoami-docker-compose.yml up -d
docker-compose -f nginx-docker-compose.yml up -d

Leave a Reply

Your email address will not be published. Required fields are marked *