Anyone have experience running two separate Docker containers instead of the secondsite method?

I can’t seem to get the secondsite method working again, so now I’m looking at running my two sites in separate containers on the same server.

If anyone has any experience with this, drop me a message.

It is mostly doable on a decently sized machine, You’ll need a reverse proxy at the bare minimum to handle ssl. And maybe use the socketed template instead of exposing ports.

2 Likes

would a docker network be appropriate?

If you know what you are doing then yes. There shouldn’t be any problem.

2 Likes

I’ve done it with treafik and nginx proxy something. It does use more resources than multisite. You still have to understand how to get postgres to have multiple databases (unless you want to run two copies of postgres, which will require still more resources).

1 Like

This server has 12 processors and 16 Gig and these are not high volume forums, so I’m not worried about the extra resources to have two containers both running postgres.

I just need to figure out how to get two containers running at the same time, if I rebuild one, it stops the other.

I can handle the proxy issue in nginx.

You need to make another yml file, like app2.yml and change all the stuff that conflicts with the other one.

Hi Jay,

When you say

do you mean I should be treating the two containers as a single site behind a sensible hostname and failover setup (i.e. same DISCOURSE_HOSTNAME with a load balancer/health checks in front), rather than exposing both containers’ ports directly?

I’m assuming both configs can just join the same Docker network rather than binding host ports, which would avoid some of the obvious conflicts — is that the right approach?

And for the volumes: section, do the bind mounts need to be different for each container (e.g. separate /var/discourse/shared/app1 and /var/discourse/shared/app2), or is there a sane way to share some of that between them?

Thanks!

Wait. Did you clone Discourse twice? You want clone Discourse once and then have multiple yml files in the containers directory.

Maybe look at Use Nginx Proxy Manager to manage multiple sites with Discourse, though https://hub.docker.com/r/jwilder/nginx-proxy is the one that I’ve used. You just need to add some ENV variables to your YML to get it to connect up, but there are still a whole bunch of things that you have to understand to make it work.

Each site has its own hostname. That’s the point of all this, right?

I have the reverse proxy talk to port 80 on the container. Others prefer to use sockets. You should not expose any ports.

No. None of those files can be shared.

Each site needs a postgres database (can be on the same postgres server if you know how to do that).

Each site needs its own redis. They cannot share redis, which is one advantage of the multisite setup.

If you want to run two postgres’s, then just change the hostname, smtp, and volume paths and remove/comment out the ssl and letsencrypt templates. You can even use discourse-setup if you rename app.yml to, say, hostname.yml before you run ./discourse-setup again.

1 Like

could you expand on this point, i’ve adapted both examples below to fit a second site configuration rather than single-site

##########################################
# app1.yml  (web + sidekiq)
##########################################

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

- docker_args: "--network=discourse-net"
+ docker_args: "--network=discourse-net-1"

expose:
  - "8001:80"

params:
  version: tests-passed

env:
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8

  DISCOURSE_HOSTNAME: "physicsyear2.site"
  DISCOURSE_DEVELOPER_EMAILS: "tvgazebo5@gmail.com"

  DISCOURSE_SMTP_ADDRESS: smtp-relay.brevo.com
  DISCOURSE_SMTP_PORT: 2525
  DISCOURSE_SMTP_USER_NAME: "YOUR_BREVO_USERNAME"
  DISCOURSE_SMTP_PASSWORD: "YOUR_BREVO_PASSWORD"
  DISCOURSE_NOTIFICATION_EMAIL: "noreply@physicsyear2.site"

  ## External Postgres
  DISCOURSE_DB_HOST: pg
  DISCOURSE_DB_PORT: 5432
  DISCOURSE_DB_USERNAME: discourse
  DISCOURSE_DB_PASSWORD: "REPLACE_ME_discordb_strong"
-  DISCOURSE_DB_NAME: discourse
+ DISCOURSE_DB_NAME: discourse1
  DISCOURSE_DB_SOCKET: ""

  ## External Redis
-  DISCOURSE_REDIS_HOST: redis
+ DISCOURSE_REDIS_HOST: redis1
  DISCOURSE_REDIS_PORT: 6379
  DISCOURSE_REDIS_PASSWORD: "REPLACE_ME_redis_strong"

  ## MUST be identical on app1 and app2
  SECRET_KEY_BASE: "REPLACE_ME_secret_key_base"

volumes:
  - volume:
-      host: /var/discourse/shared/web-only
+     host: /var/discourse/shared/web-only-1
      guest: /shared
  - volume:
-      host: /var/discourse/shared/web-only/log/var-log
+     host: /var/discourse/shared/web-only/log/var-log-1
      guest: /var/log

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

run:
  - exec: echo "App1 starting — Sidekiq ENABLED"
  # Note: NO sidekiq/down file here → Sidekiq runs
  - exec: echo "App1 ready"



##########################################
# app2.yml  (web + sidekiq)
##########################################

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

- docker_args: "--network=discourse-net"
+ docker_args: "--network=discourse-net-2"

expose:
  - "8002:80"

params:
  version: tests-passed

env:
  LC_ALL: en_US.UTF-8
  LANG: en_US.UTF-8
  LANGUAGE: en_US.UTF-8

- DISCOURSE_HOSTNAME: "physicsyear2.site"

+ DISCOURSE_HOSTNAME: "year2physics.site"

  DISCOURSE_DEVELOPER_EMAILS: "ppyem3@gmail.com"

  DISCOURSE_SMTP_ADDRESS: smtp-relay.brevo.com
  DISCOURSE_SMTP_PORT: 2525
  DISCOURSE_SMTP_USER_NAME: "YOUR_BREVO_USERNAME"
  DISCOURSE_SMTP_PASSWORD: "YOUR_BREVO_PASSWORD"
  DISCOURSE_NOTIFICATION_EMAIL: "noreply@physicsyear2.site"

  ## External Postgres
  DISCOURSE_DB_HOST: pg
  DISCOURSE_DB_PORT: 5432
  DISCOURSE_DB_USERNAME: discourse
  DISCOURSE_DB_PASSWORD: "REPLACE_ME_discordb_strong"
-  DISCOURSE_DB_NAME: discourse
+ DISCOURSE_DB_NAME: discourse2
  DISCOURSE_DB_SOCKET: ""

  ## External Redis
-  DISCOURSE_REDIS_HOST: redis
+ DISCOURSE_REDIS_HOST: redis2
  DISCOURSE_REDIS_PORT: 6379
  DISCOURSE_REDIS_PASSWORD: "REPLACE_ME_redis_strong"

  ## MUST be identical on app1 and app2
  SECRET_KEY_BASE: "REPLACE_ME_secret_key_base"

volumes:
  - volume:
-      host: /var/discourse/shared/web-only
+     host: /var/discourse/shared/web-only-2
      guest: /shared
  - volume:
-      host: /var/discourse/shared/web-only/log/var-log
+     host: /var/discourse/shared/web-only/log/var-log-2
      guest: /var/log

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

run:
  - exec: echo "App2 starting — Sidekiq ENABLED"
  # IMPORTANT: we DO NOT create /etc/service/sidekiq/down here
  # so Sidekiq also runs in app2
  - exec: echo "App2 ready"

this sounds good, and probably explains why .\discourse-setup wasn’t working with an app.yml rather than the yml file being named the intended hostname?

1 Like

I’ve got two separate copies of Discourse, at least for now, that may allow me to play around a bit with them. As I said earlier, this system is big enough and the sites are small enough that I don’t think it’s a problem duplicating things.

Looks like I’ve got everything back online.

1 Like

It’s not the space. It’s just confusing. It’s designed to have a single discourse clone and all the containers in the containers directory. That’s why it’s called containers.

Understood. I’ll probably fix it tomorrow, sounds like an easy fix.