Kann Discourse regelmäßig Docker-Images bereitstellen, die nicht gebootstrapped werden müssen?

Ich glaube, der Launcher wurde erstellt, bevor Docker Compose aufkam:

1 „Gefällt mir“

Docker Compose bietet nicht die erforderliche Funktionalität. Die Dockerfile-Templating-Konstruktion von Discourse ermöglicht flexible Docker-Ergebnisse. Mit Compose haben Sie lediglich eine mögliche Sammlung fester Dockerfiles, die zu einer Vielzahl von Containern führen können.

In meinem Discourse-Setup verwende ich einen einzelnen Container mit Discourse und Nginx, der einen UNIX-Socket nutzt. PostgreSQL und Redis sind ein Dienst auf dem Host. Das weicht erheblich vom Standard-Setup ab, ist aber out-of-the-box möglich.

Es ist teilweise mit Compose möglich, vielleicht durch die eher schlecht konstruierte Profil-Funktion. Aber selbst dann ist es ziemlich unübersichtlich. Oder Sie müssten für jede Variante unterschiedliche Compose-Dateien bereitstellen.

Sie verschieben nur das Problem.

Ein sauberes Compose-Setup für Discourse würde die folgenden Dienste in separaten Containern umfassen:

  • Discourse
  • Nginx
  • PostgreSQL
  • Redis

Discourse und Nginx müssen sich ein Volume teilen, keine große Sache.

PostgreSQL und Redis… das sind Dinge, die Sie vielleicht woanders hosten möchten und keinen Discourse-spezifischen Container dafür benötigen. Und nun wird Docker Compose zu einem Problem: docker compose up -d startet Ihr unerwünschtes PostgreSQL. Okay, also machen wir daraus docker compose --profile postgresql up -d, um das grundlegende Discourse-Konfiguration und einen PostgreSQL-Container zu starten. docker compose --profile postgresql --profile redis up -d für das “vollständige” in sich geschlossene Discourse-Container-Setup. Sie sollten besser kein --profile ...-Argument vergessen, denn dann haben Sie weitere Probleme.

Für eine bessere UX erstellen Sie also einen Launcher, der sich um die Erstellung des gewünschten Docker Compose-Befehls kümmert. Jetzt sind wir irgendwie wieder am Anfang. Außer dass Modifikationen am Nginx-Container noch nicht möglich sind. Ich brauche also einen Nginx-HTTP-Container und einen Nginx-UNIX-Container, die sich gegenseitig ausschließen sollten? …

Sicher, das Plugin-Management könnte besser sein, aber das mit Docker Compose zu machen, das wird die Hölle.

1 „Gefällt mir“

Zusammenfassend lässt sich sagen, dass es kein richtiges Docker-Image geben wird.

Was die unglaubliche Menge an falschem Wissen darüber, was Docker ist und wie es funktioniert, betrifft: What is Docker? | Docker Docs

Sie können Container teilen, während Sie arbeiten, und sicher sein, dass jeder, mit dem Sie sie teilen, denselben Container erhält, der auf die gleiche Weise funktioniert.

Und mit dem beliebten „Launcher“ – wie kann ich Discourse auf einem k8s-Cluster ausführen, wenn es kein Docker-Image gibt, das ich konsumieren und dort bereitstellen kann?

Riiight…

Dieses Skript muss als Root ausgeführt werden. Bitte führen Sie sudo aus oder melden Sie sich zuerst als Root an.

Nein, danke. Ich mag es nicht, zufällige Skripte aus dem Internet auszuführen. Ich möchte nur ein schönes Docker-Image haben, das ich sicher isoliert ausführen kann :slight_smile:

Ich habe Discourse erfolgreich mit Docker Compose und dem veröffentlichten Image für die Produktion bereitgestellt, ebenso wie meine Kunden.

Es ist jedoch unordentlich und erfordert eine beträchtliche Menge an kundenspezifischer Arbeit.

Es ist viel einfacher, bei der Standardinstallation mit dem CDCK-Launcher zu bleiben, es sei denn, Sie müssen wirklich eine andere Methode verwenden, weil Sie eine eigene Meinung, eine spezielle Architektur oder andere besondere Anforderungen haben.

1 „Gefällt mir“

Die Verwendung eines nicht-assistentengeführten Ansatzes ist nicht “voreingenommen, spezifisch oder besonders” :roll_eyes:

Auf jeden Fall – der Hinweis ist das ursprüngliche Docker-Image von Discourse. So einfach ist das.

Ich habe versucht, die offizielle Anleitung und den “Launcher” zu verwenden, nur um mit dem Setup zu spielen – ohne Erfolg (bis auf eine ziemlich alberne Prüfung, ob der Benutzer root ist, was nur Probleme verursacht).

Ich habe mich dann dem Bitnami-Image (und seiner vorgeschlagenen Compose-Datei) von https://hub.docker.com/r/bitnami/discourse zugewandt und nach einem docker compose up (und einer Reihe von SQL-Fehlern [was nichts Gutes verheißt] sowie Warnungen von Ruby [gleicher Vorbehalt]) hatte ich eine laufende Instanz von Discourse:

Reine Konvolut und “nicht-standardmäßige Magie”…

Also noch einmal – warum gibt es kein reguläres Image?

Beim Durchsuchen von Quellen und Repositories habe ich festgestellt, dass das Basis-Image verwendet wird (https://hub.docker.com/r/discourse/base/), obwohl mich die Versionierung/Tagging überrascht hat (https://hub.docker.com/r/discourse/base/tags)… Gibt es keine sinnvollen Versionen, habe ich mich gefragt? Und tatsächlich schien es beim Blick auf das Haupt-Repository keine Releases zu geben, aber hey – zumindest gibt es ordnungsgemäß getaggte Versionen (Tags · discourse/discourse · GitHub).

Nun fragt man sich – warum gibt es keine entsprechenden Images im Haupt-Docker-Hub?

Also ja – wenn man sich ansieht, wie die Dinge organisiert sind, stimme ich zu:

:smiley:


Auf der anderen Seite (oder besser gesagt: “wie Dinge sein sollten”) ein Beispielprojekt (kleiner im Umfang, aber die Begründung bleibt): GitHub - miniflux/v2: Minimalist and opinionated feed reader.

Es hat sinnvolle Releases: Releases · miniflux/v2 · GitHub

Welche entsprechende Images korrekt getaggt haben: https://hub.docker.com/r/miniflux/miniflux/tags

Und dann ist das Upgrade nur das Wechseln der Version von x auf y (oder die Verwendung des latest-Tags, sodass ein einfaches stop/pull/start die aktualisierte Version liefert (die alle erforderlichen Migrationen automatisch ausführt).

(Oh, und das Image ist etwa 70x kleiner, aber das ist eine andere Geschichte)

Gut gemacht!

Nur zwei Fragen… was sind SQL-Fehler und Ruby-Warnungen? Damit bin ich nicht vertraut. Aber vielleicht liegt es daran, dass ich Docker und Zeug völlig falsch benutzt habe :thinking:

Sie machen so etwas:

./launcher bootstrap myimage
# der Befehl, der dieses Image an Ihren bevorzugten Ort zum Starten von Images pusht
./launcher start-cmd

und das gibt Ihnen die Umgebungsvariablen, die Sie zum Starten Ihres Images festlegen müssen.

Es ist wirklich nicht so schwer. Sie können es sogar in eine GitHub-Aktion integrieren, damit es Ihr Image erstellt und in Ihr Docker-Repository pusht. Wenn man sich die Commits zu docker_compose ansieht, scheint es Bestrebungen zu geben, ein Image zu produzieren, das nicht gebootstrapped werden muss, oder es zumindest einfacher zu machen, einige der erforderlichen Dinge zu erledigen (Datenbank migrieren, Assets vorkompilieren und nach S3 pushen usw.). Ich habe dies für Kunden getan, die k8s oder das AWS Image-Launcher-Ding (ich erinnere mich nicht an den Namen) verwenden wollten.

Ein paar Mal habe ich darüber nachgedacht, solche vorgefertigten Images als Dienst anzubieten, aber nie jemanden gefunden, der dafür bezahlen wollte.

Aber es gibt eine Reihe von kleinen Teilen. Soweit ich weiß, verwendet CDCK den Launcher zum Erstellen von Images, aber sie starten und verwalten sie mit anderen Tools, genau wie Sie es möchten. Und als sie anfingen, war docker-compose noch keine gute Möglichkeit, dies zu tun, und als es das war, hatten sie den Launcher bereits zum Laufen gebracht, sodass es keine wirkliche Option war, alle vom Launcher zu etwas anderem zu migrieren.

Wenn die Bitnami-Images für Sie funktionieren, dann verwenden Sie sie, aber wenn nicht, müssen Sie Hilfe von jemandem bekommen, der sie verwendet, und das sind hier hauptsächlich niemand.

2 „Gefällt mir“

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

Das ist ein ausgezeichneter Punkt. Es gibt eigentlich keinen guten Grund, warum dieses Skript nicht als Nicht-Root ausgeführt werden kann.

Das Setup-Skript ist das einzige, das wirklich Root benötigt, für den beängstigenden Teil, wo es vorschlägt, das Docker-Installationsskript aus dem Internet auszuführen. Also kann selbst das geändert werden, um als Nicht-Root ausgeführt zu werden.

Das Launcher-Skript benötigt kein Root, es benötigt nur Schreibzugriff auf /var/discourse und die Berechtigung, Docker-Container zu verwalten.

1 „Gefällt mir“

Äh… :slight_smile:

Das Skript benötigt nicht einmal Zugriff auf /var/discourse (warum auch?).

Das gesamte Problem ergibt sich aus ein paar Dingen:

  1. Großes Missverständnis darüber, was Docker ist, wie es funktioniert und was es ermöglicht
  2. Verknüpfung der Vorstellung, dass Docker = Docker-Compose (ist es nicht!)

Sie können eine vollständig in sich geschlossene Einrichtung haben, die die Host-Umgebung praktisch nicht berührt…

Nach einigem Nachforschen scheint es, dass das gesamte “Setup”-Skript erstellt wurde, um die Installation für die absolut nicht-technische Person so einfach wie möglich zu gestalten. Es prüft, leitet den Benutzer an und richtet alles ein. Das mag eine nette Sache sein, aber es bricht vollständig zusammen, wenn man versucht, auch nur den kleinsten Schritt vom vorgesehenen Weg abzuweichen.

Bei der grundlegendsten Einrichtung benötigen Sie möglicherweise nicht einmal Zugriff auf Host-Verzeichnisse – alles wird in einer begrenzten Umgebung enthalten sein (das Image wird verwendet, um den Container zu erstellen, und der gesamte erforderliche Speicher wird über Docker-Volumes verwaltet [es gibt Probleme, wenn Sie woanders migrieren oder auf die Dateien zugreifen möchten, aber wir sprechen hier von den Grundlagen]).

Es versucht auch sicherzustellen, dass DNS korrekt ist, versucht, Zertifikate, Reverse-Proxy, SMTP und dergleichen einzurichten – wieder, völlig in Ordnung, diese einfache Einrichtung bereitzustellen.

ABER!

Das Problem ist NICHT, das wegzuwerfen, sondern ZUSÄTZLICH ein reines Docker-Image bereitzustellen (es ist bereits vorhanden, es wird von den Skripten und Vorlagen verwendet, die das Skript verwendet! discourse_docker/templates/postgres.template.yml at main · discourse/discourse_docker · GitHub & discourse_docker/launcher at main · discourse/discourse_docker · GitHub) mit

  1. ordnungsgemäßer Versionierung: Sie kennzeichnen das Image mit der veröffentlichten Discourse-Version (3.4.5 oder was auch immer)
  2. vernünftiger, einfacher Dokumentation der erwarteten Umgebungsvariablen (die die Datenbank-/Redis-/etc.-Konnektivität steuern) und möglicher Pfade/Volumes, die auf den Host gemountet werden können.

Nur das…

Werfen Sie einen Blick auf den oben genannten Miniflux-Leitfaden: Miniflux Installation with Docker – er gibt Ihnen Details über das Image (und welche Repositories sie bereitstellen) und mögliche Umgebungsvariablen zur Konfiguration.
Oder das MySQL-Docker-Image: https://hub.docker.com/_/mysql – dasselbe – ein Leitfaden, der erklärt, was konfiguriert werden kann (siehe insbesondere den Abschnitt: “Umgebungsvariablen”).

Niemand sagt: “Sie müssen den MySQL-Launcher verwenden, um das MySQL-Image zu erstellen, damit Sie es verwenden können”, oder Redis übrigens – in diesem Fall verwenden Sie einfach vorhandene Images, und das ist der Hinweis und der Kern der Verwendung von Docker. Doch im Fall von Discourse ist dies plötzlich eine “schlechte” Lösung und alle rufen: “Sie müssen Ihr eigenes Image erstellen!” – warum!?

Nein. Wegen Plugins.

1 „Gefällt mir“

Ähm … ich musste ein wenig über Plugins recherchieren und muss wieder sagen/zitieren:

:smiley:

Also, was ich getan habe - ich ging zum Plugin-Bereich, klickte auf das erste Plugin, suchte nach Anweisungen und Installationsanleitungen (Plugin directory | Discourse - Civilized DiscussionSign in with Apple | Discourse - Civilized DiscussionDiscourse Apple AuthenticationInstall plugins on a self-hosted site) und … mein Gott - was für ein verschlungenes “Durcheinander”.

Warum zum Teufel braucht man ein neues Image, nur um Plugins zu haben? Mit Docker kann man einfach ein Mount-Verzeichnis für Plugins angeben und es dort platzieren …

Ich bin kein Ruby-Typ, daher sind die Dinge hier vielleicht seltsamer, aber zum Beispiel in der Java-Welt wirft man einfach ein jar mit dem Plugin hinein, damit es geladen wird, und voilà - man hat es laufen. Und man benutzt dasselbe Image wie alle anderen …

(Ich sage nicht, dass es nicht unordentlich ist, ich erkläre nur, warum die Dinge so sind, wie sie sind)

Wegen der Ember-Asset-Pipeline.

Was auch unordentlich wäre, weil man diese Abhängigkeiten nicht extern haben möchte.

2 „Gefällt mir“

Dieses hier: GitHub - ember-engines/ember-asset-loader: Asset loading support for Ember applications?

Warum nicht?

Plugins können on the fly verarbeitet werden, dies geschieht auch beim Upgrade eines Plugins. Mit ein wenig Magie kann man auch ein neues Plugin zu einer laufenden Instanz hinzufügen, ohne den Container neu zu erstellen. Das Mounten eines Plugin-Volumes in einen Container sollte also möglich sein (mit einer Reihe von Änderungen).

Das Hauptproblem, das ich sehe, ist das Upgrade von Discourse. Dies kann derzeit mit einer laufenden Instanz erfolgen. Das Upgrade baut den Discourse im Grunde neu auf. Wenn Discourse tatsächlich aus einem vorab erstellten Image stammt, können Sie diese Dateien nicht ändern. Daher wird ein Upgrade mit null/geringer Ausfallzeit wahrscheinlich einiges an Arbeit erfordern.

Das ist etwas, das ich nicht verstehe (wahrscheinlich fehlt mir der Kontext in Bezug auf Ruby…).

Im Allgemeinen können Sie mit Docker/Containern/Orchestrierung Blue-Green/Red-Black-Deployments durchführen, bei denen Sie einen neuen Container mit einer neuen Version vorbereiten und den Datenverkehr umschalten, sobald er fertig ist. Im Allgemeinen sollte dies jedoch bei kleineren Bereitstellungen kein Problem darstellen, da der Start des Dienstes (Containers) meist nur wenige Sekunden dauert, sodass die Ausfallzeit beim Wechsel der Versionen minimal sein sollte (das größte Problem ist, dass Schema-Upgrades ausgeführt werden müssen, aber das gilt unabhängig davon, ob Sie das Image neu erstellen oder nicht).

Ja, aber so funktioniert es derzeit nicht, daher muss dieser Teil überarbeitet werden. Wie werden Sie das innerhalb der Discourse-Admin-Oberfläche tun? Wie werden Sie den blauen Container herunterskalieren, während Sie den grünen Container hochfahren (Systeme haben keine unendlichen Ressourcen, daher möchten Sie vor dem Start von Blau die Unicorn-Worker in Grün reduzieren). Oder Sie können einfach so vorgehen: Grün ist ausgefallen, und jetzt startet Blau.

Es gibt viele Dinge, die geklärt und umgesetzt werden müssen. Sowohl aus technischer Sicht als auch aus der Sicht eines Administrators. Das Ein-Klick-Upgrade innerhalb der Admin-Oberfläche ist eine wertvolle Funktion.

1 „Gefällt mir“

Plugins und benutzerdefinierte Images müssen noch erstellt werden, aber für das Vanilla-Building für Compose rückt dies heutzutage in greifbare Nähe – ich habe hier ein kleines Proof-of-Concept-Experiment hier für alle Neugierigen gemacht.

Da dies alles meine Repos sind (nicht die von Discourse™), ist dies natürlich nichts Offizielles, daher können Sie variieren, und erwarten Sie definitiv keine offizielle Unterstützung :dragon: Ich werfe das hier rein, da erwähnt wurde, dass Leute bereits Bitnami und andere nicht sanktionierte Wege zum Ausführen verwenden.

Die fertigen Postgres-Images (oder pgvector) funktionieren nicht für Discourse – Discourse muss die Standardkonfiguration ändern, sich nicht über einen Superuser verbinden, Locales unterstützen und Postgres-Upgrades unterstützen, ohne dass ein Discourse-Administrator Dump/Restore durchführen muss.

4 „Gefällt mir“

Äh … das ist, glaube ich, der entscheidende Unterschied, und dieses „Update aus der Admin-Oberfläche“ erinnert irgendwie an alte Zeiten, als man nur „Webhosting“ mit einem PHP-Interpreter hatte, sodass alles um diese Vorstellung herum aufgebaut war. Und ich denke, das hat sich darauf übertragen, wie Discourse funktioniert und verwaltet werden soll.

Nun, das ist eine weitere Sache, die mir aufgefallen ist – Discourse ist ziemlich ressourcenintensiv (der Container begann, Ressourcen während des Starts in beängstigendem Umfang zu verbrauchen), also ja – das könnte ein Problem sein.

Wie werden diese im Kontext von Ruby „gebaut“ (was größtenteils eine interpretierte und keine kompilierte Sprache ist)?

Wäre es nicht besser, fertige Lösungen zu verwenden? Selbst für die Postgres-Konfiguration kann diese einfach geändert werden, indem man einfach eine benutzerdefinierte postgresql.conf-Datei bereitstellt/einhängt, keine komplett benutzerdefinierte Image mit eingebauter Konfiguration erforderlich ist … und selbst dann – wenn das erforderlich ist, könnte Discourse ein solches vorab erstelltes Image bereitstellen, das nur heruntergeladen und nicht jedes Mal neu erstellt werden müsste…

Diese „Admin-Upgrade-Oberfläche“ ist ein Plugin (genannt „docker manager“). Sie müssen es nicht einbeziehen, wenn Sie eine andere Möglichkeit für Online-Updates haben.