Would anyone be able to advise on building a Discourse Docker image that has a number of plugins built in rather than installing via the UI?
Background - we want to utilise the latest Discourse build i.e. discourse:stable and from what I have read in the installation guide and other documentation is that we can take this as a base image in our own Dockerfile and then do something like:
RUN cd /var/www/discourse/plugins && \
git clone https://github.com/discourse/discourse-chat-integration.git
This would add the discourse-chat-integration plugin into the build. Then at runtime we can pass in all the required environment variables i.e. DISCOURSE_HOSTNAME, DISCOURSE_SMTP_DOMAIN, DISCOURSE_DB_HOST etc rather than having these hardcode in the app.yml file.
If anyone could advise on the above it would be greatly appreciated.
You can’t install plugins from the UI. You install them from the YML file. If you’re using some not-yet-supported container that you didn’t build yourself with launcher, then you’d do something like you suggest.
But that plugin is in core (but maybe not yet in stable?).
They aren’t really hard-coded in the YML file. The yml file is used to build and launch the container. You can build it and then launch it yourself, however you want. You can use ./launcher start-cmd container-name (or something like that, you can look in launcher to see if I got it wrong).
So what I think you want to do is continue to use launcher, add the plugin, ./launcher bootstrap app the container, and then launch it however you want. You can even push it to a repo where you can launch it from some other machine.
So, what we are looking to do is run Discourse in our Kubernetes cluster and would like to be able to build the image in our CI/CD workflow hence the custom Dockerfile. All of the environment variables are then supplied to the running pod in a ConfigMap and/pr Secret. I know this is not a supported install but am trying to at least use the supported way of building a Discourse image for a specific version of Discourse so we can control when we update.
Looking at the existing launcher script and the samples/web_only.yml I believe I can comment out the volumes and links sections as this would be done in Kubernetes with a Persistent Volume and mount. We would then add the fixed environment values in the web_only.yml, build the container with the bootstrap command and then copy the generated image to our own repository.
For the Discourse version, we can monitor when a new release is available in Docker Hub and then amend the base_image value in the web.template.yml file.
Does this sounds correct?
One other question - in the web.template.ymlit performs a db:migrate command but at the time of running the bootstrap we are not connecting to any database - I did try to use the --skip-tags flag but that doesn’t seem to work anymore. Can that command just be removed from the template as it will be performed in an initcontainer when we start the pod.
Maybe, but the container needs to talk to some database to build the container, usually. It doesn’t need to be the actual database (but then you need to migrate the database and precompile assets in your pipeline).
You may be conflating the issue of Discourse upgrades vs updates of the resources in the base container.
I did manage to get the container to build ok without the db:migrate hook - not sure if its going to work as I have not tested it yet - its on the todo list
For the base_image value - I assume this changes when a new docker image is released so I think I will just take whatever is on main branch as that is what gets called in the launcher script.
Thanks Jay. Finally got my build to work, well the pod started I changed my CI/CD build process to include the db:migrate by using a temporary db.
Does a db:migrate always need to be executed on start up as my image build would be against a dummy db/redis? My current approach is that the db:mirgate and precompile would be performed in an initContainer in my pod.
The discourse/discourse image would be ideal to use if it will be production ready soon.
If you’re interested in zero-downtime upgrades you should use SKIP_POST_DEPLOYMENT_MIGRATIONS and after the old pods are dead do the migration again with something like rake db:ensure_post_migrations db:migrate
At present I and setting several env vars in our deployment i.e. DISCOURSE_BACKUP_LOCATION=s3 and my understanding is Discourse will use that value rather than what has been set via the UI and hence stored in the site_settings table - is that correct? If yes, are there any tools/scripts available that would allow me to check what env vars are set and determine their site setting equivalent?
Why - I am looking to migrate a running Discourse instance and to help minimise the risk I wanted to not set the env vars for now incase I missed any in the new instance and had a detrimental impact on the new instance. My thought was I could check what is set in the current instance, create the relevant settings in the table, backup/restore to the new instance and then extract away to the env vars one at a time.
Logical - maybe not but I thought that would be the most common sense approach just incase an env var in the running instance is different/not supported in the new instance (running = old Discourse version, new = latest Discourse)