# Multiple Discourses, multiple containers, one server

**URL:** <https://meta.discourse.org/t/multiple-discourses-multiple-containers-one-server/35367>\
**Category:** Self-hosting\
**Created:** [9 בנובמבר,‏ 2015,‏ 3:45am UTC](https://meta.discourse.org/t/multiple-discourses-multiple-containers-one-server/35367 "2015-11-09T03:45:16Z")\
**Posts on this page:** 1\
**Showing post:** 1

<div class="post-metadata">

**Author:** ![lightweight](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/lightweight/32/116381_2.png) [@lightweight](https://meta.discourse.org/u/lightweight)\
**Post date:** [9 בנובמבר,‏ 2015,‏ 3:45am UTC](https://meta.discourse.org/t/multiple-discourses-multiple-containers-one-server/35367/1 "2015-11-09T03:45:16Z")

</div>

Despite [at least one reference which purports to describe the process](https://meta.discourse.org/t/multisite-configuration-with-docker/14084) I found it very difficult to work out how to run multiple Discourse instances on the same hosting infrastructure (using an instance of nginx running on the host to proxy the Discourse instances).

Apparently there’s a way to run Discourse in a “multisite” mode, with multiple instances from a single code installation, but I have not yet seen a real description of how that works.

I’ve gone the route of two independent code installations, but a common data container (two separate databases on the same server). After a lot of fiddling, I’ve now got two Discourse instances running [community.oeru.org](http://community.oeru.org) and forums.oeru.org, with two separate Docker _web_ containers and a single _data_ container on a single server.

For the benefit of others wanting to achieve this, here’s how I did it:

**1.** Set up a new Postgres database in the data container - after trying to create the second database via my data.yml file (in containers dir), which didn’t seem to work - I logged directly into the container to create the second database (the launcher command is run from within the Discourse root directory, in my case /home/www/discourse):

`./launcher enter data`

and I ran the following (my second database is “discourse2”, and is owned by the same discourse user (and password) as my other Discourse instance, with db of “discourse”):

```
sudo -u postgres createdb discourse2

sudo -u postgres psql discourse2 <<END 
GRANT ALL PRIVILEGES ON DATABASE discourse2 TO discourse;
ALTER SCHEMA public OWNER TO discourse;
CREATE EXTENSION IF NOT EXISTS hstore;
CREATE EXTENSION IF NOT EXISTS pg_trgm;
END

```

and then exited:

`CTRL-D`

**2.** I restarted the data container (this seemed to be necessary, although I’m not sure why):  
`./launcher restart data`

**3.** I created a configuration for a second web container (my first is just web.yml, so I called the second web2.yml) in which I put:

* * *

```
# IMPORTANT: SET A SECRET PASSWORD in Postgres for the Discourse User
# TODO: change SOME_SECRET in this template

templates:
  # - "templates/redis.template.yml"
   - "templates/sshd.template.yml"
   - "templates/web.template.yml"
   - "templates/web.ratelimited.template.yml"

expose:
# increment the ports by one from the convention initiated by first discourse
   - "8081:80"
   - "2223:22"

params:
  ## Which Git revision should this container use? (default: tests-passed)
  #version: tests-passed

env:
   LANG: en_US.UTF-8
   ## TODO: How many concurrent web requests are supported?
   ## With 2GB we recommend 3-4 workers, with 1GB only 2
   UNICORN_WORKERS: 3

   ## TODO: configure connectivity to the databases
   DISCOURSE_DB_SOCKET: ''
   DISCOURSE_DB_USERNAME: discourse
   DISCOURSE_DB_PASSWORD: '[***discourse user password***]'
   DISCOURSE_DB_NAME: discourse2
   DISCOURSE_DB_HOST: data
   DISCOURSE_REDIS_HOST: data
   ##
   ## TODO: List of comma delimited emails that will be made admin and developer
   ## on initial signup example 'user1@example.com,user2@example.com'
   DISCOURSE_DEVELOPER_EMAILS: '[***my email***]'
   ##
   ## TODO: The domain name this Discourse instance will respond to
   DISCOURSE_HOSTNAME: 'forums.oeru.org'
   ##
   ## TODO: The mailserver this Discourse instance will use
   DISCOURSE_SMTP_ADDRESS: smtp.mandrillapp.com # (mandatory)
   DISCOURSE_SMTP_PORT: 587 # (optional)
   DISCOURSE_SMTP_USER_NAME: [***my email***] # (optional)
   DISCOURSE_SMTP_PASSWORD: [***my password***] # (optional)
   DISCOURSE_SMTP_ENABLE_START_TLS: True
   ##
   ## The CDN address for this Discourse instance (configured to pull)
   #DISCOURSE_CDN_URL: //discourse-cdn.example.com

volumes:
   - volume:
     host: /home/www/discourse/shared2/web
     guest: /shared
   - volume:
     host: /home/www/discourse/shared2/web/log/var-log
     guest: /var/log

 ## Use 'links' key to link containers together, aka use Docker --link flag.
 links:
   - link:
     name: data
     alias: data

 ## The docker manager plugin allows you to one-click upgrade Discouse
 ## http://discourse.example.com/admin/docker
 hooks:
   after_code:
      - exec:
        cd: $home/plugins
        cmd:
           - mkdir -p plugins
           - git clone https://github.com/discourse/docker_manager.git

## Remember, this is YAML syntax - you can only have one block with a name
run:
   - exec: echo "Beginning of custom commands"

## If you want to configure password login for root, uncomment and change:
## Use only one of the following lines:
#- exec: /usr/sbin/usermod -p 'PASSWORD_HASH' root
#- exec: /usr/sbin/usermod -p "$(mkpasswd -m sha-256 'RAW_PASSWORD')" root

## If you want to authorized additional users, uncomment and change:
#- exec: ssh-import-id username
#- exec: ssh-import-id anotherusername

- exec: echo "End of custom commands"
- exec: awk -F\# '{print $1;}' ~/.ssh/authorized_keys | awk 'BEGIN { print "Authorized SSH keys for this container:"; } NF>=2 {print $NF;}'`

```

**4.** Build the new web container

`./launcher bootstrap web2`

and after it finishes

`./launcher start web2`

At this point, you should be able to check [http://localhost:8081](http://localhost:8081) on the host using a text browser like links or lynx to confirm that it’s actually producing something… Finally, setting up the nginx proxy.

**5.** Then I created the following file in /etc/nginx/sites-available (you can easily upgrade this configuration to use SSL and create another server definition to redirect traffic to port 80 to port 443 - now that we’ve been accepted to the Let’s Encrypt beta, I’ll be doing that shortly and will post an update afterwards):

* * *

```
upstream discourse2 {
#fail_timeout is optional; I throw it in to see errors quickly
  server 127.0.0.1:8081 fail_timeout=5;
}

# configure the virtual host
server {
  listen 5.9.142.102:80;
  # replace with your domain name
  server_name forums.oeru.org;

  root /var/www; # placeholder only!
  index index.html;

  #Rewrite

  # assets
  location ~* \.(jpg|jpeg|gif|png|bmp|ico|pdf|txt|css|js) {
    try_files $uri @discourse2;
    add_header Cache-Control public;
    add_header Cache-Control must-revalidate;
    expires 7d;
  }

  # example.com/a.html gets redirected to example.com/a
  location ~* \.html$ {
    rewrite ^(.*)\/index.html$ $1 permanent;
    rewrite ^(.+)\.html$ $scheme://$host$1 permanent;
  }

  # example.com/foo/ loads example.com/foo/index.html
  location ~* ^(.*)/$ {
    try_files $1.html $1/index.html @discourse2;
  }

  # anything else not processed by the above rules:
  # * example.com/a will load example.com/a.html
  # * or if that fails, example.com/a/index.html

  location / {
    rewrite ^(.*)\/index$ $1 permanent;
    try_files $uri.html $uri/index.html @discourse2;
  }

  location @discourse2 {
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
    proxy_redirect off;
    proxy_pass http://discourse2;
  }
}

```

And there you have it - our second Discourse instance, “forums”, is now available on the same host as our “community” Discourse instance.. Hope this helps someone. Any feedback on this approach would be welcome!

---

_[View the full topic](https://meta.discourse.org/t/multiple-discourses-multiple-containers-one-server/35367)._
