Run Discourse as docker swarm service

I am attempting to deploy Discourse as a docker swarm service.
Used the official launcher method to deploy Discourse in a single-container setup.
Copied the required files from /var/www/discourse inside the standalone container to a location on the host servers to use in the Swarm service.
Used an existing postgre server
Created a dedicated Redis container for Discourse
Discourse fails to start and exits with:
uninitialized constant Discourse::SiteSetting (NameError)
The container connects to PostgreSQL and Redis without issues.
DISCOURSE_HOSTNAME is correctly set to discourse.xyz in the environment.
Could this be due to missing dependencies or a broken asset compilation?
Does Discourse require any modifications to properly function within a Swarm environment?

version: '3.7'

services:
  app:
    image: discourse-app:latest
    user: "1000:1000"
    working_dir: /var/www/discourse
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
      labels:
        - "traefik.enable=true"
        - "traefik.backend=discourse"
        - "traefik.docker.network=service"
        - "traefik.frontend.rule=Host:discourse.xyz"
        - "traefik.port=80"
    command:
      - "/bin/bash"
      - "-c"
      - |
        bundle config set deployment true && \
        bundle config set without 'test development' && \
        RAILS_ENV=production bundle install && \
        RAILS_ENV=production bundle exec rake db:migrate && \
        RAILS_ENV=production bundle exec rails server -b 0.0.0.0
    environment:
      DISCOURSE_DB_HOST: "postgrest1"
      DISCOURSE_DB_PORT: "5432"
      DISCOURSE_DB_USERNAME: "postgres"
      DISCOURSE_DB_PASSWORD: "****"
      DISCOURSE_DB_NAME: "discourse"
      DISCOURSE_REDIS_HOST: "redis-discourse"
      DISCOURSE_REDIS_PORT: "6379"
      DISCOURSE_REDIS_PASSWORD: "****"
      DISCOURSE_HOSTNAME: "discourse.xyz"
      DISCOURSE_DEVELOPER_EMAILS: "abc@xyz.com"
      DISCOURSE_SMTP_ADDRESS: "xyz"
      DISCOURSE_SMTP_PORT: "25"
      DISCOURSE_NOTIFICATION_EMAIL: "donotreply@xyz.com"
    networks:
      - service
    ports:
      - "8080:80"
      - "8443:443"
    volumes:
      - type: bind
        source: /discourse/discourse_files/discourse
        target: /var/www/discourse
        bind:
          propagation: rprivate

      - type: bind
        source: /discourse/shared/standalone
        target: /shared
        bind:
          propagation: rprivate

      - type: bind
        source: /discourse/shared/standalone/log/rails
        target: /data/modulusdata/infra/discourse/shared/standalone/log/rails
        bind:
          propagation: rprivate

      - type: bind
        source: /discourse/shared/standalone/log/var-log
        target: /var/log
        bind:
          propagation: rprivate

networks:
  service:
    external: true

This is beyond the support you can expect here. There are just too many tiny things that could be wrong that’s why the standard install is really all that is supported. Here are some hints. If you’re stuck and have a budget you can contact me or ask in Marketplace

You can’t use the base image. You have to bootstrap your own and push it to a repo. If you’re clever and have lots of time you can get github to do it for you.

You’ll need to put your assets on S3 (Configure an S3 compatible object storage provider for uploads)

Are you trying to have all of those write to the same log files? I’d just leave them in the container and ignore them.

I don’t think you need ports 8080 and 8443—traefik is handling that, right? Discourse won’t work on a non-standard port.

something like:

./launcher bootstrap app
docker push-that-container-to-your-private-repo
./launcher start-cmd

Then you can use the variables in the start-cmd to launch your swarm with the right stuff so it can find your database, redis, and so on. I see you have a bunch, but I’m not sure that’s all that you need.

2 Likes