I believe the launcher was built before docker compose was a thing:
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.
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
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.
Using non-wizard-take-my-by-the-hand approach is not āopinionated, specific or specialā
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:
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
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.
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:
- 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
- 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.
Ehā¦
The script doesnāt even need access to /var/discourse
(why it does?!).
The whole problem stems from a couple of things:
- huge misunderstanding what docker it, how it works and what it enables
- 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
- proper versioning: you tag the image with the released discourse version (3.4.5 or whatnot)
- 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.
Uhm⦠had to do a bit of digging regarding plugins and again I have to say/quote:
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.
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.
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 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.
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.