Multisite configuration with Docker

:warning: While multisite is supported in the Discourse application, this is an advanced sysadmin setup. If you don’t know what you’re doing, do not set up multisite. The Discourse team is unable to provide multisite configuration support.

If you wish to host multiple domains on a singled Docker setup, you’ll need a multisite configuration. Here are the basic building blocks for one.

Understand hooks

Multisite is a fairly advanced topic. Before attempting a multisite build, spend some time to learn about them.

Discourse templates use pups; its rules are simple and powerful.

Each rule you run may define a hook:

run:
  exec:
    cd: some/path
    hook: my_hook
    cmd:
      - echo 1

Later on in your container you can insert rules before or after a hook:

hooks:
  before_my_hook:
    - exec: echo "I ran before"
  after_my_hook:
     - exec: echo "I ran after"

So in the example above you will see output like the following:

I ran before
1
I ran after

You can read through the templates in /var/discourse/templates to see what hooks you have available.

Amend your standalone container to provision the second site tenant

Replace the entire hooks section with:

hooks:
  after_postgres:
     - exec: sudo -u postgres createdb b_discourse || exit 0
     - exec:
          stdin: |
            grant all privileges on database b_discourse to discourse;
          cmd: sudo -u postgres psql b_discourse
          raise_on_fail: false

     - exec: /bin/bash -c 'sudo -u postgres psql b_discourse <<< "alter schema public owner to discourse;"'
     - exec: /bin/bash -c 'sudo -u postgres psql b_discourse <<< "create extension if not exists hstore;"'
     - exec: /bin/bash -c 'sudo -u postgres psql b_discourse <<< "create extension if not exists pg_trgm;"'

  after_code:
    - exec:
        cd: $home/plugins
        cmd:
          - mkdir -p plugins
          - git clone https://github.com/discourse/docker_manager.git
  before_bundle_exec:
    - file:
        path: $home/config/multisite.yml
        contents: |
         secondsite:
           adapter: postgresql
           database: b_discourse
           pool: 25
           timeout: 5000
           db_id: 2
           host_names:
             - b.discourse.example.com

  after_bundle_exec:
    - exec: cd /var/www/discourse && sudo -E -u discourse bundle exec rake multisite:migrate

There are 3 hooks in play:

  1. after_postgres ensures that after postgres is installed an additional db called b_discourse is created with the appropriate permissions.

  2. before_bundle_exec, ensures docker_manager is in place and that the multisite.yml file is in place (which defines where to find the databases)

  3. after_bundle_exec, runs the custom db migration task rake multisite:migrate this ensures all the dbs are up to date.

Note on configuration

The above sample can be split into data container / app container if needed. Just run the after_postgres hook in the data container and the rest in web container.

The above sample can be extended to provision even more DBs. To do so, provision more DBs by duplicating the create db etc calls, and make sure you add additional sites in multisite.yml.

Make sure you amend the host_names node in multisite.yml to match the actual host name you wish to host.

Also, if you plan to run HTTPS, you will need a proxy in front of the site to handle it as the built in letsencrypt functionality will not work in a multisite scenario.

Last edited by @JammyDodger 2024-05-26T20:56:50Z

Check documentPerform check on document:
「いいね!」 68

db_id: 2 の値が上記の推奨設定で何をするのか疑問に思っていました。

また、既存のマルチサイト設定に新しいサイトを追加する手順は何ですか?それは単に次のようになりますか?

  • YAML を更新する
  • ./launcher bootstrap multisite [1]
  • ./launcher start multisite

フルブートストラップまたは再構築を行わずに、必要な追加のデータベースを何らかの方法で追加して、他のすべての既存サイトへの影響を回避する方法はありますか?


  1. ./launcher rebuild multisite を最初に試しましたが、失敗したようです。 ↩︎

db id はもう必要ないと思います。

multisite ファイルを新しいサイトで編集し、

sv restart unicorn

を実行してから、データベースを移行すればよいでしょう。

「いいね!」 1

命の恩人です!

再起動に必要なコマンドでした(sv reload unicorn も試しましたが、うまくいきませんでした)。

データベースの作成に関して、自動化する方法はありますか? rake db:create[mynewdbname] のようにできれば嬉しいです。そうでなければ、短いシェルスクリプトを作成します。

現時点では、手動で作成し(DBを作成して権限を設定)、その後 RAILS_DB=newdb rake db:migrate でデータを投入しています。

そして、私が愚かなことをしていないか確認するために:

  • 現在、Docker内のマルチサイトファイル(/var/www/discourse/config/multisite.yml)を編集しています。
  • データベースを手動で作成しています。
  • rake db:migrate を実行しています。
  • sv restart unicorn を実行しています。
  • 将来の再構築やアップグレードに備えて、Docker外のYAMLファイルも編集して、マルチサイト構成を同期させる必要があります。

1か所で編集して変更をプッシュする方法があるのに、2か所でマルチサイト構成を編集するのは愚かなことでしょうか?

このドキュメントをもう少し整理して、さらに詳しい説明を提供することは可能でしょうか?まず、私はDockerに全くの初心者です。Linuxサーバーの経験はありますが、プロではありません。昔ながらのcronジョブやシェルスクリプト、Apacheのマルチサイトなどの奇妙なものが好きです。しかし、これはもっと複雑で、使い慣れたものとは異なるプログラミング言語を使用しています。もしかしたら、デモンストレーションビデオのようなものも可能でしょうか?Discourseがマルチサイト対応になれば、ファイルをいくつか編集するだけで済むので、それは素晴らしいでしょう。

それを貼り付けて、都合に合わせて編集してください。

その後、リバースプロキシを使用するか、複数のドメイン/リダイレクトでLet’s Encryptを設定するに従って、すべてのドメインの証明書を取得する必要があります。

Let’s Encryptとリバースプロキシなしでマルチサイト構成を設定するも参照してください。ただし、これは前のリンクから取得できる別の行が必要になるように更新する必要があります。更新するつもりでしたが、まだできていません。

「いいね!」 1

マルチサイトを行う場合、ドメインはどこを指すべきですか?サーバー(他のフォーラムをホストしている)と同じIPアドレスですか?

はい、すべてのドメインを同じサーバーIPに向けます。
NginxまたはCaddyサーバーでリバースプロキシを設定します。
Caddyは、すべてのドメインに無料の自動SSL証明書を提供するという点で最良です。

「いいね!」 1