Discourse on Debian Wheezy via Docker

Introduction

The makers of the StackExchange network have been working on Discourse for quite a while now. It is a modern communication platform, with the goal to be a nice mixture of classical internet forums, mailing lists, and established social media features:

Discourse is a from-scratch reboot, an attempt to reimagine what a modern, sustainable, fully open-source Internet discussion platform should be today – both from a technology standpoint and a sociology standpoint.

Technically, Discourse is based on various single components with Ruby on Rails at its core, thin as a leightweight web server, Redis for caching and job control, Sidekiq for micro job management, and PostgreSQL as a persistent database backend. Likewise, deploying Discourse right from the git repository can be a time-consuming task, not to mention the implications of maintaining a Discourse instance or running multiple Discourse instances on the same host. Discourse realized that the complicated deployment certainly prevents a couple of people from using it. Fortunately, the awesome “leightweight VM” container system Docker became production-ready in June 2014:

This release’s “1.0” label signifies a level of quality, feature completeness, backward compatibility and API stability to meet enterprise IT standards. In addition, to provide a full solution for using Docker in production we’re also delivering complete documentation, training programs, professional services, and enterprise support.

… and Discourse consequently decided to work on a Docker-based deployment system, which is the default by now, and even the only supported method (as you can see, Discourse evolves quite quickly). However, Docker is officially supported only on very modern Linux distributions, because Docker’s libcontainer as well as AuFS require kernel features that were only recently introduced. Consequently, Docker (and with that Discourse) is not supported on e.g. Debian 7 (Wheezy), which is the current “stable” Debian as sysadmins love it. But there is something we can do about it.

Although not officially supported or recommended, Docker and Discourse can be run on Debian 7 by backporting a more modern Linux kernel. Currently, Wheezy comes with a kernel from the 3.2 branch. The wheezy-backports (or Debian 8) kernel currently is from the 3.14 branch, which is new enough. Is using a kernel from backports safe? I can only tell that my system runs without quirks, and as you will find on the web, a couple of other people are also running successfully with a kernel from backports.

Hence, if you want to deploy Discourse on Wheezy, you can do it, and it will work perfectly fine. I will quickly go through the required steps in the next sections.

Using a kernel from backports

Follow the official instructions for using the backports repository:

# echo "deb http://ftp.de.debian.org/debian wheezy-backports main" > \
    /etc/apt/sources.list.d/wheezy-backports.list
# apt-get update

Get the newer kernel:

# apt-get -t wheezy-backports install linux-image-amd64 linux-headers-amd64

Reboot:

# reboot

Verify:

$ uname -a
Linux gurke2 3.14-0.bpo.1-amd64 #1 SMP Debian 3.14.12-1~bpo70+1 (2014-07-13) x86_64 GNU/Linux

Install Docker

Following the official installation instructions for Ubuntu (which Debian is very close to):

# apt-get install apt-transport-https
# apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv-keys 36A1D7869245C8950F966E92D8576A8BA88D21E9
# sh -c "echo deb https://get.docker.io/ubuntu docker main \
   > /etc/apt/sources.list.d/docker.list"
# apt-get update
# apt-get install lxc-docker

Install Discourse ecosystem

Following the instructions from here and here:

# install -g docker -m 2775 -d /var/docker
# adduser discourseuser
# usermod -a -G docker discourseuser

Now, as user discourseuser:

$ git clone https://github.com/discourse/discourse_docker.git /var/docker

Configure Discourse app

As user discourseuser:

$ cd /var/docker
$ cp samples/standalone.yml containers/app.yml

Edit app.yml to your needs. In my case, I made the Discourse container’s web server and SSH server not listen on an external interface, by changing the expose section to:

expose:
  - "127.0.0.1:8200:80"
  - "127.0.0.1:2222:22"

That means that web and SSH servers of the container are reachable through localhost, but not from outside. This has important security advantages:

  • We can proxy the HTTP traffic of the Discourse web application through a web server running on the host (e.g. nginx), and encrypt the connection (the Discourse Docker container does not have TLS support built-in, duh).
  • Why would you want to expose the Discourse container via SSH to the internet, anyway? That’s a severe mistake, in my opinion, and you should disable that unless you have a very good reason not to.

I have set DISCOURSE_SMTP_ADDRESS: 172.17.42.1, as 172.17.42.1 is the IP address of the host in the private virtual Docker network in my case. On my Debian host, I am running an Exim4 MTA, which is configured with dc_local_interfaces='172.17.42.1' and dc_relay_nets='172.17.0.0/16', i.e. it listens on the local Docker network and relays mails incoming from that network. That way, the Discourse instance running within a Docker container can send mail through the Exim MTA running on the Debian host. I have described that in more detail in another blog post.

Each change of the configuration file app.yml requires a re-build via ./launcher rebuild app. A re-build implicates stopping, destructing, bootstrapping, and launching the container. What I have learned just recently: don’t worry too much about the word “destruction”. It does not implicate data loss. You can re-build your Discourse container at any time. Persistent data is stored in the PostgreSQL database and in the shared volume, both of which are not affected by a re-build.

Hope that helps!

One Pingback/Trackback

  • menasquez

    Hi Jan, thank you for your tutorial, unfortunately i’m unable to understand how to use this line : install -g docker -m 2775 -d /var/docker

    install refers to what ?

    • Just execute this line. Did you try man install? :-)

      INSTALL(1)                                                   User Commands
      
             install - copy files and set attributes
      

      This command ist not required by POSIX, but I think it is quite common.

      • menasquez

        Yes, my bad I asked before taking a look to the man. It was conflicting with an alias of mine. Thank You.

  • Pingback: Discourse Docker container: send mail through Exim | Jan-Philip Gehrcke()