The preffered way to deploy Discourse is to use
https://github.com/discourse/discourse_docker, but this flow didn't fit our
Our goals are:
- Have image that has all dependencies baked in, and have it tested with all our
system, and then deployed, first to
- Be able to run discourse inside our normal
- Acknowlediging that my understanding of Ruby world is. . . limited, I wanted to
re-use as much of
- I definetely didn't want to fork discourse.
- Use 12 factor guildelines as much as possible.
What we didn't need:
- Magic button that updates discourse --- to update we'll re-build the image, test
everything and then deploy.
So here we ware.
How this works
discourse_docker relies on a provisioning tool called
pups that uses
templates to provision server. It works kinda sorta like Ansible.
Dockerfile is based on
discourse/discourse, and during image
creation we apply two templates:
We have updated
web.template.yml to disable running migrations.
At runtime we have two containers and couple of volumes.
discourse_migrate--- It runs migrations and compiles assets, then it exits.
discourse--- Runs discourse: Rails app, nginx, rsyslog, you name it ;).
It would be good to 12 factorize it, but this probably not worth the effort.
discourse_assetsfor compiled assets, assets are shared inside volume,
as they are generated in
discourse_sharedall other stuff, including: backups, letsencrypt certs etc.
docker-compose.yml contains a fully working development enviornment,
docker-compose up and after a while point your browser to:
If you need to test email sending, locally head to:
mailhog is located there.
Runtime enviorment variables
Before deploying this to producition you'll probably want to set
LANG=en_US.UTF-8 DISCOURSE_DEFAULT_LOCALE=en RAILS_ENV=production
Some ruby magic that makes discourse run faster:
# this gives us very good cache coverage, 96 -> 99 # in practice it is 1-2% perf improvement RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 # stop heap doubling in size so aggressively, this conserves memory RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000 RUBY_GC_HEAP_INIT_SLOTS=400000 RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5 ## Uncomment if you want the container to be started with the same ## hostname (-h option) as specified above (default "$hostname-$config") DOCKER_USE_HOSTNAME=true
How many threads to use:
Emails of discourse developers (will be used to initialize your instance):
SMTP Server address:
DISCOURSE_SMTP_ADDRESS=mailhog DISCOURSE_SMTP_PORT=1025 DISCOURSE_SMTP_USER_NAME= DISCOURSE_SMTP_PASSWORD= DISCOURSE_SMTP_ENABLE_START_TLS=false # (optional, default true)
Postgres database connection:
DISCOURSE_DB_USERNAME=discourse DISCOURSE_DB_PASSWORD=discourse DISCOURSE_DB_HOST=postgres DISCOURSE_DB_NAME=discourse
How to update to newer discourse version
This probably should be more or less painless, but can't be automated.
I'm unsure how many resources we'll be able to commit to keeping this up to date
So to update you'll need to:
- Clone current version of:
- Check if templates in
discourse_composite/*/templateshave been changes,
if they have been changed update them. See description to what have been changed,
at the time of writing only migration tasks were commented out.
- Test it.
Configuration and extensions
If you want to run some extra customisations like:
- Set admin user
- Enable SSO
*.rb file to
(in the container). These files will be executed after database migrations.
To configure SSO set following enviornment variables:
COMPOSE_DISCOURSE_SSO_SECRET--- contains SSO secret
COMPOSE_DISCOURSE_SSO_PROVIDER_URL--- contains SSO provider url
NOTE: Enabling of SSO is non-reversible.
Configure admin user
To configure admin user set following enviornment variables:
COMPOSE_DISCOURSE_ADMIN_EMAIL--- contains admin email
COMPOSE_DISCOURSE_ADMIN_PASSWORD--- contains admin password
COMPOSE_DISCOURSE_ADMIN_USERNAME--- contains admin username
NOTE: While after each run admin with this email and password
will exist, previously created admins won't be deleted. If user
with such password
You can also set following "misc" settings:
DJANGO_COMPOSE_INVITE_ONLYBoolean setting, controls invite_only property.
DJANGO_COMPOSE_LOGIN_REQUIREDBoolean setting, controls invite_only property.
DJANGO_COMPOSE_BOOTSTRAP_MODEBoolean setting, controls bootstrap mode.
Boolean settings can should have value
DJANGO_COMPOSE_TITLEString site title.
DJANGO_COMPOSE_SITE_DESCRIPTIONString site description
DJANGO_COMPOSE_CONTACT_EMAILString contact email
DJANGO_COMPOSE_CONTACT_URLString contact url
DJANGO_COMPOSE_COMPANY_SHORT_NAMEString company name
DJANGO_COMPOSE_COMPANY_FULL_NAMEString company full name
DJANGO_COMPOSE_COMPANY_DOMAINString company domain
- Right now assets are generated inside
discourse_migrateand not during
image creation, asset creation during image build is not easy as Rails insists
that database needs to be present for asset generation I'm not sure this is Rails
fault, or Discourse just needs database for this.
- Enable and test letsencrypt template.