Multisite configuration with Docker

docker

(Sam Saffron) #1

You may wish to host multiple domains on a singled Docker setup. To do so follow these instructions:

We strongly recommend you run separate web and data containers

The standalone container is extremely easy to configure, however has a couple of drawbacks

  1. You will need to stop your site when bootstrapping a new image
  2. You run through the db bootstrap only when needed

Multisite is a fairly advanced topic, learn about hooks before attempting this.

Understand hooks

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 site and talk to it

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.

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 have 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.


Multisite configuration step by step
Two Discourse installation in one Virtual Machine?
How to create 1000 subcategories in a scalable way?
How does multisite.yml look?
How would you migrate the wordpress.org forum to Discourse?
Pros and cons of multiple standalone containers vs one for multiple Discourse installs?
Help with multisite configuration
Success - New Multisite Install on Dedicated server using ServerPilot, Nginx and Apache
Multiple Forums in a Single Installation
Will I need to start over with multisite configuration from standalone version?
How 2 websites can use one forum?
Multiple Discourses, multiple containers, one server
Did my tutorial get deleted
Multiple Discourse Installs - Single Server
Installation wizard not appearing in multisite installs
Multisite Installation
Need proper documentation for multisite discourse with docker
Discourse multisite installation help with digitalocean
Disabling/restricting user search
Starting a second Discourse forum on the same VPS
Multi-site Installation
Install Discourse on Plesk / Ubuntu 14 without Docker
Multisite installation with seperated smtp emails
Custom Redis/PostgreSQL in Docker Installation
How do you set up multiple discourse forums on the same server?
Can I log into multiple instances of discourse simultaneously?
Multiple docker containers for multiple Discourse forums?
How to move from standalone container to separate web and data containers
Stable branch assets won't compile
Second discourse instance on the same server
How do I set category tracking level defaults historically
Feature proposal: Customizations based on primary group membership, a.k.a. tenancy 'lite'
Integration with .NET MVC application for a SaaS platform
Can we change lets encrypt script?
Pros and cons of a multisite installation
Multiple discourse instances in a single server
Multiple discourse instances in a single server
How to move from standalone container to separate web and data containers
How to move from standalone container to separate web and data containers
Can I add a plugin if I'm using Discourse hosting?
Multisite viability - 2 read-only and 1 active
Are there other workarounds to not having category moderation such as multiple instances of the board?
How can Admin login while Read-only mode is enabled on multisite?
Iterating over multisite.yml in the data container
Stable branch assets won't compile
Holy Crap! Need help with multisite configuration
Pull request for Wikis?
PAID Require Discourse expert for extreme customization
Multitenat Dockerize Discourse
How to setup multi-tenant forums?
Multi-Domain with two docker containers
Add path to cookie
Two Discourse installation in one Virtual Machine?
Little help with multisite configuration
Contabo experience with Plesk, Webmin or other server-admin setup?
Issues in discourse's multi-site configuration
Sandbox and test discourse on host?
Multisite builds are currently broken under new native theme changes
(Felix Freiberger) #119

What is the correct way to initialize a new database in a multisite configuration?

This is what I’m doing so far:

#!/bin/bash
if [ $# -eq 0 ]
  then
    echo "No arguments supplied"
    exit 1
fi

echo "Creating database..."
sudo -u postgres createdb $1 || exit 0
echo "Granting privileges..."
sudo -u postgres psql $1 <<< "alter schema public owner to discourse;"
sudo -u postgres psql $1 <<< "grant all privileges on database \"$1\" to discourse;"
echo "Creating extensions..."
sudo -u postgres psql $1 <<< "create extension if not exists hstore;"
sudo -u postgres psql $1 <<< "create extension if not exists pg_trgm;"
echo "Running db:migrate..."
RAILS_DB=$1 cd /var/www/discourse && sudo -E -u discourse bundle exec rake db:migrate
echo "Done"

This typically results in a broken site because seeding failed. However, simply re-running the db:migrate step typically fixes it.


(Felix Freiberger) #120

Sorry to bump this, but… any chance to get some advice on this by a team member? :cry:


(Sam Saffron) #121

I would strongly recommend you run in a multicontainer environment if you are doing multisite, then use createdb to create the databases by entering the postgres container.


Contabo experience with Plesk, Webmin or other server-admin setup?
(Felix Freiberger) #122

But createdb isn’t enough, the DB also needs to be seeded / migrated, right?


(Sam Saffron) #123

seeding and migrating is easy cause you already have a step for that. That is what multisite:migrate does.


(Felix Freiberger) #124

I think I had already tried running multisite:migrate from within the standalone container, and it didn’t work out – but I’m not sure about that anymore.

I’d really like to avoid having to run a multi-container setup as it doesn’t really have an advantage for me, and brings a lot of additional complexity (including having to migrate from my current setup).


(Jay Pfaffman) #125

One significant advantage, and why I think that it makes sense even for a single site, is that you can bootstrap from the command line without taking the site down for 5-15 minutes.

I think what’s wrong with your db:migrate is that it’s running for the main site, not the one you just created. Add RAILS_DB=secondsite before your rake. But the multisite:migrate should do it, I’d think (but I’m far from an expert).


Contabo experience with Plesk, Webmin or other server-admin setup?
(Felix Freiberger) #126

Bootstrapping has become such a rare event (thanks to Docker Manager) that this simply isn’t a strong enough argument to convince me to spend some hours adding complexity :slight_smile:

Good catch – the variable I’m setting might not actually come through. I’ve moved it just before the bundle command and will report back the next time I create a multisite tenant. Thanks!


Contabo experience with Plesk, Webmin or other server-admin setup?
#127

Some time ago I had time to configure multisite with 3 containers: data, web, and redis. All was working fine until one day I upgraded, and bam, something wrong happened and I had to revert to single site from backups.

Now I have a little time and wish to get this multisite setup running again. But this time, I want to clarify some things before I break stuff again :slight_smile:

  • the admin dashboard used to have a blue “upgrade” button linking to /admin/upgrade, somehow this one disappeared for me. Do you know how to make it appear again? Maybe that simple thing already taints my installation for split containers.
  • is the “button upgrade” still available in multisite mode then?
  • how would you setup to have a plugin that appears on one instance, but not the next? This would be useful for staging a plugin in production environment, or to add a site-specific plugin (e.g., a theme).

Contabo experience with Plesk, Webmin or other server-admin setup?
Contabo experience with Plesk, Webmin or other server-admin setup?
(Rafael dos Santos Silva) #128

All sites on a multisite install share the same plugins. If the plugin is broken all sites are affected.


(Fajfi) #129

Hi,

I want to setup discourse configuration with 2 site (2 domain).

My configuration: [YAML] # this is the all-in-one, standalone Discourse Docker container template ## ## - Pastebin.com I only get 1 site working - 2nd get redirection to 1st one (and ssl certificate problems), is there any bad in my config?

I thought that can be ssl problem and with commenting:

#  - "templates/web.ssl.template.yml"
#  - "templates/web.letsencrypt.ssl.template.yml"
#  - "443:443" # https

Discourse did not work with this changes (after rebuild). Even if I start fresh installation with this changes, it did not work on http (port 80).

So is there any bad multisite configuration with my file?


Setting up Let’s Encrypt with Multiple Domains
(Erlend Sogge Heggen) #130

If you only need two sites then you are probably better off setting up two separate Discourse instances.


(Fajfi) #131

It will be 3 or more in the future I think.
In two seperate instances you mean two containers with nginx reverse proxy/haproxy?


(Fajfi) #132

Ok, there is Cache problem with redirection. HTTP work but on second site I get error (500 on site):

[secondsite] Started GET "/" for **** at 2017-11-22 21:15:11 +0000
[secondsite] Processing by ListController#latest as HTML
[secondsite] Completed 500 Internal Server Error in 37ms (ActiveRecord: 11.8ms)
[secondsite] ActiveRecord::StatementInvalid (PG::UndefinedTable: 
ERROR:  relation "groups" does not exist
LINE 1: SELECT "groups"."id", "groups"."name" FROM "groups" 
ORDER BY...
                                               ^
: SELECT "groups"."id", "groups"."name" FROM "groups" ORDER BY 
 "groups"."name" ASC)
 /var/www/discourse/vendor/bundle/ruby/2.4.0/gems/rack-mini-profiler-0.10.5/lib/patches/db/pg.rb:90:in `async_exec'
 [secondsite] Started GET "/" for **** at 2017-11-22 21:15:12 +0000
 [secondsite] Processing by ListController#latest as HTML
 [secondsite] Completed 500 Internal Server Error in 4ms (ActiveRecord: 0.7ms)
 [secondsite] ActiveRecord::StatementInvalid (PG::UndefinedTable: 
 ERROR:  relation "groups" does not exist 
 LINE 1: SELECT "groups"."id", "groups"."name" FROM "groups" ORDER BY...
                                               ^
 : SELECT "groups"."id", "groups"."name" FROM "groups" ORDER BY "groups"."name" ASC)
/var/www/discourse/vendor/bundle/ruby/2.4.0/gems/rack-mini-profiler-0.10.5/lib/patches/db/pg.rb:90:in `async_exec'

(Jay Pfaffman) #133

I suspect that the second database didn’t get created.


(Fajfi) #134

I found base in psql:

b_discourse-# \dS
 pg_catalog | pg_prepared_xacts               | view  | postgres
 pg_catalog | pg_proc                         | table | postgres
 pg_catalog | pg_range                        | table | postgres
 pg_catalog | pg_replication_origin           | table | postgres
 pg_catalog | pg_replication_origin_status    | view  | postgres
 pg_catalog | pg_replication_slots            | view  | postgres
 pg_catalog | pg_rewrite                      | table | postgres
 pg_catalog | pg_roles                        | view  | postgres
 pg_catalog | pg_rules                        | view  | postgres
 pg_catalog | pg_seclabel                     | table | postgres
 pg_catalog | pg_seclabels                    | view  | postgres
 pg_catalog | pg_settings                     | view  | postgres
 pg_catalog | pg_shadow                       | view  | postgres
 pg_catalog | pg_shdepend                     | table | postgres
 pg_catalog | pg_shdescription                | table | postgres
 pg_catalog | pg_shseclabel                   | table | postgres
 pg_catalog | pg_stat_activity                | view  | postgres
 pg_catalog | pg_stat_all_indexes             | view  | postgres
 pg_catalog | pg_stat_all_tables              | view  | postgres
 pg_catalog | pg_stat_archiver                | view  | postgres
 pg_catalog | pg_stat_bgwriter                | view  | postgres
 pg_catalog | pg_stat_database                | view  | postgres
 pg_catalog | pg_stat_database_conflicts      | view  | postgres
 pg_catalog | pg_stat_replication             | view  | postgres
 pg_catalog | pg_stat_ssl                     | view  | postgres
 pg_catalog | pg_stat_sys_indexes             | view  | postgres
 pg_catalog | pg_stat_sys_tables              | view  | postgres
 pg_catalog | pg_stat_user_functions          | view  | postgres
 pg_catalog | pg_stat_user_indexes            | view  | postgres
 pg_catalog | pg_stat_user_tables             | view  | postgres
 pg_catalog | pg_stat_xact_all_tables         | view  | postgres
 pg_catalog | pg_stat_xact_sys_tables         | view  | postgres
 pg_catalog | pg_stat_xact_user_functions     | view  | postgres
 pg_catalog | pg_stat_xact_user_tables        | view  | postgres
 pg_catalog | pg_statio_all_indexes           | view  | postgres
 pg_catalog | pg_statio_all_sequences         | view  | postgres
 pg_catalog | pg_statio_all_tables            | view  | postgres
 pg_catalog | pg_statio_sys_indexes           | view  | postgres
 pg_catalog | pg_statio_sys_sequences         | view  | postgres
 pg_catalog | pg_statio_sys_tables            | view  | postgres
 pg_catalog | pg_statio_user_indexes          | view  | postgres
 pg_catalog | pg_statio_user_sequences        | view  | postgres
 pg_catalog | pg_statio_user_tables           | view  | postgres
 pg_catalog | pg_statistic                    | table | postgres
 pg_catalog | pg_stats                        | view  | postgres
 pg_catalog | pg_tables                       | view  | postgres
 pg_catalog | pg_tablespace                   | table | postgres
 pg_catalog | pg_timezone_abbrevs             | view  | postgres
 pg_catalog | pg_timezone_names               | view  | postgres
 pg_catalog | pg_transform                    | table | postgres
 pg_catalog | pg_trigger                      | table | postgres
 pg_catalog | pg_ts_config                    | table | postgres
 pg_catalog | pg_ts_config_map                | table | postgres
 pg_catalog | pg_ts_dict                      | table | postgres
 pg_catalog | pg_ts_parser                    | table | postgres
 pg_catalog | pg_ts_template                  | table | postgres
 pg_catalog | pg_type                         | table | postgres
 pg_catalog | pg_user                         | view  | postgres
 pg_catalog | pg_user_mapping                 | table | postgres
 pg_catalog | pg_user_mappings                | view  | postgres
 pg_catalog | pg_views                        | view  | postgres
(106 rows)

Any ideas?


(Jay Pfaffman) #135

Not really. Perhaps it didn’t get seeded and migrated.


(Fajfi) #136

I thought that this line is for this:

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

I used this command in app and secondsite works! Now only SSL to configure :slight_smile:


(veblock) #137

How exactly did you fix the issue? I keep getting

I, [2017-12-22T09:20:11.912278 #15] INFO -- : &gt; cd /var/www/discourse &amp;&amp; su discourse -c 'bundle exec rake db:migrate'

rake aborted!

PG::ConnectionBad: could not connect to server: No such file or directory

 Is the server running locally and accepting

 connections on Unix domain socket "/var/run/postgresql/.s.PGSQL.5432"?

Same thing locally and on the remote server. Manually can access/enter data container and Postgres with no probs.