Traefik 2.0 での Discourse の運用について

スクリーンショットを共有してもらえますか?

添付されたのは、Traefik ダッシュボードのスクリーンショット 2 枚です。これらは、サービスに Discourse が 2 回表示されていることを示していますが、ルーターには何も表示されていません。それが何を意味するかは必ずしもわかりませんが、気づいたので報告します。

編集:私は Discourse の新用户なので、1 つの投稿に画像を 2 つ貼り付ける権限がありません。そのため、別の返信で画像を投稿します。

今夜、比較のために Docker を起動する必要があります。その時点でお知らせするか、あるいはここにいる他の誰かがダッシュボードを共有して比較してくれるかもしれません。

それは不要です。代わりに API に切り替え、Traefik v2.1 を使用してください。つまり:
- "traefik.http.routers.traefik_dashboard-router.service=api@internal"
詳細は Endless 502 / forwarding when calling dashboard via subdomain #6123 - #5 by ldez - Traefik v2 - Traefik Labs Community Forum をご覧ください。

コメントを削除していただけますか?

そうすれば私たちも読みやすくなります。
ご心配なく、私も以前同じことを言われたことがあります : )。
私はコメントを別行に記述しています。そうすれば cat traefikV2.yaml | grep -v "#" を使ってきれいに印刷できます。

こちらが私のダッシュボードです

  1. ダッシュボード
  2. HTTP ルーター
  3. HTTP サービス
  4. HTTP ミドルウェア

はい、これにたどり着くまで数日かかりました。Traefik の設定を docker-compose 全体に記述するのではなく、yaml ファイルを使用するように再構成しました。しかし、すべてを再度接続したところ、同じ、あるいは似たような動作が見られます。ドメインで 404 エラーが発生し、Traefik のダッシュボードでは Services と Routers に discourse のエントリが表示されますが、Routers には何も表示されません。

Traefik docker-compose
version: '3'

services:
  traefik:
    image: traefik:v2.0
    container_name: traefik
    restart: unless-stopped
    security_opt:
      - no-new-privileges:true
    networks:
      - proxy
    ports:
      - 80:80
      - 443:443
    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.traefik.entrypoints=http"
      - "traefik.http.routers.traefik.rule=Host(`monitor.example.com`)"
      - "traefik.http.middlewares.traefik-auth.basicauth.users=user:redacted"
      - "traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https"
      - "traefik.http.routers.traefik.middlewares=traefik-https-redirect"
      - "traefik.http.routers.traefik-secure.entrypoints=https"
      - "traefik.http.routers.traefik-secure.rule=Host(`monitor.example.com`)"
      - "traefik.http.routers.traefik-secure.middlewares=traefik-auth"
      - "traefik.http.routers.traefik-secure.tls=true"
      - "traefik.http.routers.traefik-secure.tls.certresolver=http"
      - "traefik.http.routers.traefik-secure.service=api@internal"

networks:
  proxy:
    external: true
Traefik data/traefik.yml
api:
  dashboard: true

entryPoints:
  http:
    address: ":80"
  https:
    address: ":443"

providers:
  docker:
    endpoint: "unix:///var/run/docker.sock"
    exposedByDefault: false

certificatesResolvers:
  http:
    acme:
      email: nick@innomadic.com
      storage: acme.json
      httpChallenge:
        entryPoint: http
containers/app.yml
templates:
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/web.template.yml"
  - "templates/web.ratelimited.template.yml"

expose:

params:
  db_default_text_search_config: "pg_catalog.english"

  db_shared_buffers: "128MB"



env:
  LANG: en_US.UTF-8

  UNICORN_WORKERS: 2

  DISCOURSE_HOSTNAME: forum.example.com


  DISCOURSE_DEVELOPER_EMAILS: 'info@example.com'

  DISCOURSE_SMTP_ADDRESS: redacted.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: redacted
  DISCOURSE_SMTP_PASSWORD: "redacted"

  LETSENCRYPT_ACCOUNT_EMAIL: info@example.com


volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared
  - volume:
      host: /var/discourse/shared/standalone/log/var-log
      guest: /var/log

hooks:
  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - git clone https://github.com/discourse/docker_manager.git

run:
  - exec: echo "Beginning of custom commands"
  - exec: echo "End of custom commands"

labels:
  app_name:                                                                     discourse

  traefik.enable:                                                               true
  traefik.docker.network:                                                       proxy
  traefik.http.routers.discourse.rule:                                          Host(`forum.example.com`)
  traefik.http.routers.discourse.entrypoints:                                   http
  traefik.http.routers.discourse.middlewares:                                   discourse_redirect2https
  traefik.http.services.discourse.loadbalancer.server.port:                     80

  traefik.http.routers.discourse_secure.rule:                                   Host(`forum.example.com`)
  traefik.http.routers.discourse_secure.entrypoints:                            https

  traefik.http.services.discourse_secure.loadbalancer.server.port:              80
  traefik.http.routers.discourse_secure.tls.certresolver:                       tlsChallenge_letsencrypt

  traefik.http.middlewares.discourse_redirect2https.redirectscheme.scheme:      https

docker_args:
  - "--network=proxy"
  - "--expose=80"

docker network connect proxy コマンドを実行して、これを Traefik ネットワークに接続したと思います。

何か見落としている点があればご指摘いただければ幸いです。また、セキュリティ設定が適切に行われているかについてもご意見をいただければ大変嬉しく思います。

何が不足しているのか分かりません。Ansible で Traefik を使ってサイトを構築する際に行っている手順は以下の通りです:

        --docker-args "-l traefik.frontend.rule=Host:{{discourse_hostname}} \
        -l traefik.frontend.entryPoints=https \
        -l traefik.backend={{discourse_shortname}} \
        -l traefik.port=80"

その後、以下を実行します。

       ./launcher start {{ discourse_yml }} {{ docker_args }}

docker_args に Traefik のルールを追加し、yml には記述しないことで、ブートストラップ中のコンテナに Traefik が反応しないという利点があります。

あれは多分 Traefik v1 ですね?

あ、ごめんなさい。ええと、それは Traefik 1 だと思いますので、具体的なことについてはお役に立てないかもしれません。

app.yml でそれらのラベルに値を設定していないようですが、ルールを設定し、おそらくミドルウェアも設定する必要があると思います。

ブートストラップ中にダウンタイムを避けたい場合は、私の例のように ./launcher start で設定する必要があります。

もしかして「ミドルウェア」は以前「バックエンド」と呼ばれていたものですか?Discourse コンテナが目的のサーバーであることを確立し、適切なバックエンド/サーバーにフロントエンドや URL を接続するための何らかの処理が必要になります。

設定は反映されていますが、表示するには少し右にスクロールする必要があります。単なるフォーマットの問題です。

ありがとうございます

LOL。ごめんなさい。

ええと、私が何について話しているのかはわかりませんが、Discourse@Dockerをロードバランサーとして設定するのは理にかなっていないように思えます。

やあ、わかったと思います。

以下の行を削除しました:
# traefik.http.services.discourse_secure.loadbalancer.server.port: 80

ただし、こちらは残しました:

traefik.http.services.discourse.loadbalancer.server.port: 80

labels:
  app_name:                                                                     discourse

  #----Traefik lables------------------------
  traefik.enable:                                                               true
  traefik.docker.network:                                                       proxy
   #---HTTP ROUTER SECTION-------------------
  traefik.http.routers.discourse.rule:                                          Host(`forum.example.com`)
    #--HTTP SECTION--------------------------
  traefik.http.routers.discourse.entrypoints:                                   http
  traefik.http.routers.discourse.middlewares:                                   discourse_redirect2https
  traefik.http.services.discourse.loadbalancer.server.port:                     80

   #---HTTPS ROUTER SECTION
  traefik.http.routers.discourse_secure.rule:                                   Host(`forum.example.com`)
    #--HTTPS SECTION
  traefik.http.routers.discourse_secure.entrypoints:                            https

 # traefik.http.services.discourse_secure.loadbalancer.server.port:              80
    #--TLS SECTION
  traefik.http.routers.discourse_secure.tls.certresolver:                       tlsChallenge_letsencrypt

   #---MIDDLEWARE SECTION redirect http to https
  traefik.http.middlewares.discourse_redirect2https.redirectscheme.scheme:      https

どうしてこうなったのか、なぜこうなっているのかはわかりませんが、動作しています。つまり、スレッドに投稿した上記のすべての設定を使用しつつ、この 1 つの変更を加えることで、現在動作しています。

みなさん、ありがとう!

その対応で正しいです。
私は設定に以下を追加しています:

#—SERVICE SECTION: Traefik にリクエストを送る先を指定
traefik.http.services.discourse.loadbalancer.server.port: 80

これはお分かりいただけますか?
ここでやっていることは、「どのサービスに」「どのポートで」リクエストを送るかを指定することです。
expose を使って解決することも可能ですが、セキュリティの観点からはコンテナの公開を最小限に抑えるべきです。さらに、複数のポートを公開した場合、Traefik は最初のポートを選択するため、loadbalancer を使用する方がよりクリーンです。


Traefik の data/traefik.yml

私はこれを指定していません。このパスはデフォルトのパスだからです。

ここでは絶対パスを使わず、デフォルトのパスを使用しています。パスを常に意識しなければならないため、私はこれを好ましく思いません。私は storage: /etc/ssl/certs/letsencrypt/acme.json と指定しています。

ネットワークも定義しています。デフォルト設定は好ましくありません。

providers:
  docker:
    exposedByDefault: false
    network: bridge_proxy_traefikv2

containers/app.yml

これは不要です。loadbalancer によって自動的に処理されます。

Traefik docker-compose

このネットワークに名前を付けることをお勧めします。私の場合は以下の通りです。

networks:
  traefik:
    external:
      name: bridge_proxy_traefikv2

あなたの提案を検討してきました。ご返信ありがとうございます。

一点指摘させてください。エンドポイントについてはデフォルトを信頼するよう書かれていますが、ストレージの場所についてはデフォルトを信頼しないとおっしゃっていますね。:slight_smile:

あなたが言及した acme.json の変更を試みました:

しかし、その変更をすると私の Traefik コンテナがファイルを見つけられず、ログにエラーが表示されました。そのため、現時点では acme.json のままにしています。

ただ、これについては質問したいことがあります:

これは単にネットワークの名前を変更しているだけ、あるいはローカル名を付けているだけではないでしょうか?私は他の設定やここではローカルに「proxy」と呼んで参照していました。これは私が定義した名前をそのまま使用しているだけで、名前を変更しているわけではありません。少なくとも私の理解ではそのように思われます。

最後に重要な懸念点が一つあります。「Success!」という投稿をした後に気づいたのですが、HTTPS は機能しているものの、「混合コンテンツ」の警告が表示されています。つまり、すべてが暗号化されていないということです。

Discourse のインストールでは混合コンテンツのエラーが発生していますが、同じサーバー上の WordPress のインストールでは発生していません。これは私の Discourse の設定に特有の問題に違いありません。

開発者コンソールを確認すると、以下のようなメッセージが表示されています:

Loading mixed (insecure) display content “http://talk.redacted.com/uploads/default/optimized/1X/_129430568242d1b7f853bb13ebea28b3f6af4e7_2_180x180.png” on a secure page FaviconLoader.jsm:174:19

もしかすると、リダイレクトが正しく機能していないのでしょうか?

関連ファイルを下に添付しましたので、ご確認をお願いします。

Traefik.yml

api:
dashboard: true

entryPoints:
http:
address: “:80”
https:
address: “:443”

providers:
docker:
exposedByDefault: false
network: proxy

certificatesResolvers:
http:
acme:
email: info@private.com
storage: acme.json
httpChallenge:
entryPoint: http

Traefik docker-compose

version: ‘3’

services:
traefik:
image: traefik:v2.0
container_name: traefik
restart: unless-stopped
security_opt:
- no-new-privileges:true
networks:
- proxy
ports:
- 80:80
- 443:443
volumes:
- /etc/localtime:/etc/localtime:ro
- /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/traefik.yml:/traefik.yml:ro
- ./data/acme.json:/acme.json
labels:
- “traefik.enable=true”
- “traefik.http.routers.traefik.entrypoints=http”
- “traefik.http.routers.traefik.rule=Host(monitor.private.com)”
- “traefik.http.middlewares.traefik-auth.basicauth.users=private:private”
- “traefik.http.middlewares.traefik-https-redirect.redirectscheme.scheme=https”
- “traefik.http.routers.traefik.middlewares=traefik-https-redirect”
- “traefik.http.routers.traefik-secure.entrypoints=https”
- “traefik.http.routers.traefik-secure.rule=Host(monitor.private.com)”
- “traefik.http.routers.traefik-secure.middlewares=traefik-auth”
- “traefik.http.routers.traefik-secure.tls=true”
- “traefik.http.routers.traefik-secure.tls.certresolver=http”
- “traefik.http.routers.traefik-secure.service=api@internal”

networks:
proxy:
external: true

app.yml

templates:

  • “templates/postgres.template.yml”
  • “templates/redis.template.yml”
  • “templates/web.template.yml”
  • “templates/web.ratelimited.template.yml”

expose:

params:
db_default_text_search_config: “pg_catalog.english”

db_shared_buffers: “128MB”

env:
LANG: en_US.UTF-8

UNICORN_WORKERS: 2

DISCOURSE_HOSTNAME: talk.private.com

DISCOURSE_DEVELOPER_EMAILS: ‘info@private.com’

LETSENCRYPT_ACCOUNT_EMAIL: info@private.com

volumes:

  • volume:
    host: /var/discourse/shared/standalone
    guest: /shared
  • volume:
    host: /var/discourse/shared/standalone/log/var-log
    guest: /var/log

hooks:
after_code:
- exec:
cd: $home/plugins
cmd:
- git clone GitHub - discourse/docker_manager: Plugin for use with discourse docker image · GitHub

run:

  • exec: echo “Beginning of custom commands”
  • exec: echo “End of custom commands”

labels:
app_name: discourse

traefik.enable: true
traefik.docker.network: proxy
traefik.http.routers.discourse.rule: Host(talk.private.com)
traefik.http.routers.discourse.entrypoints: http
traefik.http.routers.discourse.middlewares: discourse_redirect2https
traefik.http.services.discourse.loadbalancer.server.port: 80

traefik.http.routers.discourse_secure.rule: Host(talk.private.com)
traefik.http.routers.discourse_secure.entrypoints: https
traefik.http.routers.discourse_secure.tls: true
traefik.http.routers.discourse_secure.service: discourse
traefik.http.routers.discourse_secure.tls.certresolver: http

traefik.http.middlewares.discourse_redirect2https.redirectscheme.scheme: https

docker_args:

  • “–network=proxy”

さて、なぜ混合コンテンツのエラーが発生しているのかについて、何かご意見はありますか?

さて、一瞬、Discourse が自我を持っちゃったのかと思いました。管理画面でこんな通知が来たんですから:

でも、この変更を加えても「混合コンテンツ」のエラーが消えません。ログアウトしてキャッシュを削除し、再度ログインしても同じです。

ログインリクエストは依然として暗号化されているようなので、それは良いことかもしれませんが、この混合コンテンツのエラーを何とかする必要があります。設定は前の投稿に記載されています。

もう一つの更新:混合コンテンツの警告が今では消えています。なぜかはっきりしません。force_https 設定に関連しているのだと思いますが、上記で述べたように、キャッシュをクリアし、ログアウトして再度ログインしたにもかかわらず、設定を変更してから約 30 分間はクリーンなページ読み込みが得られませんでした。

良い知らせは、Traefic リバースプロキシの背後で正常に動作する Discourse インストールができたようです。


問題は http 接続でソースを取得している画像にあります。私も同様の問題に直面しました。以下のスレッドを参照してください:


ボリュームのマウントは正しく行いましたか?パスに関しては Traefik は非常に混乱しやすいです。
例えば、私は次のようにしています:

volumes:       
  - /etc/ssl/certs/traefik/letsencrypt:/etc/ssl/certs/letsencrypt
  - /opt/traefik/traefik-config.yaml:/etc/traefik/traefik.yaml
  - /etc/passwd.traefik.dashboard:/etc/passwd.BasicAuth.dashboard
  - /etc/passwd.traefik.whoami:/etc/passwd.BasicAuth.whoami

正確な記憶はありませんが、それには理由があったはずです。おそらく、CLI でネットワークをリスト表示した際に明確に識別するためだったのでしょう。

いいえ、私はそのようにマウントしていません。以下は、traefik の docker-compose からのボリュームセクションです:

    volumes:
      - /etc/localtime:/etc/localtime:ro
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - ./data/traefik.yml:/traefik.yml:ro
      - ./data/acme.json:/acme.json

私の設定には let’s encrypt の記述すらありませんが、 yours にはあります。おそらく、docker-compose ディレクトリ内で深くネストされたフォルダを作成し、そこに acme.json を置いたのでしょう。

他には、docker.sock と localtime があることに気づきました。localtime の役割は不明で、docker.sock の記述がセキュリティ上の問題になる可能性もあるかもしれません。それについては調べる必要があります。

Let’s Encrypt の証明書作成は Traefik が担当しています。ボリュームをマウントすることで、Docker 内ではなくホスト上に保存できるようになります。
マウント設定を完了させるのは本当に手間でした。docker exec -it で以下のような確認を繰り返しました:

  • ls
  • dir
  • vi