Ubuntu20.04でDockerコンテナのリバースプロキシとしてTraefikv2を使用する方法
著者は、 Write for DOnations プログラムの一環として、 Girls WhoCodeを選択して寄付を受け取りました。
序章
Docker は、本番環境でWebアプリケーションを実行するための効率的な方法ですが、同じDockerホストで複数のアプリケーションを実行したい場合があります。 この状況では、リバースプロキシを設定する必要があります。 これは、ポートのみを公開する必要があるためです 80
と 443
世界の残りの部分に。
Traefik は、監視ダッシュボードを含むDocker対応のリバースプロキシです。 Traefik v1はしばらくの間広く使用されており、この以前のチュートリアルに従ってTraefik v1 をインストールできます)。 ただし、このチュートリアルでは、Traefik v2をインストールして構成します。これには、かなりの違いが含まれています。
Traefik v1とv2の最大の違いは、フロントエンドとバックエンドが削除され、それらを組み合わせた機能がルーター、ミドルウェア、およびサービス。 以前は、バックエンドがリクエストに変更を加え、そのリクエストを処理することになっているものにそのリクエストを取得するという仕事をしていました。 Traefik v2は、サービスに送信する前に要求を変更できるミドルウェアを導入することにより、関心の分離を強化します。 ミドルウェアを使用すると、さまざまなルートで使用される可能性のある単一の変更ステップを簡単に指定して、それらを再利用できるようになります(HTTP基本認証など。これについては後で説明します)。 ルーターは、さまざまなミドルウェアを使用することもできます。
このチュートリアルでは、リクエストを2つの異なるWebアプリケーションコンテナ(WordPressコンテナとAdminerコンテナ)にルーティングするようにTraefik v2を構成し、それぞれがMySQLと通信します。データベース。 Let’s Encrypt を使用して、HTTPS経由ですべてを提供するようにTraefikを構成します。
前提条件
このチュートリアルを完了するには、次のものが必要です。
- sudo非rootユーザーとファイアウォールを備えた1台のUbuntu20.04サーバー。 これは、Ubuntu20.04初期サーバーセットアップガイドに従ってセットアップできます。
- サーバーにDockerがインストールされています。これは、 Ubuntu20.04にDockerをインストールして使用する方法のステップ1および2に従って実行できます。
- DockerComposeはUbuntu20.04にDockerComposeをインストールする方法のステップ1の手順を使用してインストールされます。
- ドメインと3つのAレコード、
db-admin.your_domain
,blog.your_domain
とmonitor.your_domain
. それぞれがサーバーのIPアドレスを指している必要があります。 DigitalOceanのドメインとDNSドキュメントを読むことで、ドメインをDigitalOceanドロップレットにポイントする方法を学ぶことができます。 このチュートリアル全体を通して、ドメインを次のように置き換えますyour_domain
構成ファイルと例で。
ステップ1—Traefikの構成と実行
Traefikプロジェクトには公式Dockerイメージがあるため、これを使用してDockerコンテナーでTraefikを実行します。
ただし、Traefikコンテナを起動して実行する前に、構成ファイルを作成し、暗号化されたパスワードを設定して、監視ダッシュボードにアクセスできるようにする必要があります。
を使用します htpasswd
この暗号化されたパスワードを作成するユーティリティ。 まず、に含まれているユーティリティをインストールします apache2-utils
パッケージ:
- sudo apt-get install apache2-utils
次に、でパスワードを生成します htpasswd
. 代わりの secure_password
Traefik管理者ユーザーに使用するパスワードを使用して:
- htpasswd -nb admin secure_password
プログラムからの出力は次のようになります。
Outputadmin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/
Traefik構成ファイルでこの出力を使用して、Traefikヘルスチェックおよび監視ダッシュボードのHTTP基本認証を設定します。 後で貼り付けることができるように、出力行全体をコピーします。
Traefikサーバーを構成するには、次の2つの新しい構成ファイルを作成します。 traefik.toml
と traefik_dynamic.toml
TOML形式を使用します。 TOML は、INIファイルに似た構成言語ですが、標準化されています。 これらのファイルを使用すると、Traefikサーバーとさまざまな統合を構成できます、または providers
、使用したいこと。 このチュートリアルでは、Traefikで利用可能な3つのプロバイダーを使用します。 api
, docker
、 と acme
. これらの最後、 acme
、Let’sEncryptを使用したTLS証明書をサポートします。
作成して開く traefik.toml
を使用して nano
またはお好みのテキストエディタ:
- nano traefik.toml
まず、Traefikがリッスンするポートを指定します。 entryPoints
設定ファイルのセクション。 ポートで聞きたいので2つ欲しい 80
と 443
. これらを呼びましょう web
(ポート 80
) と websecure
(ポート 443
).
次の構成を追加します。
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"
また、TLSを介して処理されるトラフィックを自動的にリダイレクトしていることに注意してください。
次に、Traefikを構成します api
、APIとダッシュボードインターフェースの両方にアクセスできます。 の見出し [api]
ダッシュボードはデフォルトで有効になっているため、必要なのはこれだけですが、当面は明示的になります。
次のコードを追加します。
...
[api]
dashboard = true
Webリクエストの保護を完了するには、Let’sEncryptを使用して有効なTLS証明書を生成します。 Traefik v2は、Let’s Encryptをすぐにサポートし、タイプの証明書リゾルバーを作成することで構成できます。 acme
.
名前を使用して証明書リゾルバーを構成しましょう lets-encrypt
:
...
[certificatesResolvers.lets-encrypt.acme]
email = "your_email@your_domain"
storage = "acme.json"
[certificatesResolvers.lets-encrypt.acme.tlsChallenge]
このセクションは acme
ACME は、Let’sEncryptと通信して証明書を管理するために使用されるプロトコルの名前であるためです。 Let’s Encryptサービスでは、有効な電子メールアドレスで登録する必要があるため、Traefikにホストの証明書を生成させるには、 email
あなたのメールアドレスへの鍵。 次に、Let’sEncryptから受け取る情報をと呼ばれるJSONファイルに保存することを指定します。 acme.json
.
The acme.tlsChallenge
セクションでは、Let’sEncryptが証明書を検証する方法を指定できます。 ポート経由のチャレンジの一部としてファイルを提供するように構成しています 443
.
最後に、Dockerと連携するようにTraefikを構成する必要があります。
次の構成を追加します。
...
[providers.docker]
watch = true
network = "web"
The docker
プロバイダーにより、TraefikはDockerコンテナーの前でプロキシとして機能できます。 プロバイダーを次のように構成しました watch
上の新しいコンテナの場合 web
すぐに作成するネットワーク。
最終的な構成では、 file
プロバイダー。 Traefik v2では、静的構成と動的構成を混在させて一致させることはできません。 これを回避するには、 traefik.toml
静的構成を定義してから、動的構成を別のファイルに保持します。このファイルを呼び出します。 traefik_dynamic.toml
. ここでは、 file
別のファイルから動的構成で読み取る必要があることをTraefikに通知するプロバイダー。
以下を追加します file
プロバイダー:
- [providers.file]
- filename = "traefik_dynamic.toml"
完成しました traefik.toml
次のようになります。
[entryPoints]
[entryPoints.web]
address = ":80"
[entryPoints.web.http.redirections.entryPoint]
to = "websecure"
scheme = "https"
[entryPoints.websecure]
address = ":443"
[api]
dashboard = true
[certificatesResolvers.lets-encrypt.acme]
email = "your_email@your_domain"
storage = "acme.json"
[certificatesResolvers.lets-encrypt.acme.tlsChallenge]
[providers.docker]
watch = true
network = "web"
[providers.file]
filename = "traefik_dynamic.toml"
ファイルを保存して閉じます。
では、作成しましょう traefik_dynamic.toml
.
独自のファイルに保持する必要のある動的構成値は、ミドルウェアとルーターです。 ダッシュボードをパスワードの背後に配置するには、APIのルーターをカスタマイズし、HTTP基本認証を処理するようにミドルウェアを構成する必要があります。 ミドルウェアを設定することから始めましょう。
ミドルウェアはプロトコルごとに構成され、HTTPを使用しているため、ミドルウェアを http.middlewares
. 次に、後で参照できるようにミドルウェアの名前を示し、次にミドルウェアのタイプを示します。 basicAuth
この場合。 ミドルウェアと呼びましょう simpleAuth
.
と呼ばれる新しいファイルを作成して開きます traefik_dynamic.toml
:
- nano traefik_dynamic.toml
次のコードを追加します。 ここに、からの出力を貼り付けます htpasswd
指図:
[http.middlewares.simpleAuth.basicAuth]
users = [
"admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/"
]
API用にルーターを構成するには、プロトコル名からチェーンオフしますが、使用する代わりに http.middlewares
、使用します http.routers
ルーターの名前が続きます。 この場合、 api
を使用して構成できる独自の名前付きルーターを提供します [http.routers.api]
セクション。 ダッシュボードで使用する予定のドメインを構成するには、 rule
ホストマッチを使用するキー、使用するエントリポイント websecure
、および含めるミドルウェア simpleAuth
.
次の構成を追加します。
...
[http.routers.api]
rule = "Host(`monitor.your_domain`)"
entrypoints = ["websecure"]
middlewares = ["simpleAuth"]
service = "api@internal"
[http.routers.api.tls]
certResolver = "lets-encrypt"
The web
エントリポイントはポートを処理します 80
、 websecure
エントリポイントはポートを使用します 443
TLS/SSLの場合。 ポート上のすべてのトラフィックを自動的にリダイレクトします 80
に websecure
すべての要求に対して安全な接続を強制するためのエントリポイント。
ここの最後の3行は、 service を構成し、tlsを有効にして、構成することに注意してください。 certResolver
に "lets-encrypt"
. サービスは、リクエストが最終的に処理される場所を決定するための最終ステップです。 The api@internal
serviceは、公開するAPIの背後にある組み込みサービスです。 ルーターやミドルウェアと同様に、このファイルでサービスを構成できますが、目的の結果を得るために構成する必要はありません。
完成しました traefik_dynamic.toml
ファイルは次のようになります。
[http.middlewares.simpleAuth.basicAuth]
users = [
"admin:$apr1$ruca84Hq$mbjdMZBAG.KWn7vfN/SNK/"
]
[http.routers.api]
rule = "Host(`monitor.your_domain`)"
entrypoints = ["websecure"]
middlewares = ["simpleAuth"]
service = "api@internal"
[http.routers.api.tls]
certResolver = "lets-encrypt"
ファイルを保存して、エディターを終了します。
これらの構成が整ったら、Traefikを起動します。
ステップ2–Traefikコンテナを実行する
このステップでは、プロキシがコンテナと共有するためのDockerネットワークを作成します。 次に、Traefikダッシュボードにアクセスします。 Dockerネットワークは、DockerComposeを使用して実行されるアプリケーションで使用できるようにするために必要です。
と呼ばれる新しいDockerネットワークを作成します web
:
- docker network create web
Traefikコンテナが起動したら、このネットワークに追加します。 次に、後でTraefikがプロキシするために、このネットワークにコンテナを追加できます。
次に、Let’sEncrypt情報を保持する空のファイルを作成します。 これをコンテナに共有して、Traefikが使用できるようにします。
- touch acme.json
Traefikは、コンテナ内のrootユーザーがこのファイルへの一意の読み取りおよび書き込みアクセス権を持っている場合にのみ、このファイルを使用できます。 これを行うには、上の権限をロックダウンします acme.json
ファイルの所有者のみが読み取りおよび書き込み権限を持つようにします。
- chmod 600 acme.json
ファイルがDockerに渡されると、所有者はコンテナ内のrootユーザーに自動的に変更されます。
最後に、次のコマンドを使用してTraefikコンテナを作成します。
- docker run -d \
- -v /var/run/docker.sock:/var/run/docker.sock \
- -v $PWD/traefik.toml:/traefik.toml \
- -v $PWD/traefik_dynamic.toml:/traefik_dynamic.toml \
- -v $PWD/acme.json:/acme.json \
- -p 80:80 \
- -p 443:443 \
- --network web \
- --name traefik \
- traefik:v2.2
このコマンドは少し長いです。 分解してみましょう。
あなたは -d
コンテナをデーモンとしてバックグラウンドで実行するためのフラグ。 次に、 docker.sock
Traefikプロセスがコンテナーへの変更をリッスンできるように、コンテナーにファイルします。 あなたも共有します traefik.toml
と traefik_dynamic.toml
構成ファイルをコンテナに入れるだけでなく、 acme.json
.
次に、ポートをマップします :80
と :443
DockerホストをTraefikコンテナ内の同じポートに接続して、TraefikがサーバーへのすべてのHTTPおよびHTTPSトラフィックを受信できるようにします。
コンテナのネットワークを次のように設定します web
、そしてあなたはコンテナに名前を付けます traefik
.
最後に、 traefik:v2.2
このチュートリアルが書かれているものとは完全に異なるバージョンを実行していないことを保証できるように、このコンテナのイメージ。
DockerイメージのENTRYPOINTは、イメージからコンテナーが作成されるときに常に実行されるコマンドです。 この場合、コマンドは traefik
コンテナ内のバイナリ。 コンテナを起動するときにそのコマンドに追加の引数を渡すことができますが、ですべての設定を構成しました traefik.toml
ファイル。
コンテナが起動すると、コンテナの状態を確認するためにアクセスできるダッシュボードができました。 このダッシュボードを使用して、Traefikが登録したルーター、サービス、およびミドルウェアを視覚化することもできます。 ブラウザで次の位置に移動すると、監視ダッシュボードにアクセスできます。 https://monitor.your_domain/dashboard/
(末尾 /
必要とされている)。
ユーザー名とパスワードの入力を求められます。これらはadminであり、手順1で構成したパスワードです。
ログインすると、Traefikインターフェースが表示されます。
すでにいくつかのルーターとサービスが登録されていることに気付くでしょうが、それらはTraefikとAPI用に作成したルーター構成に付属しているものです。
これでTraefikプロキシが実行され、Dockerと連携して他のコンテナーを監視するように構成されました。 次のステップでは、Traefikがプロキシするためのいくつかのコンテナを開始します。
ステップ3—コンテナをTraefikに登録する
Traefikコンテナを実行すると、その背後でアプリケーションを実行する準備が整います。 Traefikの背後にある次のコンテナを起動しましょう。
- 公式WordPress画像を使用したブログ。
- 公式管理者イメージを使用するデータベース管理サーバー。
Docker Composeを使用して、これらのアプリケーションの両方を管理します。 docker-compose.yml
ファイル。
を作成して開きます docker-compose.yml
エディター内のファイル:
- nano docker-compose.yml
次の行をファイルに追加して、使用するバージョンとネットワークを指定します。
version: "3"
networks:
web:
external: true
internal:
external: false
DockerComposeバージョンを使用します 3
これは、作成ファイル形式の最新のメジャーバージョンだからです。
Traefikがアプリケーションを認識するためには、それらが同じネットワークの一部である必要があります。ネットワークを手動で作成したため、次のネットワーク名を指定してネットワークをプルします。 web
と設定 external
に true
. 次に、別のネットワークを定義して、公開されたコンテナを、Traefikを介して公開しないデータベースコンテナに接続できるようにします。 このネットワークを呼び出します internal
.
次に、それぞれを定義します services
、 一つずつ。 から始めましょう blog
コンテナ。公式のWordPressイメージに基づいています。 この構成をファイルの最後に追加します。
...
services:
blog:
image: wordpress:4.9.8-apache
environment:
WORDPRESS_DB_PASSWORD:
labels:
- traefik.http.routers.blog.rule=Host(`blog.your_domain`)
- traefik.http.routers.blog.tls=true
- traefik.http.routers.blog.tls.certresolver=lets-encrypt
- traefik.port=80
networks:
- internal
- web
depends_on:
- mysql
The environment
キーを使用すると、コンテナ内に設定される環境変数を指定できます。 の値を設定しないことによって WORDPRESS_DB_PASSWORD
、Docker Composeに、シェルから値を取得し、コンテナーを作成するときにそれを渡すように指示しています。 コンテナを起動する前に、シェルでこの環境変数を定義します。 このようにして、パスワードを構成ファイルにハードコーディングする必要はありません。
The labels
セクションでは、Traefikの構成値を指定します。 Dockerラベルはそれ自体では何もしませんが、Traefikはこれらを読み取るため、コンテナーの処理方法を認識しています。 これらの各ラベルの機能は次のとおりです。
traefik.http.routers.adminer.rule=Host(```
blog.your_domain
```)
コンテナの新しいrouterを作成し、リクエストがこのコンテナに一致するかどうかを判断するために使用されるルーティングルールを指定します。traefik.routers.custom_name.tls=true
このルーターがTLSを使用する必要があることを指定します。traefik.routers.custom_name.tls.certResolver=lets-encrypt
以前に作成した証明書リゾルバーがlets-encrypt
このルートの証明書を取得するために使用する必要があります。traefik.port
Traefikがトラフィックをこのコンテナにルーティングするために使用する公開ポートを指定します。
この構成では、ポートでDockerホストに送信されるすべてのトラフィック 80
また 443
のドメインで blog.your_domain
にルーティングされます blog
容器。
このコンテナを2つの異なるネットワークに割り当てて、Traefikが web
ネットワークとそれはを介してデータベースコンテナと通信することができます internal
通信網。
最後に、 depends_on
keyは、依存関係が実行された後にこのコンテナーを開始する必要があることをDockerComposeに通知します。 WordPressを実行するにはデータベースが必要なので、 mysql
開始する前にコンテナ blog
容器。
次に、MySQLサービスを構成します。
services:
...
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:
networks:
- internal
labels:
- traefik.enable=false
このコンテナには、公式のMySQL5.7イメージを使用しています。 もう一度使用していることに気付くでしょう environment
値のないアイテム。 The MYSQL_ROOT_PASSWORD
と WORDPRESS_DB_PASSWORD
WordPressコンテナがMySQLと通信できるようにするには、変数を同じ値に設定する必要があります。 あなたは公開したくない mysql
コンテナをTraefikまたは外の世界に割り当てるため、このコンテナをに割り当てるだけです。 internal
通信網。 TraefikはDockerソケットにアクセスできるため、プロセスは引き続きルーターを公開します。 mysql
デフォルトではコンテナなので、ラベルを追加します traefik.enable=false
Traefikがこのコンテナを公開しないように指定します。
最後に、Adminerコンテナを定義します。
services:
...
adminer:
image: adminer:4.6.3-standalone
labels:
- traefik.http.routers.adminer.rule=Host(`db-admin.your_domain`)
- traefik.http.routers.adminer.tls=true
- traefik.http.routers.adminer.tls.certresolver=lets-encrypt
- traefik.port=8080
networks:
- internal
- web
depends_on:
- mysql
このコンテナは、公式のAdminerイメージに基づいています。 The network
と depends_on
このコンテナの構成は、使用しているものと完全に一致します。 blog
容器。
この線 traefik.http.routers.adminer.rule=Host(```
db-admin.your_domain
```)
要求されたホストを調べるようにTraefikに指示します。 のパターンと一致する場合 db-admin.your_domain
、Traefikはトラフィックをにルーティングします adminer
ポート上のコンテナ 8080
.
完成しました docker-compose.yml
ファイルは次のようになります。
version: "3"
networks:
web:
external: true
internal:
external: false
services:
blog:
image: wordpress:4.9.8-apache
environment:
WORDPRESS_DB_PASSWORD:
labels:
- traefik.http.routers.blog.rule=Host(`blog.your_domain`)
- traefik.http.routers.blog.tls=true
- traefik.http.routers.blog.tls.certresolver=lets-encrypt
- traefik.port=80
networks:
- internal
- web
depends_on:
- mysql
mysql:
image: mysql:5.7
environment:
MYSQL_ROOT_PASSWORD:
networks:
- internal
labels:
- traefik.enable=false
adminer:
image: adminer:4.6.3-standalone
labels:
labels:
- traefik.http.routers.adminer.rule=Host(`db-admin.your_domain`)
- traefik.http.routers.adminer.tls=true
- traefik.http.routers.adminer.tls.certresolver=lets-encrypt
- traefik.port=8080
networks:
- internal
- web
depends_on:
- mysql
ファイルを保存して、テキストエディタを終了します。
次に、シェルに値を設定します WORDPRESS_DB_PASSWORD
と MYSQL_ROOT_PASSWORD
変数:
- export WORDPRESS_DB_PASSWORD=secure_database_password
- export MYSQL_ROOT_PASSWORD=secure_database_password
代わりの secure_database_password
ご希望のデータベースパスワードを使用してください。 両方に同じパスワードを使用することを忘れないでください WORDPRESS_DB_PASSWORD
と MYSQL_ROOT_PASSWORD
.
これらの変数を設定して、を使用してコンテナを実行します docker-compose
:
- docker-compose up -d
次に、Traefik管理ダッシュボードが表示されているのを確認します。
ルーターセクションを調べると、次のルーターが見つかります。 adminer
と blog
TLSで構成:
案内する blog.your_domain
、置換 your_domain
あなたのドメインで。 TLS接続にリダイレクトされ、WordPressのセットアップを完了することができます。
次に、にアクセスしてAdminerにアクセスします db-admin.your_domain
あなたのブラウザで、再び置き換えます your_domain
あなたのドメインで。 The mysql
コンテナは外界にさらされていませんが、 adminer
コンテナは、 internal
を使用して共有するDockerネットワーク mysql
ホスト名としてのコンテナ名。
管理者ログイン画面で、次のように入力します。 root
ユーザー名には、次のように入力します mysql
Server の場合、設定した値を入力します MYSQL_ROOT_PASSWORD
パスワードの場合。 データベースは空のままにします。 次に、ログインを押します。
ログインすると、Adminerユーザーインターフェイスが表示されます。
現在、両方のサイトが機能しており、次の場所でダッシュボードを使用できます。 monitor.your_domain
アプリケーションを監視します。
結論
このチュートリアルでは、Dockerコンテナー内の他のアプリケーションにリクエストをプロキシするようにTraefikv2を構成しました。
アプリケーションコンテナレベルでのTraefikの宣言型構成により、より多くのサービスを簡単に構成でき、再起動する必要はありません。 traefik
Traefikは監視しているDockerソケットファイルを介して変更にすぐに気付くため、プロキシトラフィックに新しいアプリケーションを追加するときのコンテナ。
Traefik v2でできることの詳細については、公式のTraefikドキュメントにアクセスしてください。