# Discourse Image Builder for Gitlab CI/CD Pipelines

**URL:** https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857
**Category:** Self-hosting
**Tags:** unsupported-install
**Created:** [April 16, 2023, 12:44pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857 "2023-04-16T12:44:10Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![mkbrechtel](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mkbrechtel/32/295242_2.png) [@mkbrechtel](https://meta.discourse.org/u/mkbrechtel)
#### Post date: [April 16, 2023, 12:44pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/1 "2023-04-16T12:44:10Z")

</div>

Heyho!

We created a repository called [RPS Discourse Image Builder](https://gitlab.com/idcohorts/rps/discourse-image-builder) is used to create a Discourse OCI image. I think this might be helpful to some people looking here. We mainly did this so we don’t need to wait for the discourse deploy which takes long and to be able to version pin discourse reliably.

We wrote a script that uses the discourse\_docker repo to build the image with the stable version in the most general way possible.

There is also a docker compose file that brings up the databases required for building and the discourse image for testing and runs it for local development. This can run on a GitLab runner with the `shell` executor, but you need a system with a `docker-compose` version that supports profiles.

## Approach

The build script should be run within our CI/CD pipelines so we can easily update the version so further adjustments are done in different repos with Dockerfiles that are based on the image created by this repo.

## Background

Discourse is a very nice piece of software, but it is not very easy to deploy and to version pin. This repository is used to create a docker image that can be used to deploy discourse.

The problem is that discourse has a very unique way of building their docker images. The Discourse developers expect you to build the image on the target machine with their discourse\_docker repo.

There have been a lengthy discussions about this on the forum, TL;DR: The discourse lead developers refuse to support a public docker image that can be used to deploy discourse. They want to keep the discourse\_docker repo as the only official way to deploy discourse.

The main disadvatages for this approach are:

- It is not possible, from our experience, to version pin discourse reliably.
- It takes a long time to build the image and when the image is built the service is not available. Also discourse has the longest DevOps iteration cycle of all the services we support.
- Databases are managed in a different way than for usual docker based projects.
- The official Discourse deployment story is incompatible with OCI based development workflows and deployments, like Kubernetes or even Docker-Compose.
- The discourse\_docker launcher makes a lot of assumptions about the environment it is running in. For example it refuses to run on rootless Podman with an error about missing storage volumes without being able to bypass this with an argument or env var.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [April 16, 2023, 4:47pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/4 "2023-04-16T16:47:34Z")

</div>

> [@mkbrechtel](#):
>
> It is not possible, from our experience, to version pin discourse reliably.

There is a `version` parameter on the app.yml file that can be set to the version you want to run.

> [@mkbrechtel](#):
>
> It takes a long time to build the image and when the image is built the service is not available. Also discourse has the longest DevOps iteration cycle of all the services we support.

Using the [official install](https://meta.discourse.org/t/142537?silent=true) that is handled using [Move from standalone container to separate web and data containers](https://meta.discourse.org/t/move-from-standalone-container-to-separate-web-and-data-containers/29413).

> [@mkbrechtel](#):
>
> Databases are managed in a different way than for usual docker based projects.

True, we try to make it friendly for webmasters from the “drag and drop this zip file contents with FileZilla via FTP”, while ensuring that everyone runs recent, supported and patched versions of all the software in the stack, even their Databases.

For more knowledgeable Discourse admins, pointing to an externally managed database is an environment variable away per [Configure Discourse to use a separate PostgreSQL server](https://meta.discourse.org/t/configure-discourse-to-use-a-separate-postgresql-server/46375)

> [@mkbrechtel](#):
>
> The official Discourse deployment story is incompatible with OCI based development workflows and deployments, like Kubernetes or even Docker-Compose.

Yes, the launcher based flow is not compatible out-of-the-box with container orchestration. That said, it can be made compatible by running `./launcher bootstrap app` and pushing the resulting image to a container registry and then running said image via orchestration.

> [@mkbrechtel](#):
>
> For example it refuses to run on rootless Podman with an error about missing storage volumes without being able to bypass this with an argument or env var.

We welcome a pull request to make this possible, as it sounds useful generally. #pr-welcome

---

<div class="post-metadata">

### Author: ![mkbrechtel](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mkbrechtel/32/295242_2.png) [@mkbrechtel](https://meta.discourse.org/u/mkbrechtel)
#### Post date: [April 16, 2023, 9:10pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/5 "2023-04-16T21:10:55Z")

</div>

> [@Falco](#):
>
> There is a `version` parameter on the app.yml file that can be set to the version you want to run.

We tried that to create a deployment from 2.8, but it fails complaining about a wrong Discourse version. Since we can now reproduce this in our CI/CD you can look at the error here: [docker-build (#4121616927) · Jobs · idcohorts / RPS / Discourse Image Builder · GitLab](https://gitlab.com/idcohorts/rps/discourse-image-builder/-/jobs/4121616927#L160)

> [@Falco](#):
>
> Using the [official install](https://meta.discourse.org/t/142537?silent=true) that is handled using Move from standalone container to separate web and data containers.

> [@Falco](#):
>
> Yes, the launcher based flow is not compatible out-of-the-box with container orchestration. That said, it can be made compatible by running `./launcher bootstrap app` and pushing the resulting image to a container registry and then running said image via orchestration.

That’s what we are doing basically. 🙂

> [@Falco](#):
>
> We welcome a pull request to make this possible, as it sounds useful generally. #pr-welcome

Thank you, on it.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [April 16, 2023, 9:13pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/6 "2023-04-16T21:13:07Z")

</div>

> [@mkbrechtel](#):
>
> We tried that to create a deployment from 2.8, but it fails complaining about a wrong Discourse version. Since we can now reproduce this in our CI/CD you can look at the error here: [docker-build (#4121616927) · Jobs · idcohorts / RPS / Discourse Image Builder · GitLab](https://gitlab.com/idcohorts/rps/discourse-image-builder/-/jobs/4121616927#L160)

That’s because Discourse 2.8 is unsupported now, which means we didn’t back port newest Ruby to it, and it runs on a Ruby version that’s already EOL. No one should run it in production.

---

<div class="post-metadata">

### Author: ![mkbrechtel](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mkbrechtel/32/295242_2.png) [@mkbrechtel](https://meta.discourse.org/u/mkbrechtel)
#### Post date: [April 16, 2023, 9:30pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/7 "2023-04-16T21:30:23Z")

</div>

> [@mkbrechtel](#):
>
> Thank you, on it.

Done, see [add bypasses for unsupported docker versions by mkbrechtel · Pull Request #706 · discourse/discourse\_docker · GitHub](https://github.com/discourse/discourse_docker/pull/706)

---

<div class="post-metadata">

### Author: ![mkbrechtel](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mkbrechtel/32/295242_2.png) [@mkbrechtel](https://meta.discourse.org/u/mkbrechtel)
#### Post date: [April 17, 2023, 6:14pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/8 "2023-04-17T18:14:53Z")

</div>

> [@Falco](#):
>
> That’s because Discourse 2.8 is unsupported now, which means we didn’t back port newest Ruby to it, and it runs on a Ruby version that’s already EOL. No one should run it in production.

Still it is not even technically possible (with just changing the version parameter), so we can’t reproduce old environments anymore.

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [April 17, 2023, 6:48pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/9 "2023-04-17T18:48:18Z")

</div>

> [@mkbrechtel](#):
>
> Still it is not even technically possible (with just changing the version parameter), so we can’t reproduce old environments anymore.

well you can, you just have to use an older base image.

---

<div class="post-metadata">

### Author: ![mkbrechtel](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/mkbrechtel/32/295242_2.png) [@mkbrechtel](https://meta.discourse.org/u/mkbrechtel)
#### Post date: [April 17, 2023, 7:21pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/10 "2023-04-17T19:21:08Z")

</div>

> [@merefield](#):
>
> well you can, you just have to use an older base image.

How would i do that? I searched for it and did not find a solution…

---

<div class="post-metadata">

### Author: ![merefield](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/merefield/32/176214_2.png) [@merefield](https://meta.discourse.org/u/merefield)
#### Post date: [April 17, 2023, 7:58pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/11 "2023-04-17T19:58:44Z")

</div>

You literally reference the older base image (created approximately around the date of the release you are targeting - it obviously must be at least later)

There are pages (and pages!) of them:

> **[discourse/base - Docker Image](https://hub.docker.com/r/discourse/base/tags)**

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [April 18, 2023, 2:28pm UTC](https://meta.discourse.org/t/discourse-image-builder-for-gitlab-ci-cd-pipelines/261857/12 "2023-04-18T14:28:32Z")

</div>

> [@Falco](#):
>
> There is a `version` parameter on the app.yml file that can be set to the version you want to run.

But if you try to pin to a version that is too old, it may not work with updated versions of the Discourse base image. I can’t remember specific examples, but stuff like and old version of Discourse won’t work with Ruby 3.2, so you (sometimes) also need to pin `discourse_docker` if you pin to an old version of Discourse.

The safest and, in most cases, least wasteful solution is to build an image and push it to a repo rather than building a new image at every deployment. And if you have plugins, you’re likely to need to pin each of those as well.

> [@Falco](#):
>
> it can be made compatible by running `./launcher bootstrap app` and pushing the resulting image to a container registry and then running said image via orchestration.

I’ve done this for several clients for ECS as well as k8s on GCP and AWS.

> [@mkbrechtel](#):
>
> so we can’t reproduce old environments anymore.

I’m pretty sure that you can if you also pin `discourse_docker` to the old version. As I mentioned above, it’s more complicated with plugins, as you’re likely to need to pin those to the old versions as well. If you really want to maintain old versions building them exactly once and pushing them to a repo is the way to go. I’m doing this with a client to test upgrade paths from current production to latest and it’s working smoothly.
