Multiple docker containers for multiple Discourse forums?


(AstonJ) #1

Is it possible to just duplicate the install process so that you end up with multiple docker containers therefore multiple Discourse instances?

Or am I completely misunderstanding things here? :neutral_face:


(Sander Datema) #2

Why would you want to do that? If it’s because you want to have multiple Discourse instances, then go for multisite.


(AstonJ) #3

I (and by looking at that thread, a few others) find multisite confusing - I thought that by simply duplicating the install process would be the easiest option?

Do you know of any easier guides on setting up multiple discourse instances?


#4

I’m learning the ins & outs and will make a guide within the week going over everything learned, and step-by-step process.


(AstonJ) #5

Thanks - that’d be very helpful @webeindustry!

Looking at the guide now it seems to make more sense (has it been changed?) maybe I will give it a go this week and add some notes to the official wiki (or your guide) as well :slight_smile:


(Sander Datema) #6

Here’s my app.yml. Just replace the values in the env block and at the end in the before_bundle_exec block. You only need to enter some urls for your Discourse instances and you’re done. This file supports 7 instances, should be enough. :slightly_smiling:

This file will also install some plugins, btw.

# this is the base templates used, you can cut it down to include less functionality per container
templates:
  - "templates/cron.template.yml"
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/sshd.template.yml"
  - "templates/web.template.yml"

# which ports to expose?
expose:
  - "7081:80"   # fwd host port 80   to container port 80 (http)
  - "2222:22" # fwd host port 2222 to container port 22 (ssh)
  - "7181:81"

params:
  # git revision to run
  version: tests-passed

env:
  UNICORN_WORKERS: 2
  DISCOURSE_DEVELOPER_EMAILS: 'you@email.address'
  DISCOURSE_HOSTNAME: 'primary.discourse.com'
  DISCOURSE_SMTP_ADDRESS: smtp.mandrillapp.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: mandrill_username
  DISCOURSE_SMTP_PASSWORD: s0m3passw0rd

# These containers are stateless, all the data is stored in /shared
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared

# you may use the docker manager to upgrade and monitor your docker image
# UI will be visible at http://yoursite.com/admin/docker
hooks:
  after_postgres:
     - exec: sudo -u postgres createdb discourse_dbase1 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase2 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase3 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase4 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase5 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase6 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase7 || exit 0
     - exec:
          stdin: |
            grant all privileges on database discourse_dbase1 to discourse;
            grant all privileges on database discourse_dbase2 to discourse;
            grant all privileges on database discourse_dbase3 to discourse;
            grant all privileges on database discourse_dbase4 to discourse;
            grant all privileges on database discourse_dbase5 to discourse;
            grant all privileges on database discourse_dbase6 to discourse;
            grant all privileges on database discourse_dbase7 to discourse;
          cmd: sudo -u postgres psql discourse_dbase1
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase2
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase3
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase4
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase5
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase6
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase7
          raise_on_fail: false

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

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

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

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

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

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

     - exec: /bin/bash -c 'sudo -u postgres psql discourse_dbase7 <<< "alter schema public owner to discourse;"'
     - exec: /bin/bash -c 'sudo -u postgres psql discourse_dbase7 <<< "create extension if not exists hstore;"'
     - exec: /bin/bash -c 'sudo -u postgres psql discourse_dbase7 <<< "create extension if not exists pg_trgm;"'
  after_code:
    - exec:
        cd: /var/www/discourse/plugins
        cmd:
          - mkdir -p plugins
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-bbcode-color.git
          - git clone https://github.com/discourse/discourse-spoiler-alert.git
          - git clone https://github.com/discourse/discourse-tagging.git
          - git clone https://github.com/discourse/discourse-akismet.git
          - git clone https://github.com/discourse/discourse-solved.git

  before_bundle_exec:
    - file:
        path: /var/www/discourse/config/multisite.yml
        contents: |
         discourse_instance2:
           adapter: postgresql
           database: discourse_dbase2
           pool: 25
           timeout: 5000
           db_id: 2
           host_names:
             - instance2.discourse.org
         discourse_instance3:
           adapter: postgresql
           database: discourse_dbase5
           pool: 25
           timeout: 5000
           db_id: 3
           host_names:
             - instance3.discourse.org
         discourse_instance4:
           adapter: postgresql
           database: discourse_dbase4
           pool: 25
           timeout: 5000
           db_id: 4
           host_names:
             - instance4.discourse.org
         discourse_instance5:
           adapter: postgresql
           database: discourse_dbase6
           pool: 25
           timeout: 5000
           db_id: 5
           host_names:
             - instance5.discourse.org
         discourse_instance6:
           adapter: postgresql
           database: discourse_dbase7
           pool: 25
           timeout: 5000
           db_id: 6
           host_names:
             - instance6.discourse.org
         discourse_instance7:
           adapter: postgresql
           database: discourse_dbase7
           pool: 25
           timeout: 5000
           db_id: 7
           host_names:
             - instance7.discourse.org
  after_bundle_exec:
    - exec: cd /var/www/discourse && sudo -E -u discourse bundle exec rake multisite:migrate

# Remember, this is YAML syntax - you can only have one block with a name
run:
  - exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Authorized SSH keys for this container:"; } NF>=2 {print $NF;}'

(AstonJ) #7

Thanks @Sander78 that’s very helpful :slightly_smiling: (I’ll try this this week)

Just a few quick questions, will reply by email still work? And will I be able to customise each site separately?


(Sander Datema) #8

Absolutely. I have all that working on multiple Discourse instances. There’s one caveat at the moment: backups work, but restores don’t (yet). That’s the only problem I have found so far.


(AstonJ) #9

Awesome, thanks!

Is restore functionality due soon? I may move servers soon so will be needing some way to restore each site…


(Sander Datema) #10

I just moved to another server and this is how I did it. Might keep an eye on that thread.


(Sander Datema) #11

Not tested yet, but this should work as well. Now you only need to edit the first part of the file:

############################################################
###              ONLY EDIT WITHIN THIS BLOCK             ###
############################################################
###                                                      ###
### Don't touch the &variables!
###
### Owner's mail address
owner_mail: &owner_mail you@email.com
### Mandrill username
mandrill_username: &mandrill_username your_mandrill_username
### Mandrill password
mandrill_password: &mandrill_password s0m3passw0rd

### First (and primary) Discourse instance
discourse_instance1_domain: &d1domain url1.discourse.org
### 2nd Discourse instance
discourse_instance2_domain: &d2domain url2.discourse.org
### 3rd Discourse instance
discourse_instance3_domain: &d3domain url3.discourse.org
### 4th Discourse instance
discourse_instance4_domain: &d4domain url4.discourse.org
### 5th Discourse instance
discourse_instance5_domain: &d5domain url5.discourse.org
### 6th Discourse instance
discourse_instance6_domain: &d6domain url6.discourse.org
### 7th Discourse instance
discourse_instance7_domain: &d7domain url7.discourse.org
###                                                      ###
############################################################
###        ^^^^^ ONLY EDIT WITHIN THIS BLOCK ^^^^^       ###
############################################################




# this is the base templates used, you can cut it down to include less functionality per container
templates:
  - "templates/cron.template.yml"
  - "templates/postgres.template.yml"
  - "templates/redis.template.yml"
  - "templates/sshd.template.yml"
  - "templates/web.template.yml"

# which ports to expose?
expose:
  - "7081:80"   # fwd host port 80   to container port 80 (http)
  - "2222:22" # fwd host port 2222 to container port 22 (ssh)
  - "7181:81"

params:
  # git revision to run
  version: tests-passed

env:
  UNICORN_WORKERS: 2
  DISCOURSE_DEVELOPER_EMAILS: *owner_mail
  DISCOURSE_HOSTNAME: *db1domain
  DISCOURSE_SMTP_ADDRESS: smtp.mandrillapp.com
  DISCOURSE_SMTP_PORT: 587
  DISCOURSE_SMTP_USER_NAME: *mandrill_username
  DISCOURSE_SMTP_PASSWORD: *mandrill_password

# These containers are stateless, all the data is stored in /shared
volumes:
  - volume:
      host: /var/discourse/shared/standalone
      guest: /shared

# you may use the docker manager to upgrade and monitor your docker image
# UI will be visible at http://yoursite.com/admin/docker
hooks:
  after_postgres:
     - exec: sudo -u postgres createdb discourse_dbase1 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase2 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase3 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase4 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase5 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase6 || exit 0
     - exec: sudo -u postgres createdb discourse_dbase7 || exit 0
     - exec:
          stdin: |
            grant all privileges on database discourse_dbase1 to discourse;
            grant all privileges on database discourse_dbase2 to discourse;
            grant all privileges on database discourse_dbase3 to discourse;
            grant all privileges on database discourse_dbase4 to discourse;
            grant all privileges on database discourse_dbase5 to discourse;
            grant all privileges on database discourse_dbase6 to discourse;
            grant all privileges on database discourse_dbase7 to discourse;
          cmd: sudo -u postgres psql discourse_dbase1
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase2
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase3
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase4
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase5
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase6
          raise_on_fail: false
          cmd: sudo -u postgres psql discourse_dbase7
          raise_on_fail: false

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

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

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

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

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

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

     - exec: /bin/bash -c 'sudo -u postgres psql discourse_dbase7 <<< "alter schema public owner to discourse;"'
     - exec: /bin/bash -c 'sudo -u postgres psql discourse_dbase7 <<< "create extension if not exists hstore;"'
     - exec: /bin/bash -c 'sudo -u postgres psql discourse_dbase7 <<< "create extension if not exists pg_trgm;"'
  after_code:
    - exec:
        cd: /var/www/discourse/plugins
        cmd:
          - mkdir -p plugins
          - git clone https://github.com/discourse/docker_manager.git
          - git clone https://github.com/discourse/discourse-bbcode-color.git
          - git clone https://github.com/discourse/discourse-spoiler-alert.git
          - git clone https://github.com/discourse/discourse-tagging.git
          - git clone https://github.com/discourse/discourse-akismet.git
          - git clone https://github.com/discourse/discourse-solved.git

  before_bundle_exec:
    - file:
        path: /var/www/discourse/config/multisite.yml
        contents: |
         discourse_instance2:
           adapter: postgresql
           database: discourse_dbase2
           pool: 25
           timeout: 5000
           db_id: 2
           host_names:
             - *db2domain
         discourse_instance3:
           adapter: postgresql
           database: discourse_dbase5
           pool: 25
           timeout: 5000
           db_id: 3
           host_names:
             - *db3domain
         discourse_instance4:
           adapter: postgresql
           database: discourse_dbase4
           pool: 25
           timeout: 5000
           db_id: 4
           host_names:
             - *db4domain
         discourse_instance5:
           adapter: postgresql
           database: discourse_dbase6
           pool: 25
           timeout: 5000
           db_id: 5
           host_names:
             - *db5domain
         discourse_instance6:
           adapter: postgresql
           database: discourse_dbase7
           pool: 25
           timeout: 5000
           db_id: 6
           host_names:
             - *db6domain
         discourse_instance7:
           adapter: postgresql
           database: discourse_dbase7
           pool: 25
           timeout: 5000
           db_id: 7
           host_names:
             - *db7domain
  after_bundle_exec:
    - exec: cd /var/www/discourse && sudo -E -u discourse bundle exec rake multisite:migrate

# Remember, this is YAML syntax - you can only have one block with a name
run:
  - exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Authorized SSH keys for this container:"; } NF>=2 {print $NF;}'

Multisite Discourse separate folder structure of each instance - 2018
#12

You seem to have errors in the app.yml posted. You list db_id: 6 for 3 separate instances. MIght this be the cause of restore failure?

also, 1, 2, 5, 4, 6, 7, 7,


(Sander Datema) #13

Good point. Though it’s only appearing in this example file. Bad copy/pasting. I edited both my examples above to correct those mistakes.


(honggian) #14

Hello @Sander78.

Is the multiple Discourse instance code is still works? Do you know any updated information for the multiple instance configuration? I am interested in the multiple instance all the time, but I am not sure it yet.

By the way, I already succeed the discourse installation in the nginx reverse proxy environment.

Thank you

Honggi An


(Sander Datema) #15

I’m still using this same configuration with an updated Discourse. So yeah, it should work.


(Siraphop Sea S.) #16

Please help:

  1. Create xxx.yml with edited multisite template you shared 4 posts above this post.
  2. ./launcher rebuild xxx
  3. Fail with error.
Ensuring launcher is up to date
Fetching origin
Launcher is up-to-date
cd /pups && git pull && /pups/bin/pups --stdin
/usr/bin/docker: invalid reference format.
See '/usr/bin/docker run --help'.
cat: cids/app_bootstrap.cid: No such file or directory
"docker rm" requires at least 1 argument.
See 'docker rm --help'.

Usage:  docker rm [OPTIONS] CONTAINER [CONTAINER...] [flags]

Remove one or more containers
rm: cannot remove 'cids/app_bootstrap.cid': No such file or directory
** FAILED TO BOOTSTRAP ** please scroll up and look for earlier error messages, there may be more than one

Question:

  • for 2. did I use the wrong command or skip some step?

Best,
Sea


(Sander Datema) #17

I’m afraid I have no idea what is causing that or how to resolve it…


(Siraphop Sea S.) #18

Can you help me explain this following term?

  • instance
  • container
  • data.xml
  • web_only.xml

Thank in advance,
Sea