1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

DockerSwarmでデプロイしたコンテナを自動的にtraefikに登録する

Posted at

概要

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
スクリーンショット 2021-12-19 17.51.45.png

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では動かなかったりするよ!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?