ホストのポート番号、足りていますか?!
docker-compose でバンバンサービスを立ち上げて監視しつつ、開発しつつ、実験などやっていると、3000
とか8080
とかぶつかって8081
とか8180
とか、ポート番号をずらすのが大変になってきますよね?
ちょっと違いますが僕は先日、k3s
上の何かのサービスのhttps用ポートで8443
がぶつかってしまったので6443
に変更し、 k3sのクラスタを丸ごと喪失させました。k3sが6443
使ってるんだよね!
Dockerで多数のサービスがサクサク動かせるのは良いことなのですがホストのポート番号がマヂでヤヴァイのであります。
そんなあなたに!今回は Traefik と nip.io
のワイルドカードDNS を使ってポート番号の衝突から解放される手順をご紹介します!
対象環境
OS: Ubuntu 18.04.3 LTS (Bionic Beaver)
docker: 19.03.5
docker-compose: v1.24.0
ip アドレス: 192.168.1.50
今回は ipアドレス 192.168.1.50
の Ubuntu に docker-compose でモリモリサービスを立ち上げてみます。
何をするのか
以下の手順で行う内容ですが、先にタネを明かしてしまいますと、nip.io
のワイルドカードDNSを使って xxxxx.192.168.1.50.nip.io
やyyyyy.192.168.1.50.nip.io
などをすべて 192.168.1.50
に解決させてしまいます。
これでホスト名が変わっても192.168.1.50
にすべてリクエストが行きますが、Traefikで "サブドメイン"でルーティングさせ て対応する Docker コンテナにリクエストを転送させるようにします。
また、Traefikの設定をコンテナ側で行うことで、コンテナをデプロイするだけで Traefik にサービスが自動的に登録されるようになります。
これによって Traefik コンテナだけで 80
番を待ち受けていれば、好きなコンテナを起動するだけでホスト名でのルーティングができるようになっている、ということが実現できます。
この手順を以下で紹介いたします!
1. Traefik の準備
まずは以下のような Traefik 起動用の docker-compose.yml
を、traefik
フォルダに作成いたします。
version: '3'
networks:
web:
driver: bridge
services:
reverse-proxy:
image: traefik:v2.1 # The official Traefik docker image
ports:
- "80:80" # The HTTP port
- "8080:8080" # The Web UI (enabled by --api)
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
- ./traefik.yml:/etc/traefik/traefik.yml
networks:
- web
まずは "network" に web
というネットワークを定義しております。
後ほど解説いたしますがここでは単に、traefik 経由で外に出たいコンテナはweb
ネットワークに入ってね、ということだけ覚えておけばOKです。
また他のdocker-compose.yml
からこのweb
ネットワークを参照しますが、docker-composeの作成するネットワークは**"フォルダ名_ネットワーク名"**になるます。
今回は traefik
フォルダでdocker-compsoeを起動しますので、他から参照する時はtraefik_web
というネットワーク名となります。
続いて Traefik のポートの設定ですが、80:80
と 8080:8080
の設定で80番と8080番はホストとバインドさせて、Traefik に入るようにいたします。このマシンで使用する80番と8080番はTraefik専用、といたします。
続いて volumes
で指定している ./traefik.yml:/etc/traefik/traefik.yml
ですがこれに対応するように以下の設定ファイルを作成いたします。
## traefik.yml
# https://docs.traefik.io/
# Docker configuration backend
providers:
docker:
exposedByDefault: false
defaultRule: "Host(`{{ index .Labels \"traefik.host\" }}.192.168.1.50.nip.io`)"
entryPoints:
http:
address: ":80"
# smtp:
# address: ":25"
# pop3:
# address: ":110"
# imap:
# address: ":143"
# mysql:
# address: ":3306"
# psql:
# address: ":5432"
# mongo:
# address: ":27017"
# API and dashboard configuration
api:
insecure: true
defaultRule
で "Host({{ index .Labels \"traefik.host\" }}.192.168.1.50.nip.io
)" を指定しております。
この "Host({{ index .Labels \"traefik.host\" }}.192.168.1.50.nip.io
)" がキモの一つです。
以下の設定サンプルにある通り、コンテナにつけた名前と"ラベル"がルールに使用できます。
今回はコンテナ名とは別に**traefik.host
ラベルで指定した文字列がサブドメインになる**ように指定いたしました。
続いてentryPoints
の設定ですが http を対象としますので、:80
のエントリーポイントを定義します。
また、例えばmongodbであれば 27017
を指定しておきます。ここで開けたポートは docker-compose.yml
のports
でも忘れなく指定しておきましょう。
このように使いたいポートを"エントリーポイント"としてあらかじめ定義しておきます。
2. Traefik の起動
準備が整ったところで以下のコマンドで Traefikを起動します。
$ docker-compose up -d
...
しばらくすると http://192.168.1.50.nip.io:8080
にてTraefikのダッシュボードが立ち上がると思います。
立ち上がらなければ設定にミスなどある可能性大なので docker-compose logs reverse-proxy
などでログを確認しましょう。
これでルーティングの準備は完了です。
3. サービスの起動
以下でいくつかのサンプルを上げてみましょう。
3-1. 例えば KeyCloak
それではサンプルとして最近お世話になっている KeyCloak
を立ち上げてみましょうか。
いつもの docker-compose.yml に Traefik 用の設定を追加します。
version : "3"
volumes:
kc_postgres_data:
driver: local
networks:
web:
external:
name: traefik_web
services:
kc-postgres:
image: postgres
volumes:
- kc_postgres_data:/var/lib/postgresql/data
environment:
POSTGRES_DB: keycloak
POSTGRES_USER: keycloak
POSTGRES_PASSWORD: password
keycloak:
image: jboss/keycloak:7.0.1
container_name: keycloak
restart: always
expose:
- 8180
environment:
DB_VENDOR: POSTGRES
DB_ADDR: kc-postgres
DB_DATABASE: keycloak
DB_USER: keycloak
DB_SCHEMA: public
DB_PASSWORD: password
KEYCLOAK_USER: admin
KEYCLOAK_PASSWORD: admin
networks:
- web
command: |
-Djboss.socket.binding.port-offset=100
depends_on:
- kc-postgres
tty: true
labels:
traefik.enable: true
traefik.host: keycloak
traefik.http.routers.keycloak.entrypoints: http
traefik.http.services.keycloak.loadbalancer.server.port: 8180
traefik.docker.network: traefik_web
早速ですが、
networks:
web:
external:
name: traefik_web
でtraefik
のweb
ネットワークをweb
という名前で参照いたします。この外部ネットワーク参照については過去の記事も読んでいただけると幸いです。
kc-postgres
は"keycloak用のPostgreSQL"なのでここはスルーいたします。
さて本命のkeycloak
です。
肝心なのは networks
で web
に参加していることと、labels
の設定です。
以下に列挙します。
-
traefik.enable
: このスイッチにより traefik でのルーティング対象とします。(traefik は基本的に全コンテナの起動と終了を監視しています。) -
traefik.host
: このラベルがサブドメイン名となります。ここではkeycloak.19.168.1.50.nip.io
だったらこのコンテナが呼ばれる、ということになります。 -
traefik.http.routers.keycloak.entrypoints
: 冒頭のtraefik.yml
で指定したエントリポイントを選択します。ここでは80
のhttpを使用します。 -
traefik.http.services.keycloak.loadbalancer.server.port
: 上記のhttpにマッピングされるこのコンテナのポートを指定します。keycloakが待ち受ける8180
を指定します。 -
traefik.docker.network
: treafik 側からこのコンテナを見るときのネットワークを指定します。これがないとtraefikはdefault
ネットワーク経由でこのコンテナのIPを参照してしまうようです。
traefik.docker.network
の指定が若干、残念ですがネットワークはいくらでも定義できるのでtraefik側から判断するのは困難なのでしょう。
実は、traefik_web
のネットワークに参加しなければならない大きな理由は、このtreafik側から見えるかどうかという問題です。先に立ち上がっているtraefikから、後で立ち上げたコンテナの名前を解決させるために同じネットワークに入れておく必要がある、ということなわけです。(結局、これも過去の記事と同じテーマなのです。。。)
これでブラウザから http://keycloak.192.168.1.50.nip.io
を開くと無事に Keycloakにアクセスできると思います!
3-2. 例えば Adminer
RDBに簡単につなぎに行けるWebクライアントとしては Adminerがもっともお手軽で強力だと思います。
docker-compose.ymlの追加部分はkeycloakと変わりませんのでサクッと立ち上げてしまいましょう。
version: '3'
networks:
web:
external:
name: traefik_web
services:
adminer:
image: adminer
container_name: adminer
restart: always
ports:
- 8080
networks:
- web
- db-admin
labels:
traefik.enable: true
traefik.host: adminer
traefik.http.routers.adminer.entrypoints: http
traefik.http.services.adminer.loadbalancer.server.port: 8080
traefik.docker.network: traefik_web
設定内容は上記と同じです。ただし、routers
とservices
の名前は変えておく必要があります。
前回は traefik.http.routers.keycloak.entrypoints
でしたが、今回は traefik.http.routers.adminer.entrypoints
です。
この設定で http://adminer.192.168.1.50.nip.io
で Adminer にアクセスできるようになります!
Keycloakよりシンプルだから先にこっちを挙げておけばよかったか。。。
あとはお好きなサービスでどうぞ!
トラブルシューティング
traefik のダッシュボードではエラーメッセージは一切出ないのが難点です。
コンテナ起動してもダッシュボードに反応がなければ docker-compose logs -f reverse-proxy
で treafik のログを参照するしかないです。
traefik のエラーログではgoのエラーメッセージが出てしまうのでちょっとわかりにくいのがさらに厳しいです。
ソースコード見ても落ちている箇所はわかるけどどう設定すればいいの?みたいな場合が多々あります。
ここはダッシュボードで優しく教えてくれないかな・・・
まとめ
本家サイトのガイドではDockerを使った場合も設定ファイルにガリガリ記述させるので、コンテナ立ち上げるたびに設定直してたらキリがないな…とあまり興味がなかったのですが、以下のしれっとした記述でラベルで設定できるのを見つけたので、これ幸いと traefik を導入致しました。
いや、これあっさりしすぎでしょう。この機能、超重要ですよ?
とにかく、このようにワイルドカードDNSとTraefikを組み合わせることで、社内からアクセスできるサービスをdocker-composeでポート番号を気にせずにバンバン立ち上げることができました。
また、ワイルドカードDNSはlocalhost
ではないちゃんとしたホスト名なので KeycloakでのOAuth設定もばっちりです。社内サービスのSSO化もバリバリ捗ります。
いや~素晴らしい!
本日は以上といたします。