はじめに
docker環境で、HTTPS対応のリバースプロキシ環境を利用する場合、いくつか選択肢があると思います。
自分は今まで以下のNginxを使用しLet’s EncryptによるHTTPSプロキシを作るというものを利用していました。
JrCs/docker-letsencrypt-nginx-proxy-companion: LetsEncrypt companion container for nginx-proxy
しかし、最近はk8s (kubernetes)などが流行していることもあり、そちらでよく利用されるTraefikでも、リバースプロキシとしての機能はもちろん、Let’s Encrypt機能も使えるということを知ってから、こちらを利用してみることにしました。
Traefikを利用して、Docker環境にLet’s Encryptを使用する方法については、公式ドキュメントでも項目が用意してあります。
Traefikの良いところは、Traefikが利用するネットワークに、HTTPSでリバースプロキシしてもらいたいcontainerを所属させておけば、再起動しなくても自動的にリバースプロキシ配下に組み込んでくれる点にあります。
containerがスケールしても、自動的にリバースプロキシに組み込んでくれるので、手がかからなくて良いです。また、振り分けのルールも柔軟に設定できる点や、TraefikにUIが用意されているため、簡易的にではありますが、パフォーマンスなどを確認できる点も良いと思います。
前置きが長くなりましたが手順を書いておこうと思います。
手順:
まずは、コンテナ同士の通信に使用するネットワークを作成する。
$ docker network create https-network
次にロードバランサーとして使用する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
特に、touch /opt/traefik/acme.json && chmod 600 /opt/traefik/acme.json
をしておかないと、acme.json
なディレクトリが作成されてしまうので注意が必要です。(最初、これの意味が分からなくて困っていました)
docker-compose.yml
を以下のように記述します。
version: '3'
services:
reverse-proxy:
image: traefik:latest
container_name: traefik
restart: always
ports:
- "80:80"
- "443:443"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
- ./traefik.toml:/traefik.toml
- ./acme/acme.json:/acme.json
networks:
- https-network
networks:
https-network:
external: true
Traefik container を起動する前に、設定ファイルを用意します。
logLevel = "ERROR"
defaultEntryPoints = ["https", "http"]
[entryPoints]
[entryPoints.http]
address = ":80"
[entryPoints.http.redirect]
entryPoint = "https"
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[retry]
[api]
[acme]
email = "[email protected]"
storage = "acme.json"
onHostRule = true
#caServer = "https://acme-staging-v02.api.letsencrypt.org/directory"
caServer = "https://acme-v02.api.letsencrypt.org/directory"
entryPoint = "https"
acmeLogging = true
[acme.httpChallenge]
entryPoint = "http"
[docker]
endpoint = "unix:///var/run/docker.sock"
watch = true
domain = "example.com"
exposedByDefault = false
httpのアクセスはhttpsにリダイレクトするように設定しています。
尚、[acme]
セクションのemailについては、本物のメールアドレスを指定する必要があります。架空のメールアドレスだとLet’s Encryptの設定に失敗します(真正性の証明ができないため)。
取得できたSSL証明書は、acme.json
に保管されます。
ここまで準備できたら、Traefikを起動します。
$ cd /opt/traefik
$ docker-compose up -d
あとは、同じネットワーク内にアプリケーションcontainerを立ち上げればOKです。
適当なディレクトリに以下の内容で docker-compose.yml
を用意してください。(例えば、bitwarden rustの場合)
version: '3'
services:
bitwarden:
image: mprasil/bitwarden:alpine
restart: always
volumes:
- ./bw-data/:/data/
ports:
- 1024:1024
environment:
ROCKET_PORT: "1024"
WEBSOCKET_ENABLED: "true"
SIGNUPS_ALLOWED: "false"
ADMIN_TOKEN: ""
DOMAIN: "https://bitwarden.example.com"
SMTP_HOST: ""
SMTP_FROM: "<[email protected]>"
SMTP_PORT: "true"
SMTP_SSL: "true"
SMTP_USERNAME: ""
SMTP_PASSWORD: ""
labels:
traefik.docker.network: "https-network"
traefik.enable: "true"
traefik.basic.port: "1024"
traefik.basic.frontend.rule: "Host:bitwarden.example.com"
traefik.basic.protocol: "http"
networks:
- https-network
networks:
https-network:
external: true
※ドメインやネットワークなどは適宜自分の設定に読み替えてください。
ポイントは、「labels
」セクションです。Traefikに対して、このコンテナへ接続する仕様を伝えます。
TraefikでSSLの処理をすべて行ってくれるので、アプリケーションコンテナではSSLの処理が不要となります。
準備ができたら、アプリケーションコンテナを起動します。
$ docker-compose up -d
以上で、TraefikがLet’s Encryptによる証明書を利用する形で配下のcontainerにhttpsによるサービスを提供できるようになるはずです。