DockerのTraefikを使って簡単にロードバランサーを作ることができましたので、紹介したいと思います。
ネットワーク内でアプリ(wordpressやwebサービス)のコンテナを起動すれば、自動的にLet’s Encryptの設定が行われます。アプリのコンテナを複数起動すれば、ロードバランサーとして振り分けもしてくれます。セッション維持の有無についても簡単に指定できます。
前準備
外部に公開されたサーバを用意してください。最近は気軽にVPSサーバを借りられるようになりましたので、それらを利用するのもおすすめです。
サーバにはDockerとdocker-composeをインストールしておいてください。
ここでは「test-loadbalancer.com」というドメインがサーバに割り当てられているものとして、説明を進めていきますので、適宜置き換えて解釈してください。
ロードバランサーを作る
まずは、コンテナ同志の通信に使用するネットワークを作ります。
docker network create web
次にロードバランサーとして使用するTraefikを設定するディレクトリを用意します。
mkdir -p /opt/traefik
このディレクトリ内に、以下の3つのファイルを作ります。
touch /opt/traefik/docker-compose.yml touch /opt/traefik/acme.json && chmod 600 /opt/traefik/acme.json touch /opt/traefik/traefik.toml
docker-compose.yml を以下のように記述します。
version: '2'
services:
traefik:
image: traefik
restart: always
ports:
- 80:80
- 443:443
networks:
- web
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- /opt/traefik/traefik.toml:/traefik.toml
- /opt/traefik/acme.json:/acme.json
container_name: traefik
networks:
web:
external: true
ports:
外部に公開するポートを指定します。ここではhttpとhttpsを指定しています。
network:
先程準備したdocker内のネットワーク名を指定します。
volumes:
コンテナの追加や削除を検知するための記述と、traefikの設定ファイル、Let’s Encrypt用の設定ファイルをマウントしています。
Traefik container を起動する前に、設定ファイルを用意します。
debug = false
logLevel = "ERROR"
defaultEntryPoints = ["https","http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[retry]
[docker]
endpoint = "unix:///var/run/docker.sock"
domain = "test-loadbalancer.com"
watch = true
exposedByDefault = false
[acme]
email = "your-email@test-loadbalancer.com"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
[acme.httpChallenge]
entryPoint = "http"
httpのアクセスはhttpsにリダイレクトするように設定しています。
尚、[acme]セクションのemailについては、あなたの本物のメールアドレスを指定する必要があります。架空のメールアドレスだとLet’s Encryptの設定に失敗します。
SSL証明書は、acme.jsonに保管されます。
ここまで準備できたら、Traefikを起動できます。
cd /opt/traefik docker-compose up -d
あとは、同じネットワーク内にアプリケーションコンテナを立ち上げればOKです。
ここでは、「tutum/hello-world」イメージを使ってサンプルを作ります。
適当なディレクトリに以下の内容で docker-compose.yml を用意してください。
version: '2.1'
services:
app:
image: tutum/hello-world
networks:
- web
- default
expose:
- "80"
labels:
- "traefik.enable=true"
- "traefik.docker.network=web"
- "traefik.frontend.rule=Host:test-loadbalancer.com"
- "traefik.port=80"
- "traefik.protocol=http"
networks:
web:
external: true
ポイントは、「labels」セクションです。traefikに対して、このコンテナへの接続する仕様を伝えます。
“traefik.enable=true”
このコンテナがtraefikを使用することを宣言します。
“traefik.docker.network=web”
このコンテナはwebネットワークを使用してtraefikと通信します。
“traefik.frontend.rule=Host:test-loadbalancer.com”
このコンテナでは、ここで指定したドメイン宛のリクエストを受け付けます。
“traefik.port=80”
80番ポートでリクエストを受け付けます。
“traefik.protocol=http”
通信のプロトコルは、httpであることを宣言します。
traefikでSSLの処理をすべて行ってくれるので、アプリケーションコンテナではSSLの処理が不要になります。
準備ができたら、アプリケーションコンテナを起動します。
docker-compose up -d
これで、サンプルサイトの公開が完了しました。
ブラウザから確認してみましょう!

こんなサイトが表示されていれば成功です。SSL証明書の設定も自動的に行われています。
では、再度コンソールに戻って、以下のコマンドでアプリケーションを3つに増やしてみましょう。
docker-compose scale app=3
ブラウザをリロードしてみてください。リロードの度に「My hostname is」の後の文字が変わるのが分かりますでしょうか?
ロードバランサーによって、3つのアプリケーションにラウンドロビンで順に振り分けが行われるようになりました。
なんということでしょう、アプリケーションのコンテナさえ用意しておけば、コマンドひとつでスケール出来てしまいます。
ただし、セッションを使うウェブアプリなどの場合は、これでは困ります。アクセスの度にセッションが切れてしまいます。traefik導入の前には、Nginxのリバースプロクシを使ったロードバランサーを検討していたのですが、ip_hushを使った振り分けになるため、wifi環境などでは不具合が出るのではという懸念がありました。traefikでは、cookieを使った振り分けに対応しているため、こうした心配は無用です。
では、先程のアプリケーションを、cookieを使用した振り分けに変更して行きましょう。
再度、アプリケーションコンテナの設定ファイルを開いて、labelsセクションに1行追加してください。
labels:
- "traefik.enable=true"
- "traefik.docker.network=web"
- "traefik.frontend.rule=Host:test-loadbalancer.com"
- "traefik.port=80"
- "traefik.protocol=http"
- "traefik.backend.loadbalancer.stickiness=true"
先程の設定ファイルに以下の一行を追加しただけです。
“traefik.backend.loadbalancer.stickiness=true”
保存したら、コンテナを再起動します。
docker-compose restart
ブラウザでサイトを表示してリロードしてみましょう。
いかがでしょうか?
リロードしてもHOSTNAMEが変わらず、同じコンテナにアクセスする状態になったと思います。
あっという間に、ロードバランサーが出来上がってしまいました。
今はひとつのホスト内で運用するテストを行いましたが、次はマルチホストでの運用に挑戦してみたいと思います。
ホームページの制作(デザイン・コーディング・プログラミング)に加え、ネットショップの販売促進に関するアドバイスも致します。 20年以上に渡って実際にネットショップを運営した経験を生かし、聞きかじりではない実績を伴ったノウハウを、自分の言葉でお伝えいたします。 プログラミングの経験は30年以上。HTML、CSS、JavaScript、TypeScript、Vue、NuxtJS、Node.js、MySQL、MongoDB、Elasticsearch、WordPress、PHP、Docker、Electronなど、幅広く対応します。


コメント