Traefik 路由到 Docker 容器
創建一個新的 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 容器。
定義 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 中間件
任何容器的身份驗證中間件的示例。
創建一個新文件 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