概要
swarmでデプロイしたら特に何もしなくてもtraefikにルーティングルールが追加されてサービスが公開できるようにする。
もし、さくらのクラウドで試すなら1Hでやり切れば30円くらいで試せる。2Hだと60円。
どうしてこの記事を書いたか
以前書いた、「docker swarmを一から構築してrolling updateとかしつつ、HAproxyを介してサービスを公開する」という方法だと、
新しいコンテナをデプロイする度にHAProxyのconfig書き換えないといけないので。
それはやばいから。
Docker + consul-template で HAProxy のバックエンド登録の自動化を試す という
ためになる記事にもあるようにHAProxyでも解決する方はありそうだけど、traefik使ってみたいじゃないか。
準備(前提)
- DowckerSwarmでマネージャーとノードを一台づつ構築済み
例えば、docker node ls
すると以下の感じになっている。
ubuntu@swarm-manager001:~$ sudo docker node ls
[sudo] ubuntu のパスワード:
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
c0oca505hi63sho914quutct7 * swarm-manager001 Ready Active Leader 20.10.11
itcdqn487rk97gx044igqqfab swarm-worker001 Ready Active 20.10.11
ubuntu@swarm-manager001:~$
-
test_proxy という名前でオーバーレイネットワークを構築済み
e.g.sudo docker network create --driver overlay test_proxy
っていう感じで作れる。 -
https://github.com/tomokitamaki/train_traefik をclone しておく
git clone https://github.com/tomokitamaki/train_traefik.git
的な感じ。 -
traefikのバージョンは
2.5.5
です
traefikをデプロイする
cloneしたディレクトリ内で以下のコマンドを実行する。
sudo docker stack deploy -c traefik.yaml traefikz
e.g.
ubuntu@swarm-manager001:~/train_traefik$ sudo docker stack deploy -c traefik.yaml traefikz
Creating service traefikz_traefiks
ubuntu@swarm-manager001:~/train_traefik$
traefik の管理画面を見てみる
swarmのクラスタ内のマネージャやノードのIPの8080番ポートにブラウザでアクセスしてみる。
e.g. 例えばこんなURL
http://192.168.1.20:8080
アクセスしたら以下みたいななんかかっこいい画面が見えたらOKOK
traefik.yaml の解説
version: "3.4"
services:
traefiks: # サービスの名前
image: traefik:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro
command:
- "--providers.docker.swarmMode=true" # swarmmodeで動かすという宣言
- "--api.insecure=true" #ダッシュボードを有効にするという宣言
- "--providers.docker.exposedByDefault=false" #trueだとデプロイされたコンテナを全部もれなくtraefikが見つけちゃうので、見つけてほしいものだけにする宣言
- "--providers.docker.network=test_proxy"# test_proxy というオーバーレイネットワーク上のコンテナを見つけるという宣言
ports:
- target: 80
published: 80
- target: 8080
published: 8080
deploy:
placement:
constraints:
- node.role == manager
networks:
- test_proxy
networks:
test_proxy:
external: true # test_proxy というネットワークはyamlの管理外という宣言
nginx をデプロイする
cloneしたディレクトリ内で以下のコマンドを実行する。
sudo docker stack deploy -c nginx.yaml nginxz
e.g.
ubuntu@swarm-manager001:~/train_traefik$ sudo docker stack deploy -c nginx.yaml nginxz
Creating service nginxz_nginxs
ubuntu@swarm-manager001:~/train_traefik$
nginxのあの画面を見る
swarmのクラスタ内のマネージャやノードのIPの80番ポートにブラウザでアクセスしてみる。
e.g. 例えばこんなURL
http://192.168.1.20
いつもの "welcome" が見えたらOKOK.
次は、ヘッダーのHostに "nginx.tmktmk.domdom.burger" を指定してみる。
curlでやってみよう。
例えば、 curl -H Host:nginx.tmktmk.domdom.burger 192.168.1.20
な感じでやってみて、
welcomeなHTMLが返ってきたらいい感じ!
e.g. 例えば以下の感じ。
ubuntu@swarm-manager001:~/train_traefik$ curl -H Host:nginx.tmktmk.domdom.burger 192.168.1.20
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>
<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
ubuntu@swarm-manager001:~/train_traefik$
nginx.yaml の解説
version: "3.4"
services:
nginxs:
image: nginx:latest
ports:
- target: 80
published: 9000
deploy:
placement:
constraints:
- node.role == worker # コンテナはworkerの役割のノードで動かすという宣言
replicas: 2
labels:
- "traefik.enable=true" # traefikに見つけてもらいたいという宣言
# - "traefik.http.routers.nginxs.rule=Host(`me.example.com`)"
- "traefik.http.routers.nginxs.rule=PathPrefix(`/`) || HOST(`nginx.tmktmk.domdom.burger`)" # ルーティングのルールとして "/" か ヘッダーのHostが "nginx.tmktmk.domdom.burger" であることを宣言
- "traefik.http.services.nginxs.loadbalancer.server.port=80" # ルールに当てはまるものはコンテナの80番ポートにルーティングするという宣言
networks:
- test_proxy
networks:
test_proxy:
external: true
fastapi をデプロイする
cloneしたディレクトリ内で以下のコマンドを実行する。
sudo docker stack deploy -c fastapi.yaml fastapiz
e.g.
ubuntu@swarm-manager001:~/train_traefik$ sudo docker stack deploy -c ./fastapi.yaml fastapiz
Creating service fastapiz_fastapis
ubuntu@swarm-manager001:~/train_traefik$
訳あって nginxz_nginxs のサービスを削除する
以下のコマンドで削除する。
sudo docker service rm nginxz_nginxs
サービス名は以下のコマンドで見れる。NAMEの列がサービス名。
ubuntu@swarm-manager001:~/train_traefik$ sudo docker service ls
ID NAME MODE REPLICAS IMAGE PORTS
qckdsxxn8ck7 fastapiz_fastapis replicated 1/1 tiangolo/uvicorn-gunicorn-fastapi:latest *:8000->80/tcp
pfu9szua7wsf nginxz_nginxs replicated 2/2 nginx:latest *:9000->80/tcp
u85fs2isk3lz traefikz_traefiks replicated 1/1 traefik:latest *:80->80/tcp, *:8080->8080/tcp
ubuntu@swarm-manager001:~/train_traefik$
fastapiにアクセスしてみる
ヘッダーのHostに "fastapi.tmktmk.domdom.burger" を指定してみる。
curlでやってみよう。
例えば、 curl -H Host:fastapi.tmktmk.domdom.burger 192.168.1.20
な感じでやってみて、
それっぽいjsonが返って来たらいい感じ!
e.g.
ubuntu@swarm-manager001:~/train_traefik$ curl -H Host:fastapi.tmktmk.domdom.burger 192.168.1.20
{"message":"Hello world! From FastAPI running on Uvicorn with Gunicorn. Using Python 3.9"}ubuntu@swarm-manager001:~/train_traefik$
ちなみにパスを /docs
とするとopenapiの内容が返ってくる。
e.g.
curl -H Host:fastapi.tmktmk.domdom.burger 192.168.1.20/docs
<!DOCTYPE html>
<html>
<head>
<link type="text/css" rel="stylesheet" href="https://cdn.jsdelivr.net/npm/swagger-ui-dist@3/swagger-ui.css">
<link rel="shortcut icon" href="https://fastapi.tiangolo.com/img/favicon.png">
<title>FastAPI - Swagger UI</title>
</head>
(後略)
fastapi。yamlの解説
省略。nginxのと一緒です。
nginxz_nginxs のサービスを削除しないとどうなるか
nginxのコンテナにルーティングされてしまい、fastapiのコンテナにルーティングされません。
なぜなら、nginxのコンテナのルーティングに "/" なものというルールが入っているのでそちらが先にマッチングしてしまいます。
どういった規則(ロンゲストマッチとかデプロイ順とか)でマッチングするのかは調べていません。さーせん。
まとめ
ヘッダーのHostでルーティングするなら、managerやノードのIPに対して *.tmktmk.domdom.burger
みたいなAレコードを作っておくと、シュシュっとコンテナを公開出来て便利。
traefikでHTTPSを終端するとか、let's encrypt の証明書の自動更新をするとか他にも色々出来るので、
やってみたいぞ!ってなったら公式ドキュメントをみよう。
https://doc.traefik.io/traefik/contributing/documentation/
あと、どこかのバージョンから引数とか変わったみたいなので、
ググって出てくる昔の記事のconfigでは動かなかったりするよ!