Docker連携リバースプロキシで複数コンテナへのアクセスを簡単にする[Traefik]
Reverse-ProxyのTraefikを使っています。Dockerコンテナを使った開発環境では便利!
私のローカル環境での使い方をまとめておきます。
この記事ではDnsmasqについてMacでインストールする手順を書いているだけですが、別記事でWindows用の説明もあります。
また、それ以外にも自己証明書を発行してHTTPSアクセスしたり、ダミーメールボックスのMailHogについても触れていますのでよかったらみてください。
Traefikとは
Traefik is an open-source Edge Router that makes publishing your services a fun and easy experience.
エッジルーターらしいです。まだクラウドとかエッジとかの知識がないのでよく分かりません。
私としてはサブドメインのページを手軽に作れるリバースプロキシーとして使用しています。
便利な点:
- docker composeでlabelsを設定するだけで動く
- なんならコンテナ起動するだけでいい
- リバースプロキシーの設定が不要なので手軽
- ポート番号をいちいち考えなくてもいい
- リバースプロキシーがなければ、アプリごとにポート番号を割り当てる必要があり大変
- ダッシュボードで設定が確認できる
- どのアプリが起動しているかブラウザで一覧できる
ダッシュボードのスクリーンショット
ルーターのスクリーンショット
前提
使用マシンは Mac mini (M1, 2020)で、Docker環境を Colima で構築しています。
が、他の環境でも同じでしょう。
設定
ここでは開発環境を想定した説明となります。そのためできるだけ対応が少ない方法をとっています。
ということでTraefikeのDockercompose.yaml
を用意して起動します。
compose.yaml
services:
traefik:
image: traefik
hostname: reverse-proxy
restart: unless-stopped
volumes:
# dockerと連携するために必要
- /var/run/docker.sock:/var/run/docker.sock:ro
command:
# docker連携を有効にして、デフォルトのルールを設定
- --providers.docker.defaultRule=Host(`{{ normalize .Name }}.localhost`)
# entrypointsで対応したいポート番号を書く
- --entrypoints.http.address=:80
- --entrypoints.mongodb.address=:27017
# apiを有効にするとダッシュボードが見れる(http://localhost:8080/)
- --api.insecure=true
# コンテナ間をhost経由でアクセスさせるためネットワークモードを指定
network_mode: host
これを docker compose up -d
で起動すると、http://localhost:8080/
でTraefikのダッシュボードが確認できます。
defaultRule
に.localhost
を追加しています。通常だと{{ normalize .Name }}
だけなのでブラウザで簡単にアクセスできません。
entrypoints
にポート番号を2つ指定しています。Traefikはhttpだけでなく、tcpにも対応しています。
--entrypoints.{任意の名前}.address=:{ポート番号}
でポート番号を利用する入り口がつくられます。
分かりづらいですが、api.insecure
を有効にするとダッシュボードも一緒に見れるようになります。
apiが何なのかは調べてないのでわからないですが本番では注意が必要だと思います。
このように設定を全て起動引数で指定すると、設定を変更したときにdocker compose up -d
を再度行うだけで反映されます。
traefik.yaml
を用意してマウントする方式だと一旦止めないと設定が反映されません(docker compose restart
も可)。(ファイル保存だけで反映される方法があればぜひ教えて〜)
使用
コンテナ単体起動
docker run --rm -d --name caddyTest caddy
caddyが何かはよく知らないけど、どれかのサンプルで使われてて、「おめでとう!」と言ってくれるので出来た感が嬉しい。
それはそれとして、このコマンドで起動後にダッシュボードを見るとcaddyTest.localhost
が追加されてるのが確認できます。
Chromeでhttp://caddyTest.localhostにアクセスすると、「おめでとう!」と言ってくれます。
大文字小文字の区別はありません。http://caddytest.localhostでもOK。
NOTICE 注意
Safariだと.localhost
の名前解決できません。Safariで確認が必要なら、ローカルDNSを立ち上げる必要があるようです。
ローカルDNS Dnsmasq
Dnsmasqは次の手順で動きます。
-
brew install dnsmasq
でインストール -
/opt/homebrew/etc/dnsmasq.conf
に追記(/otp/homebrewはhomebrew --prefix
で確認可能)# localhostを127.0.0.1に解決 address=/.localhost/127.0.0.1
-
sudo brew services start dnsmasq
で起動 -
sudo mkdir /etc/resolver
でDNS指定用のディレクトリ作成 -
sudo vi /etc/resolver/localhost
でlocalhostファイルを作る(ファイル名がドメイン名)nameserver 127.0.0.1 options timeout:1
-
ping -c 1 hoge.localhost
で動作確認 -
Safariでhttp://caddyTest.localhostにアクセスすると、「おめでとう!」と言ってくれます。
compose起動
caddyさんには退場してもらいましょう。(docker stop caddyTest
)
普段はオプションが面倒なのでcompose.yamlを利用しています。例えばMongoDBを例にしてみましょう。
name: my-proj
services:
mongo:
image: mongo
hostname: mongo
restart: unless-stopped
ports:
- 127.0.0.1::27017
volumes:
- mongodb-data:/data/db
- mongodb-config:/data/configdb
labels:
# traefikの設定
traefik.tcp.routers.mongo.entrypoints: mongodb
traefik.tcp.routers.mongo.rule: HostSNI(`*`)
mongo-express:
image: mongo-express
hostname: mongo-express
restart: unless-stopped
depends_on:
- mongo
ports:
- 127.0.0.1::8081
environment:
ME_CONFIG_MONGODB_SERVER: host.docker.internal
volumes:
mongodb-data:
mongodb-config:
これでhttp://mongo-express-my-proj.localhostでMongo Expressにアクセスできます。
これは、traefikのルールの.Name
がservice名(mongo-express)-COMPOSE_PROJECT_NAME(my-proj)となるためです。
MongoDBの方はというと、labels:
の指定があります。
というのもデフォルトではHTTPプロトコルとして登録されるためで、TCP通信の場合は指定が必要です。
traefik.tcp.{任意の名前}.entrypoints
で使用するポート番号を指定し(traefikの起動コマンドで書いたもの)、
traefik.tcp.{同上}.rule
で条件を指定します。TCPのルールはほとんど書けません。(TLSならドメイン名で分岐ができるらしい)
このサンプルではmongo-expressからmongoへのアクセスを無理やりホスト経由(host.docker.internal)にしています。
ホスト側を127.0.0.1の自動で割り振りのポート番号を利用している127.0.0.1::8081)ので、本来はdocker compose ps
で確認できる大きい数字のポート番号でアクセスする必要があります。
間にTraefikが入ってくれて、いい感じにコンテナに転送してくれています。
ここでTraefikのダッシュボードを見てください。
TCPの方はいい感じに登録されています。
HTTPの方はEntrypointsにhttpとmongodbの両方が登録されてしまっています。
これはTraefikに登録しているentrypointsが全て割り当てられるためで、実はhttp://mongo-express-my-proj.localhost:27017でアクセスできる時もあります。(MongoDBが立ち上がってなくて、Mongo Expressが他のDBに繋がってる時)
Version 1時代はdefaultEntrypointsで指定できたみたいですが、今のVersion 2だと無理みたいです。
ここでは開発用なので気にしないですが、本番ではちゃんと設定したほうがいいでしょう。
本番運用に向けて
本番(と言ってもアクセスが限定される社内)ではもう少し設定を書いて運用してます。
- Traefikの設定を
traefik.yaml
に書いて、/etc/traefik/traefik.yaml
にマウント -
providers.docker.exposedByDefault=false
にして、余計なものが公開されないようにする- compose.yamlのlabelsにエントリーポイントやルールを明記する
- ルールにパスを見たり、クエリを見たり、ミドルウェアを利用してパスを変換したり(/apiを消すとか)、リダイレクトしたり、SSL利用したり使用方法はいろいろあります
まとめ
ローカルで複数のコンテナを起動する場合はTraefikがあるとかなり便利ですのでおすすめです。
とりあえず使う分には手軽ですので試してみると幸せになれるかもしれません。
Traefikを含めたDocker開発環境基盤を組み立てたい人は、下記の記事、本も参考にしてください。自己証明書を発行してHTTPSアクセスしたり、ダミーメールボックスのMailHogについても触れています。
Discussion