Can Discourse ship frequent Docker images that do not need to be bootstrapped?

I believe the launcher was built before docker compose was a thing:

1 Like

Docker compose does not feature the required functionality. Discourse’s docker file templating construction allows for flexible docker results. With compose all you have is a possible set of fixed Dockefiles which can result in a bunch of containers.

In my Discourse setup I use a single container with Discourse and nginx using a UNIX socket. PostgreSQL and Redis are a service on the host. That is quite a deviation from the the default setup, but it is possible out of the box.

It is partially possible with compose, maybe by using the rather ill engineered profile feature. But even then it is rather messy. Or you would need to deliver different compose files for each variation.

You are just moving the problem.

A clean compose setup for Discourse would be the following services in separate containers:

  • Discourse
  • nginx
  • PostgreSQL
  • Redis

Disocurse and nginx need to share a volume, no biggy.

PostgreSQL and Redis… those are things you might want to host elsewhere, and not have a Discourse specific container for it. And now docker compose become an issue docker compose up -d will launch your undesired PostgreSQL. Ok, so we make it docker compose --profile postgresql up -d to launch the basic discourse setup, and a postgresql container. docker compose --profile postgresql --profile redis up -d for the ā€œfullā€ self contained Discourse container setup. You better not forger a --profile ... argument, because then you have more issues.

So for better UX, you make a launcher to take care of creating the desired docker compose command. Now we are kind of back where we are. Except that modifications to the nginx container are not possible yet. So I need a nginx-http container and nginx-unix container which should be mutually exclusive? …

Sure the plugin management could be better, but doing this with docker compose, that’ll be hell.

1 Like

So, to sum it up. There won’t be proper docker image.

As for the unbelievable amount of incorrect knowledge about what docker is and how it operates: What is Docker? | Docker Docs

You can share containers while you work, and be sure that everyone you share with gets the same container that works in the same way.

Also - with the beloved ā€œlauncherā€ - how can I run discourse on k8s cluster given there is no docker image I can consume and deploy it there?

Riiight…

This script must be run as root. Please sudo or log in as root first.

No, thank you. I don’t like running random scripts from internet. I only want to have nice Docker image that I can safely run in isolation :slight_smile:

I’ve successfully deployed Discourse to Production using Docker Compose with the published image as have clients.

However, yes, it’s messy and a reasonable amount of bespoke work is involved.

It is much easier to stick with the standard install with the CDCK launcher unless you really must use a different method because you have an opionated view, specific architecture or otherwise special requirements.

1 Like

Using non-wizard-take-my-by-the-hand approach is not ā€œopinionated, specific or specialā€ :roll_eyes:

At any rate - the clue is having original docker image from discourse. As simple as that.

I tried using the official guide and ā€œlauncherā€ just to toy with the setup - with no luck (save for quite silly check if the user is root, which is just asking for problems).

I then turned to bitnami image (and their suggested compose file) from https://hub.docker.com/r/bitnami/discourse and one docker compose up later (and a bunch of SQL error [which doesn’t bode well] as well as warning from ruby [same caveat] I got running instance of discourse:

Pure convoluted and ā€œnon-standard magicā€ā€¦

So again - why there is no regular image?

Digging through sources and repositories I found that base image is used (https://hub.docker.com/r/discourse/base/) though it’s verioning/tagging surprised me (https://hub.docker.com/r/discourse/base/tags)… There are no sane versions I wondered? And indeed, looking at the main repo there didn’t seem to be any releases but hey - at least there are properly tagged versions (Tags Ā· discourse/discourse Ā· GitHub).

Now one wonder - why there are not matching images in the main docker hub?

So yeah - having a look at how things are organized I concur:

:smiley:


On the other hand (or rather: ā€œhow things should beā€), example project (smaller in scope, but the reasoning stands): GitHub - miniflux/v2: Minimalist and opinionated feed reader.

It has sane releases: Releases Ā· miniflux/v2 Ā· GitHub

Which have corresponding images correctly tagged: https://hub.docker.com/r/miniflux/miniflux/tags

And then upgrading is just switching version from x to y (or using latest tag so simple stop/pull/start will give updated version (which would run all required migrations automatically)

(oh, and the image is like 70x smaller but that’s yet another story)

Good job!

Just two questions… what are SQL errors and ruby warnings? I’m not familiar with those. But perhaps it is because I’ve used docker and stuff totally wrong way :thinking:

You do something like this:

./launcher bootstrap myimage
# the command that pushes that image to your preferred place to launch images
./launcher start-cmd

and that gives you the ENV variables you need to set to launch your image.

It’s really not that hard. You can even get it integrated into a github action so that it will build your image and push it to your docker-repo thingy. Looking at the commits to docker_compose, it looks like there are moves afoot to produce an image that doesn’t need to be bootstrapped, or at least make it easier to have it do some of the required stuff (migrate the database, precompile assets and push to s3 and so on). I’ve done this for clients who wanted to use k8s or AWS image-launcher-thingy (I can’t remember its name).

A few times I’ve considered offering such pre-built images as a service, but never found anyone who wanted to pay for such.

But there are a bunch of little pieces. Best I can tell CDCK uses launcher to build images, but they launch and manage them with other tools, just like you want to. And when they started, docker-compose wasn’t yet a decent way to do that and by the time it was, they had already made launcher work, so finding a way to migrate everyone from launcher to something else wasn’t really an option.

If the bitnami images work for you, then use them, but if they don’t, you’ll need to get help from someone who uses them, which is mostly nobody here.

2 Likes

Eh… I already deleted the file and whole setup as I found NodeBB which feels less user hostile when it comes to deployment (guide: Docker - NodeBB Documentation; simple docker-compose file with 3 services: nodebb, postgres and redis: NodeBB/docker-compose-pgsql.yml at master Ā· NodeBB/NodeBB Ā· GitHub; and nicely tagged images: Package nodebb Ā· GitHub)

However, I got the image and here are the relevant errors:

  1. seems like sql schema issue:
postgresql-1  | 2025-07-06 17:15:40.518 GMT [155] ERROR:  relation "translation_overrides" does not exist at character 523
postgresql-1  | 2025-07-06 17:15:40.518 GMT [155] STATEMENT:  SELECT a.attname, format_type(a.atttypid, a.atttypmod),
postgresql-1  | 	       pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
postgresql-1  | 	       c.collname, col_description(a.attrelid, a.attnum) AS comment,
postgresql-1  | 	       attidentity AS identity,
postgresql-1  | 	       attgenerated as attgenerated
postgresql-1  | 	  FROM pg_attribute a
postgresql-1  | 	  LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
postgresql-1  | 	  LEFT JOIN pg_type t ON a.atttypid = t.oid
postgresql-1  | 	  LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
postgresql-1  | 	 WHERE a.attrelid = '"translation_overrides"'::regclass
postgresql-1  | 	   AND a.attnum > 0 AND NOT a.attisdropped
postgresql-1  | 	 ORDER BY a.attnum
postgresql-1  |
postgresql-1  | 2025-07-06 17:15:40.616 GMT [156] ERROR:  relation "translation_overrides" does not exist at character 523
postgresql-1  | 2025-07-06 17:15:40.616 GMT [156] STATEMENT:  SELECT a.attname, format_type(a.atttypid, a.atttypmod),
postgresql-1  | 	       pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod,
postgresql-1  | 	       c.collname, col_description(a.attrelid, a.attnum) AS comment,
postgresql-1  | 	       attidentity AS identity,
postgresql-1  | 	       attgenerated as attgenerated
postgresql-1  | 	  FROM pg_attribute a
postgresql-1  | 	  LEFT JOIN pg_attrdef d ON a.attrelid = d.adrelid AND a.attnum = d.adnum
postgresql-1  | 	  LEFT JOIN pg_type t ON a.atttypid = t.oid
postgresql-1  | 	  LEFT JOIN pg_collation c ON a.attcollation = c.oid AND a.attcollation <> t.typcollation
postgresql-1  | 	 WHERE a.attrelid = '"translation_overrides"'::regclass
postgresql-1  | 	   AND a.attnum > 0 AND NOT a.attisdropped
postgresql-1  | 	 ORDER BY a.attnum
  1. ruby warnings (both in discourse as well as sidekiq containers, which kinda makes sense as they use same image :D):
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:5: warning: already initialized constant DiscourseAutomation::Scripts::ADD_USER_TO_GROUP_THROUGH_CUSTOM_FIELD
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:5: warning: previous definition of ADD_USER_TO_GROUP_THROUGH_CUSTOM_FIELD was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:6: warning: already initialized constant DiscourseAutomation::Scripts::APPEND_LAST_CHECKED_BY
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:6: warning: previous definition of APPEND_LAST_CHECKED_BY was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:7: warning: already initialized constant DiscourseAutomation::Scripts::APPEND_LAST_EDITED_BY
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:7: warning: previous definition of APPEND_LAST_EDITED_BY was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:8: warning: already initialized constant DiscourseAutomation::Scripts::AUTO_RESPONDER
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:8: warning: previous definition of AUTO_RESPONDER was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:9: warning: already initialized constant DiscourseAutomation::Scripts::AUTO_TAG_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:9: warning: previous definition of AUTO_TAG_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:10: warning: already initialized constant DiscourseAutomation::Scripts::BANNER_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:10: warning: previous definition of BANNER_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:11: warning: already initialized constant DiscourseAutomation::Scripts::CLOSE_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:11: warning: previous definition of CLOSE_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:12: warning: already initialized constant DiscourseAutomation::Scripts::FLAG_POST_ON_WORDS
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:12: warning: previous definition of FLAG_POST_ON_WORDS was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:13: warning: already initialized constant DiscourseAutomation::Scripts::GIFT_EXCHANGE
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:13: warning: previous definition of GIFT_EXCHANGE was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:14: warning: already initialized constant DiscourseAutomation::Scripts::GROUP_CATEGORY_NOTIFICATION_DEFAULT
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:14: warning: previous definition of GROUP_CATEGORY_NOTIFICATION_DEFAULT was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:15: warning: already initialized constant DiscourseAutomation::Scripts::PIN_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:15: warning: previous definition of PIN_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:16: warning: already initialized constant DiscourseAutomation::Scripts::POST
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:16: warning: previous definition of POST was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:17: warning: already initialized constant DiscourseAutomation::Scripts::SEND_PMS
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:17: warning: previous definition of SEND_PMS was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:18: warning: already initialized constant DiscourseAutomation::Scripts::SUSPEND_USER_BY_EMAIL
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:18: warning: previous definition of SUSPEND_USER_BY_EMAIL was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:19: warning: already initialized constant DiscourseAutomation::Scripts::TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:19: warning: previous definition of TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:20: warning: already initialized constant DiscourseAutomation::Scripts::TOPIC_REQUIRED_WORDS
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:20: warning: previous definition of TOPIC_REQUIRED_WORDS was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:21: warning: already initialized constant DiscourseAutomation::Scripts::USER_GLOBAL_NOTICE
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:21: warning: previous definition of USER_GLOBAL_NOTICE was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:22: warning: already initialized constant DiscourseAutomation::Scripts::USER_GROUP_MEMBERSHIP_THROUGH_BADGE
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:22: warning: previous definition of USER_GROUP_MEMBERSHIP_THROUGH_BADGE was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:23: warning: already initialized constant DiscourseAutomation::Scripts::ZAPIER_WEBHOOK
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/scripts.rb:23: warning: previous definition of ZAPIER_WEBHOOK was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:5: warning: already initialized constant DiscourseAutomation::Triggers::AFTER_POST_COOK
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:5: warning: previous definition of AFTER_POST_COOK was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:6: warning: already initialized constant DiscourseAutomation::Triggers::API_CALL
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:6: warning: previous definition of API_CALL was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:7: warning: already initialized constant DiscourseAutomation::Triggers::CATEGORY_CREATED_EDITED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:7: warning: previous definition of CATEGORY_CREATED_EDITED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:8: warning: already initialized constant DiscourseAutomation::Triggers::PM_CREATED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:8: warning: previous definition of PM_CREATED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:9: warning: already initialized constant DiscourseAutomation::Triggers::TOPIC_TAGS_CHANGED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:9: warning: previous definition of TOPIC_TAGS_CHANGED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:10: warning: already initialized constant DiscourseAutomation::Triggers::POINT_IN_TIME
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:10: warning: previous definition of POINT_IN_TIME was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:11: warning: already initialized constant DiscourseAutomation::Triggers::POST_CREATED_EDITED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:11: warning: previous definition of POST_CREATED_EDITED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:12: warning: already initialized constant DiscourseAutomation::Triggers::RECURRING
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:12: warning: previous definition of RECURRING was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:13: warning: already initialized constant DiscourseAutomation::Triggers::STALLED_TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:13: warning: previous definition of STALLED_TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:14: warning: already initialized constant DiscourseAutomation::Triggers::STALLED_WIKI
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:14: warning: previous definition of STALLED_WIKI was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:15: warning: already initialized constant DiscourseAutomation::Triggers::TOPIC
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:15: warning: previous definition of TOPIC was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:16: warning: already initialized constant DiscourseAutomation::Triggers::USER_ADDED_TO_GROUP
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:16: warning: previous definition of USER_ADDED_TO_GROUP was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:17: warning: already initialized constant DiscourseAutomation::Triggers::USER_BADGE_GRANTED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:17: warning: previous definition of USER_BADGE_GRANTED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:18: warning: already initialized constant DiscourseAutomation::Triggers::USER_FIRST_LOGGED_IN
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:18: warning: previous definition of USER_FIRST_LOGGED_IN was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:19: warning: already initialized constant DiscourseAutomation::Triggers::USER_PROMOTED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:19: warning: previous definition of USER_PROMOTED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:20: warning: already initialized constant DiscourseAutomation::Triggers::USER_REMOVED_FROM_GROUP
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:20: warning: previous definition of USER_REMOVED_FROM_GROUP was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:21: warning: already initialized constant DiscourseAutomation::Triggers::USER_UPDATED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers.rb:21: warning: previous definition of USER_UPDATED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/recurring.rb:6: warning: already initialized constant DiscourseAutomation::Triggers::Recurring::RECURRENCE_CHOICES
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/recurring.rb:6: warning: previous definition of RECURRENCE_CHOICES was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/stalled_wiki.rb:6: warning: already initialized constant DiscourseAutomation::Triggers::StalledWiki::DURATION_CHOICES
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/stalled_wiki.rb:6: warning: previous definition of DURATION_CHOICES was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:7: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED_OR_REMOVED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:7: warning: previous definition of TAGS_ADDED_OR_REMOVED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:8: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_ADDED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:8: warning: previous definition of TAGS_ADDED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:9: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::TAGS_REMOVED
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:9: warning: previous definition of TAGS_REMOVED was here
sidekiq-1     | /opt/bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:11: warning: already initialized constant DiscourseAutomation::Triggers::TopicTagsChanged::TriggerOn::MODES
sidekiq-1     | /bitnami/discourse/plugins/automation/lib/discourse_automation/triggers/topic_tags_changed.rb:11: warning: previous definition of MODES was here
sidekiq-1     | 2025-07-06T17:15:52.699Z pid=1 tid=4ox INFO: Booted Rails 7.2.2.1 application in production environment

That’s an excellent point. There isn’t really a good reason why this script cannot run as non-root.

The setup script is the only one which really needs root, for the scary part where it suggest to execute the docker install script from the internet. So even that can be changed to execute as non-root.

The launcher script doesn’t need root, it just needs write access to /var/discourse and the permission to manage docker containers.

1 Like

Eh… :slight_smile:

The script doesn’t even need access to /var/discourse (why it does?!).

The whole problem stems from a couple of things:

  1. huge misunderstanding what docker it, how it works and what it enables
  2. glueing together the notion that docker = docker-compsose (it’s not!)

You can have completely contained setup that virtually doesn’t touch the host environment…

After doing quite a lot of digging in it seems that the whole ā€œsetupā€ script was created to make installation as simple-as-possible for the very-non-technical-person. It checks, guides the user and setups everything. That may be a nice thing, but it breaks completely in anything that tries to stray even the tiniest inch from the envisioned path.

In the most basic setup, you may not even need to access to any host directories - everything will be contained within limited environment (image will be used to create the container and all the required storage would be handle via docker volumes [it has issues where you want to migrate somewhere else or access the files but we are talking about basics]).

It also tries to make sure that DNS is correct, tries to setup certs, reverse proxy, SMTP and whatnot - again, completely fine to provide this easy setup.

BUT!

The issue is NOT about throwing that away but IN ADDITION providing plain docker image (it’s already there, it’s used by the scripts and templates used by the script! discourse_docker/templates/postgres.template.yml at main Ā· discourse/discourse_docker Ā· GitHub & discourse_docker/launcher at main Ā· discourse/discourse_docker Ā· GitHub) with

  1. proper versioning: you tag the image with the released discourse version (3.4.5 or whatnot)
  2. sane, simple documentation of the expected environment variables (driving database/redis/etc connectivity) and possible paths/volumes that can be mounted to host.

Just that…

Take a look at aforementioned miniflux guide: Miniflux Installation with Docker - it gives you details about the image (and which repositories serves them) and possible environment variables to configure it.
Or MySQL docker image: https://hub.docker.com/_/mysql - same thing - guide that expains what is possbile to configure (see especially section: " Environment Variables").

Noone says: ā€œyou have to use mysql launcher to build mysql image so you can use itā€, or redis for that matter - in this case you simply use existing images and this is the clue and gist of using docker. Yet in case of discourse suddently this is ā€œbadā€ solution and everyone shouts: ā€œyou have to build your own image!ā€ – why!?

No. Because of plugins.

1 Like

Uhm… had to do a bit of digging regarding plugins and again I have to say/quote:

:smiley:

So what I’ve done - went to plugins section, clicked on first plugin looking for instructions and installation guide (Plugin directory | Discourse - Civilized Discussion → Sign in with Apple | Discourse - Civilized Discussion → Discourse Apple Authentication → Install plugins on a self-hosted site) and… dear lord - what a convoluted ā€œmessā€.

Why on earth you would need new image just to have plugins? With docker you can just specify mount directory for plugins and then place it there…

I’m not a Ruby guy so the things may be weirder here, but for example in the Java world you just drop a jar with the plugin so it would be loaded and voila - you have it running. And you are using the same image as everyone else…

(Not saying it’s not messy, just explaining why things are as they are)

Because of the Ember asset pipeline.

Which would be a mess as well, because you don’t want to have those deps externally.

2 Likes

This one: GitHub - ember-engines/ember-asset-loader: Asset loading support for Ember applications?

Why not though?

Plugins can be processed on the fly, this is also done when upgrading a plugin. With a bit of magic you can also had a new plugin to a running instance without rebuilding the container. So mounting a plugin volume to a container should be possible (with a bunch of changes).

The major problem I see is with upgrading Discourse. This can currently be done with a running instance. Upgrading basically rebuilds the Discourse. If Discourse actually came from a pre-build image you cannot change those files. So upgrading with zero/little downtime will probably require quite some work.

This is something I don’t grasp (probably missing context in terms of Ruby…).

In general with docker/containers/orchestration you can have blue-green/red-black deployments where you prepare new container with new version and switch the trafic once it’s ready. However, in general for smaller deployments that shouldn’t be an issue as most of the time service (container) startup should be mere seconds so the downtime from switching versions should be minimal (the biggest problem is having to run schema upgrades, but this applies regardless if you re-build the image or not)

Yes, but that’s not how it currently works, so that’s the part that needs work. How are you going to do this from within the Discourse admin interface. How are you doing to scale down the blue container while spinning up the green container (systems don’t have infinite resources, so before starting up blue you want to reduce unicorn workers in green.) Or you can just go for green is down, and now blue goes up.

There are a lot of things which need to be figured out and worked out. Both from a technical perspective as an administrator perspective. The single click upgrade from within the admin interface is a valuable feature.

1 Like

Plugins and custom images still need to be built, but for vanilla building for compose is becoming within reach these days - I’ve made a little proof of concept experiment here for anyone curious.

Obviously, since these are all my repos (not Discourse’sā„¢) this is not anything Official, so YMMV, and definitely do not expect official support :dragon: I’m casting this here, since it’s been mentioned folks are already running bitnami and other non-sanctioned ways of running.

The off the shelf postgres (or pgvector) images do not work for Discourse - Discourse needs to change the default config, does not connect via a superuser, support locales, and needs to support postgres upgrades without a Discourse admin needing to dump/restore.

3 Likes

Eh… this is I think the crucial difference and this ā€œupdate from the admin interfaceā€ is somewhat of a reminder of old times, when you only had ā€œweb hostingā€ with php interpreter so everything was build around that notion. And I think this carried over to how Discourse work and is expected to be managed.

Well, that’s another thing I noticed - discourse is quite heavy (the container started consuming resources during startup at a scary level) so yeah - it may be a problem.

How those are ā€œbuildā€ in the context of Ruby (which is mostly interpreted and not compiled language)?

Wouldn’t it be better to try to use off-the-shelf solutions? Even for postgres config can be easily changed by simply providing/mouting custom postgresql.conf file, no need for completely custom image with baked in config… and even still - if that’s required, discourse could provide such pre-build image that would only be pulled instead of re-build every time…

This ā€œadmin upgrade interfaceā€ is a plugin (called ā€œdocker managerā€). You don’t need to include it if you have another way of doing online updates.