traefik の tips
traefik
が向かない環境はある
自分の環境が特殊だからかも知れないが,
- 80番ポートが既に埋まっている
- 別のリバースプロキシの下流に置く
-
traefik
からみた上流がサブドメインではなく「メインドメインのパス」になっている
上記の場合は採用を避けたほうが無難であると思う.どうにかしようと5日ほど頑張ってみたが,今の私の経験ではうまくいかなかった.
上記の条件があるとき,ルーティングのルールを工夫したり,ミドルウェアを定義して適宜調整したりする必要が増える.これは traefik
の手軽さを自ら殺す行為であり,まず触ってみようという段階で手を出すべきではない(心が折れるので).
traefik
が向いている環境もある
全部自分で管理できる環境であれば,積極的に採用すべきと思う.すなわち 80番を traefik
に割り当てることが出来て,大元のリバースプロキシは traefik
が担い,メインドメインをそのまま使えるのなら,ということである.
これは単に個人のVPS環境ということだけでなく,ローカル環境の開発でもっとも生きるということである.例えばルーティングのルールを Host(`subdomain.${HOSTNAME}`)
にして,環境変数に HOSTNAME=localhost
としておけば,http://subdomain.localhost
でアクセスできるようになる.いちいちポート番号を打ち込む必要はないし,server.loadbalancer=${POST_NUMBER}
とすればポート番号も環境変数経由で外部から決定することが出来る.もちろんプロダクション環境においては,この HOSTNAME
を置き換えればいいだけである.
PathPrefix solution
labels:
- traefik.http.middlewares.strip-prefix.chain.middlewares=strip-prefix-1,strip-prefix-2
- traefik.http.middlewares.strip-prefix-1.redirectregex.regex=^(https?://[^/]+/[a-z0-9_]+)$$
- traefik.http.middlewares.strip-prefix-1.redirectregex.replacement=$${1}/
- traefik.http.middlewares.strip-prefix-1.redirectregex.permanent=true
- traefik.http.middlewares.strip-prefix-2.stripprefixregex.regex=/[a-z0-9_]+
cf. 【魚拓】Middleware to add the "/" if needed - Traefik / Traefik v2 - Traefik Labs Community Forum
補足
ルーティングの rule
を PathPrefix
にしている際に,末尾のスラッシュ(trailing slash
)を落とすとコンテナに繋がらないことがある.これを繋がるはずのパスへリダイレクトさせて解決する(strip-prefix-1
).また,コンテナ内ではルートパス /
を期待しているのに,実際には /router-x
のようなパスで降ってくることになる.よってこれを取り除いてからコンテナ内部とつなぐ(strip-prefix-2
).
上記の工程は EntryPoint
で受け取ってからコンテナに渡すまでの中間的な処理であるが,これを担うのが middlewares
である.特に今回のように複数個のミドルウェアを使用する場合には,chain
という処理も走ることになる.
traefik の使い方 in Docker
- traefik コンテナを用意する(Nginxコンテナのようにリバースプロキシとしてつかう)
- コンテナ内に
traefik.toml
を用意して,「プロバイダとしてDockerを使う」という設定を仕込む(静的設定) - ルーティングしたいアプリケーションコンテナにラベルを付ける(動的設定)
Configuration in Traefik can refer to two different things
Docker-compose basic example
以下のサンプルのように,実は静的設定として traefik.toml
をマウントする必要はないのだが,そうすると代わりに docker-compose.yml
に長々とラベルを付けることになってしまう.動的に変更されないものはなるべく静的設定として traefik.toml
に書いたほうがいいように思う.
cf. https://doc.traefik.io/traefik/user-guides/docker-compose/basic-example/
version: "3.3"
services:
traefik:
image: "traefik:v2.4"
container_name: "traefik"
command:
#- "--log.level=DEBUG"
- "--api.insecure=true"
- "--providers.docker=true"
- "--providers.docker.exposedbydefault=false"
- "--entrypoints.web.address=:80"
ports:
- "80:80"
- "8080:8080"
volumes:
- "/var/run/docker.sock:/var/run/docker.sock:ro"
whoami:
image: "traefik/whoami"
container_name: "simple-service"
labels:
- "traefik.enable=true"
- "traefik.http.routers.whoami.rule=Host(`whoami.localhost`)"
- "traefik.http.routers.whoami.entrypoints=web"
ルーティングに関する tips
許されるならば,各アプリケーションコンテナごとに新たなサブドメインを割り振ってやるのがよい.これはローカルで開発する際に ttp://traefik.localhost
のように簡単にアクセスできるようになることを意味する.アドレスバーにポート番号を打ち込む時代は終わったってワケ(笑)
基本的には,
- エントリーポイント=コンテナ外部からアクセスするときのポート番号を定義する
- コンテナ内の何番ポートとつなぐのか
traefik
コンテナ(ロードバランサ)に伝える - どのようなルーティングにするのかルールを決める
だけラベル付けしてやればよい.
labels:
- "traefik.enable=true" # due to `exposedByDefault=false`
- "traefik.http.routers.my-service.entrypoints=web" # 1. define EntryPoint
- "traefik.http.services.my-service.loadbalancer.server.port=${PORT_NUMBER}" # 2. define server port
- "traefik.http.routers.my-service.rule=Host(`traefik.${HOSTNAME}`)" # 3. define routing
ここで my-service
とは,docker-compose.yml
のトップレベルでも定義されている services
以下の名前である(e.g. db
, app
, redis
etc.).