Deploying Discourse with Dokku
I’ve recently been using DigitalOcean’s Droplet service, which allows you to deploy SSD cloud servers with the press of a button.
I needed a quick and easy Docker-based solution to manage the applications I deployed to the Droplet, which lead me to Dokku.
Dokku
Dokku is a small PaaS that boasts easy Git deploys from the command line to the cloud. Once you’ve gone through the initial setup, all you need to do when deploying new applications is add a remote to your repository and push your code up to it. Dokku will handle the rest.
git remote add dokku dokku@example.com:todo
git push dokku master
Dokku handles the routing for you (assuming you’ve setup your DNS correctly), and the app becomes available at https://todo.example.com.
Discourse
I wanted to use Dokku to manage my deployment of Discourse on my Droplet, but the setup process for Discourse requires a bootstrapping process that goes beyond what Dokku is capable of handling. But I still wanted Dokku to handle the routing and Let’s Encrypt SSL certificate.
What I ended up doing was using Discourse’s bootstrapping process to create a standalone container image called local_discourse/app
with the configuration I needed. Then I made repository that just has a Dockerfile that derives itself from that base image. Dokku builds the image based on the bootstrapped one and deploys it for me.
I’ll outline the commands used for the bootstrapping and deployment process below.
Bootstrapping Discourse
Discourse has a repository that contains the files needed to bootstrap an image. Start off by being SSH’d into your server and cloning the repository.
mkdir /var/discourse
git clone https://github.com/discourse/discourse_docker.git /var/discourse
cd /var/discourse
Then we’ll copy the default standalone configuration and modify it.
cp samples/standalone.yml containers/app.yml
nano containers/app.yml
You’ll want to go down to the env
section and modify the developer emails, hostname, and SMTP variables to match your environment. Email has to be setup correctly in order for Discourse to work.
Once you’re done, save the file and bootstrap the image.
./launcher bootstrap app
If successful, you should see an image named local_discourse/app
when you run the following command.
docker images
Next we’ll use the launcher to start the Discourse instance, but only so we can get the docker run
command that is output in the console window.
./launcher start app
The docker run
should be output to the console window. Copy the command and save it for later. We'll need to replicate the same arguments when we deploy our app with Dokku.
Now you can stop and destroy the instance with the launcher.
./launcher stop app
./launcher destroy app
Configuring Dokku
Now you can setup and configure the app with Dokku.
dokku apps:create discourse
dokku proxy:ports-add discourse http:80:80 https:443:80
dokku proxy:ports-remove discourse http:80:5000
Next we need to take the arguments passed into the docker run
command and add them to Dokku. However, first you need to strip out the -p port:port
arguments. For reference, it should look something like this.
dokku docker-options:add discourse run,deploy "-e LANG=en_US.UTF-8 -e RAILS_ENV=production -e UNICORN_WORKERS=3 -e UNICORN_SIDEKIQS=1 -e RUBY_GLOBAL_METHOD_CACHE_SIZE=131072 -e RUBY_GC_HEAP_GROWTH_MAX_SLOTS=40000 -e RUBY_GC_HEAP_INIT_SLOTS=400000 -e RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR=1.5 -e DISCOURSE_DB_SOCKET=/var/run/postgresql -e DISCOURSE_DB_HOST= -e DISCOURSE_DB_PORT= -e DISCOURSE_HOSTNAME=xxx.xxx -e DISCOURSE_DEVELOPER_EMAILS=xxx@xxx.xxx -e DISCOURSE_SMTP_ADDRESS=xxx.xxx -e DISCOURSE_SMTP_PORT=587 -e DISCOURSE_SMTP_USER_NAME=xxx@xxx.xxx -e DISCOURSE_SMTP_PASSWORD=xxx -e DISCOURSE_SMTP_ENABLE_START_TLS=true -h xxxxxx -e DOCKER_HOST_IP=x.x.x.x -v /var/discourse/shared/standalone:/shared -v /var/discourse/shared/standalone/log/var-log:/var/log --mac-address xx:xx:xx:xx:xx:xx"
You can take it a step further and issue a Let’s Encrypt certificate for your new app.
dokku config:set --no-restart discourse DOKKU_LETSENCRYPT_EMAIL=scott@batary.io
dokku letsencrypt discourse
Deploying Discourse
Now you can create your Git repository and add a Dockerfile.
FROM local_discourse/app ENTRYPOINT ["/sbin/boot"]
Then add your remote and push it up to your server.
git remote add dokku dokku@example.com:discourse
git add . git commit -m "initial commit"
git push dokku master
And now Discourse should be available.