CentOS 7でDockerコンテナのリバースプロキシとしてTraefikを使用する方法

著者は、Write for DOnationsプログラムの一部として寄付を受け取るためにGirls Who Codeを選択しました。

前書き

Dockerは、本番環境でWebアプリケーションを実行するための効率的な方法ですが、同じDockerホストで複数のアプリケーションを実行したい場合があります。 この状況では、ポート80443のみを他の世界に公開する必要があるため、リバースプロキシを設定する必要があります。

Traefikは、独自の監視ダッシュボードを含むDocker対応のリバースプロキシです。 このチュートリアルでは、Traefikを使用して、リクエストを2つの異なるWebアプリケーションコンテナ(WordpressコンテナとAdminerコンテナ)にルーティングし、それぞれがMySQLデータベースと通信します。 Let’s Encryptを使用してHTTPS経由ですべてを提供するようにTraefikを構成します。

前提条件

このチュートリアルを進めるには、次のものが必要です。

  • sudo非rootユーザーとファイアウォールを含むInitial Server Setup with CentOS 7に従うことによってセットアップされた1つのCentOS7サーバー。

  • サーバーにDockerがインストールされています。これは、How To Install and Use Docker on CentOS 7に従って実行できます。

  • How To Install Docker Compose on CentOS 7からの指示とともにインストールされたDockerCompose。

  • ドメインと3つのAレコード、db-adminblog、およびmonitor。それぞれがサーバーのIPアドレスを指します。 DigitalOceanのDomains and DNS documentationを読むことで、ドメインをDigitalOceanドロップレットにポイントする方法を学ぶことができます。 このチュートリアル全体を通して、構成ファイルと例のyour_domainをドメインに置き換えてください。

[[step-1 -—- configuring-and-running-traefik]] ==ステップ1—Traefikの構成と実行

Traefikプロジェクトにはofficial Docker imageがあるため、これを使用してDockerコンテナーでTraefikを実行します。

ただし、Traefikコンテナを起動して実行する前に、監視ダッシュボードにアクセスできるように、構成ファイルを作成し、暗号化されたパスワードを設定する必要があります。

htpasswdユーティリティを使用して、この暗号化されたパスワードを作成します。 まず、httpd-toolsパッケージに含まれているユーティリティをインストールします。

sudo yum install -y httpd-tools

次に、htpasswdを使用してパスワードを生成します。 secure_passwordを、Traefik管理者ユーザーに使用するパスワードに置き換えます。

htpasswd -nb admin secure_password

プログラムからの出力は次のようになります。

Outputadmin:$apr1$kEG/8JKj$yEXj8vKO7HDvkUMI/SbOO.

Traefik構成ファイルでこの出力を使用して、Traefikヘルスチェックおよび監視ダッシュボードのHTTP基本認証を設定します。 後で貼り付けることができるように、出力行全体をコピーします。

Traefikサーバーを構成するために、TOML形式を使用してtraefik.tomlという新しい構成ファイルを作成します。 TOMLは、INIファイルに似た構成言語ですが、標準化されています。 このファイルを使用すると、Traefikサーバーと、使用するさまざまな統合(providers)を構成できます。 このチュートリアルでは、Traefikで利用可能な3つのプロバイダー(apidocker、およびacme)を使用します。これらは、Let’sEncryptを使用してTLSをサポートするために使用されます。

Viまたはお気に入りのテキストエディターで新しいファイルを開きます。

vi traefik.toml

iを押して挿入モードに入り、すべてのバックエンドがデフォルトでアクセスできる2つの名前付きエントリポイントhttphttpsを追加します。

traefik.toml

defaultEntryPoints = ["http", "https"]

このファイルの後半で、httpおよびhttpsエントリポイントを構成します。

次に、ダッシュボードインターフェイスへのアクセスを提供するapiプロバイダーを構成します。 ここに、htpasswdコマンドからの出力を貼り付けます。

traefik.toml

...
[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]

[api]
entrypoint="dashboard"

ダッシュボードは、Traefikコンテナ内で実行される別個のWebアプリケーションです。 ダッシュボードをポート8080で実行するように設定しました。

entrypoints.dashboardセクションは、apiプロバイダーとの接続方法を構成し、entrypoints.dashboard.auth.basicセクションは、ダッシュボードのHTTP基本認証を構成します。 実行したばかりのhtpasswdコマンドからの出力をusersエントリの値に使用します。 カンマで区切って追加のログインを指定できます。

最初のentryPointを定義しましたが、apiプロバイダーに向けられていない標準のHTTPおよびHTTPS通信用に他のentryPointを定義する必要があります。 entryPointsセクションは、Traefikとプロキシされたコンテナがリッスンできるアドレスを構成します。 entryPoints見出しの下のファイルに次の行を追加します。

traefik.toml

...
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
        entryPoint = "https"
  [entryPoints.https]
    address = ":443"
      [entryPoints.https.tls]
...

httpエントリポイントはポート80を処理し、httpsエントリポイントはTLS / SSLにポート443を使用します。 ポート80のすべてのトラフィックをhttpsのエントリポイントに自動的にリダイレクトして、すべての要求に対して安全な接続を強制します。

次に、このセクションを追加して、Traefikの証明書の暗号化サポートを設定します。

traefik.toml

...
[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

ACMEは、Let’s Encryptと通信して証明書を管理するために使用されるプロトコルの名前であるため、このセクションはacmeと呼ばれます。 Let’s Encryptサービスでは、有効なメールアドレスで登録する必要があるため、Traefikにホストの証明書を生成させるには、emailキーをメールアドレスに設定します。 次に、Let’s Encryptから受け取る情報をacme.jsonというJSONファイルに保存するように指定します。 entryPointキーは、ポート443を処理するエントリポイントを指す必要があります。この場合は、httpsエントリポイントです。

キーonHostRuleは、Traefikが証明書を生成する方法を指示します。 指定されたホスト名を持つコンテナが作成されたらすぐに証明書をフェッチする必要があります。これは、onHostRule設定が行うことです。

acme.httpChallengeセクションでは、Let’sEncryptが証明書を生成する必要があることを確認する方法を指定できます。 httpエントリポイントを介してチャレンジの一部としてファイルを提供するように構成しています。

最後に、次の行をファイルに追加して、dockerプロバイダーを構成します。

traefik.toml

...
[docker]
domain = "your_domain"
watch = true
network = "web"

dockerプロバイダーにより、TraefikはDockerコンテナーの前でプロキシとして機能できます。 プロバイダーをwebネットワーク上の新しいコンテナー用にwatchに構成し(これはまもなく作成します)、それらをyour_domainのサブドメインとして公開します。

この時点で、traefik.tomlには次の内容が含まれているはずです。

traefik.toml

defaultEntryPoints = ["http", "https"]

[entryPoints]
  [entryPoints.dashboard]
    address = ":8080"
    [entryPoints.dashboard.auth]
      [entryPoints.dashboard.auth.basic]
        users = ["admin:your_encrypted_password"]
  [entryPoints.http]
    address = ":80"
      [entryPoints.http.redirect]
        entryPoint = "https"
  [entryPoints.https]
    address = ":443"
      [entryPoints.https.tls]

[api]
entrypoint="dashboard"

[acme]
email = "your_email@your_domain"
storage = "acme.json"
entryPoint = "https"
onHostRule = true
  [acme.httpChallenge]
  entryPoint = "http"

[docker]
domain = "your_domain"
watch = true
network = "web"

内容を追加したら、ESCを押して挿入モードを終了します。 :x、次にENTERと入力して、ファイルを保存して終了します。 このすべての構成が整ったら、Traefikを起動できます。

[[step-2 -–- running-the-traefik-container]] ==ステップ2–Traefikコンテナの実行

次に、プロキシがコンテナと共有するためのDockerネットワークを作成します。 Dockerネットワークは、Docker Composeを使用して実行されるアプリケーションで使用できるようにするために必要です。 このネットワークをwebと呼びましょう。

docker network create web

Traefikコンテナが起動したら、このネットワークに追加します。 その後、Traefikがプロキシするために、このネットワークに後でコンテナを追加できます。

次に、Let’s Encrypt情報を保持する空のファイルを作成します。 これをコンテナに共有して、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/acme.json:/acme.json \
  -p 80:80 \
  -p 443:443 \
  -l traefik.frontend.rule=Host:monitor.your_domain \
  -l traefik.port=8080 \
  --network web \
  --name traefik \
  traefik:1.7.6-alpine

コマンドは少し長いので、分解しましょう。

-dフラグを使用して、コンテナーをデーモンとしてバックグラウンドで実行します。 次に、docker.sockファイルをコンテナーに共有して、Traefikプロセスがコンテナーへの変更をリッスンできるようにします。 また、作成したtraefik.toml構成ファイルとacme.jsonファイルをコンテナーに共有します。

次に、Dockerホストのポート80443をTraefikコンテナー内の同じポートにマップして、TraefikがサーバーへのすべてのHTTPおよびHTTPSトラフィックを受信するようにします。

次に、トラフィックをホスト名monitor.your_domainからTraefikコンテナ内のポート8080に転送するように、Traefikに指示する2つのDockerラベルを設定し、監視ダッシュボードを公開します。

コンテナのネットワークをwebに設定し、コンテナにtraefikという名前を付けます。

最後に、このコンテナは小さいため、traefik:1.7.6-alpineイメージを使用します。

DockerイメージのENTRYPOINTは、イメージからコンテナーが作成されるときに常に実行されるコマンドです。 この場合、コマンドはコンテナ内のtraefikバイナリです。 コンテナを起動するときにそのコマンドに追加の引数を渡すことができますが、traefik.tomlファイルですべての設定を構成しました。

コンテナが起動すると、ダッシュボードにアクセスして、コンテナの状態を確認できます。 このダッシュボードを使用して、Traefikが登録したフロントエンドとバックエンドを視覚化することもできます。 ブラウザでhttps://monitor.your_domainを指定して、監視ダッシュボードにアクセスします。 ユーザー名とパスワードの入力を求められます。これらはadminであり、手順1で構成したパスワードです。

ログインすると、次のようなインターフェースが表示されます。

Empty Traefik dashboard

まだあまり見ることはありませんが、このウィンドウを開いたままにしておくと、Traefikが操作するコンテナを追加すると内容が変更されます。

これで、Trafikプロキシが実行され、Dockerと連携するように構成され、他のDockerコンテナーを監視する準備が整いました。 Traefikのプロキシとして機能するコンテナをいくつか始めましょう。

[[step-3 -—- registering-containers-with-traefik]] ==ステップ3—コンテナをTraefikに登録する

Traefikコンテナを実行すると、その背後でアプリケーションを実行する準備が整います。 Traefikの背後にある次のコンテナを起動しましょう。

  1. official Wordpress imageを使用したブログ。

  2. official Adminer imageを使用するデータベース管理サーバー。

docker-compose.ymlファイルを使用してDockerComposeでこれらのアプリケーションの両方を管理します。 エディターでdocker-compose.ymlファイルを開きます。

vi docker-compose.yml

ファイルに次の行を追加して、使用するバージョンとネットワークを指定します。

docker-compose.yml

version: "3"

networks:
  web:
    external: true
  internal:
    external: false

Docker Composeバージョン3は、Composeファイル形式の最新のメジャーバージョンであるため、使用しています。

Traefikがアプリケーションを認識するためには、それらが同じネットワークの一部である必要があります。ネットワークを手動で作成したため、webのネットワーク名を指定し、externaltrueに設定してネットワークをプルします。 )s。 次に、公開されたコンテナをTraefikを介して公開しないデータベースコンテナに接続できるように、別のネットワークを定義します。 このネットワークをinternalと呼びます。

次に、各servicesを一度に1つずつ定義します。 公式のWordPressイメージに基づいたblogコンテナから始めましょう。 この構成をファイルに追加します。

docker-compose.yml

version: "3"
...

services:
  blog:
    image: wordpress:4.9.8-apache
    environment:
      WORDPRESS_DB_PASSWORD:
    labels:
      - traefik.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - traefik.port=80
    networks:
      - internal
      - web
    depends_on:
      - mysql

environmentキーを使用すると、コンテナ内に設定される環境変数を指定できます。 WORDPRESS_DB_PASSWORDに値を設定しないことで、Docker Composeにシェルから値を取得し、コンテナーを作成するときにそれを渡すように指示しています。 コンテナを起動する前に、シェルでこの環境変数を定義します。 このように、パスワードを構成ファイルにハードコーディングしません。

labelsセクションでは、Traefikの構成値を指定します。 Dockerラベルはそれ自体では何もしませんが、Traefikはこれらを読み取って、コンテナの処理方法を認識します。 これらの各ラベルの機能は次のとおりです。

  • traefik.backendは、Traefikのバックエンドサービスの名前を指定します(実際のblogコンテナーを指します)。

  • traefik.frontend.rule=Host:blog.your_domainは、要求されたホストを調べるようにTraefikに指示し、blog.your_domainのパターンに一致する場合は、トラフィックをblogコンテナーにルーティングする必要があります。

  • traefik.docker.network=webは、このコンテナの内部IPを見つけるためにTraefikを探すネットワークを指定します。 TraefikコンテナはすべてのDocker情報にアクセスできるため、これを指定しなかった場合、internalネットワークのIPが必要になる可能性があります。

  • traefik.portは、Traefikがトラフィックをこのコンテナにルーティングするために使用する公開ポートを指定します。

この構成では、Dockerホストのポート80に送信されるすべてのトラフィックは、blogコンテナーにルーティングされます。

このコンテナを2つの異なるネットワークに割り当てて、Traefikがwebネットワーク経由でコンテナを見つけ、internalネットワーク経由でデータベースコンテナと通信できるようにします。

最後に、depends_onキーは、このコンテナーが依存関係が実行されているafterを開始する必要があることをDockerComposeに通知します。 WordPressを実行するにはデータベースが必要なため、blogコンテナーを開始する前に、mysqlコンテナーを実行する必要があります。

次に、この構成をファイルに追加して、MySQLサービスを構成します。

docker-compose.yml

services:
...
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD:
    networks:
      - internal
    labels:
      - traefik.enable=false

このコンテナには、公式のMySQL 5.7イメージを使用しています。 値のないenvironmentアイテムを再び使用していることに気付くでしょう。 WordPressコンテナがMySQLと通信できるようにするには、MYSQL_ROOT_PASSWORD変数とWORDPRESS_DB_PASSWORD変数を同じ値に設定する必要があります。 mysqlコンテナをTraefikまたは外部に公開したくないので、このコンテナをinternalネットワークに割り当てるだけです。 TraefikはDockerソケットにアクセスできるため、プロセスはデフォルトでmysqlコンテナーのフロントエンドを公開します。そのため、ラベルtraefik.enable=falseを追加して、Traefikがこのコンテナーを公開しないように指定します。

最後に、この構成を追加してAdminerコンテナーを定義します。

docker-compose.yml

services:
...
  adminer:
    image: adminer:4.6.3-standalone
    labels:
      - traefik.backend=adminer
      - traefik.frontend.rule=Host:db-admin.your_domain
      - traefik.docker.network=web
      - traefik.port=8080
    networks:
      - internal
      - web
    depends_on:
      - mysql

このコンテナは、公式の管理者イメージに基づいています。 このコンテナのnetworkおよびdepends_on構成は、blogコンテナに使用しているものと完全に一致します。

ただし、Dockerホストのポート80へのすべてのトラフィックを直接blogコンテナーに転送しているため、トラフィックがblogに到達するようにするには、このコンテナーを別の方法で構成する必要があります。 t2)sコンテナ。 行traefik.frontend.rule=Host:db-admin.your_domainは、要求されたホストを調べるようにTraefikに指示します。 db-admin.your_domainのパターンに一致する場合、Traefikはトラフィックをadminerコンテナにルーティングします。

この時点で、docker-compose.ymlには次の内容が含まれているはずです。

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.backend=blog
      - traefik.frontend.rule=Host:blog.your_domain
      - traefik.docker.network=web
      - 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:
      - traefik.backend=adminer
      - traefik.frontend.rule=Host:db-admin.your_domain
      - traefik.docker.network=web
      - 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_PASSWORDMYSQL_ROOT_PASSWORDの両方に同じパスワードを使用することを忘れないでください。

これらの変数を設定して、docker-composeを使用してコンテナーを実行します。

docker-compose up -d

Traefik管理ダッシュボードをもう一度見てみましょう。 公開された2つのサーバーにbackendfrontendがあることがわかります。

Populated Traefik dashboard

blog.your_domainに移動し、your_domainをドメインに置き換えます。 TLS接続にリダイレクトされ、Wordpressのセットアップを完了することができます。

WordPress setup screen

次に、ブラウザでdb-admin.your_domainにアクセスし、ドメインをyour_domainに置き換えて、Adminerにアクセスします。 mysqlコンテナは外部に公開されていませんが、adminerコンテナは、mysqlコンテナ名を使用して共有するinternalDockerネットワークを介してアクセスできます。ホスト名。

管理者ログイン画面で、ユーザー名rootを使用し、servermysqlを使用し、パスワードにMYSQL_ROOT_PASSWORDに設定した値を使用します。 ログインすると、管理者のユーザーインターフェースが表示されます。

Adminer connected to the MySQL database

現在、両方のサイトが機能しており、monitor.your_domainのダッシュボードを使用して、アプリケーションを監視できます。

結論

このチュートリアルでは、Dockerコンテナ内の他のアプリケーションへのリクエストをプロキシするようにTraefikを設定しました。

アプリケーションコンテナレベルでのTraefikの宣言型構成により、より多くのサービスを簡単に構成できます。TraefikはDockerソケットファイルを介して変更にすぐに気付くため、プロキシトラフィックに新しいアプリケーションを追加するときにtraefikコンテナを再起動する必要はありません。モニタリング。

Traefikで何ができるかについて詳しくは、公式のTraefik documentationにアクセスしてください。 Dockerコンテナーをさらに詳しく調べたい場合は、How To Set Up a Private Docker Registry on Ubuntu 18.04またはHow To Secure a Containerized Node.js Application with Nginx, Let’s Encrypt, and Docker Composeを確認してください。 これらのチュートリアルはUbuntu 18.04用に作成されていますが、CentOS 7ではDocker固有のコマンドの多くを使用できます。

Related