Discourse 是否可以频繁发布无需引导的 Docker 镜像?

我相信该启动器是在 Docker Compose 出现之前构建的:

1 个赞

Docker compose 不具备所需的功能。Discourse 的 docker 文件模板构建允许灵活的 docker 结果。使用 compose,你只有一套可能的固定 Dockerfiles,这可能导致大量容器。

在我的 Discourse 设置中,我使用一个容器,其中 Discourse 和 nginx 使用 UNIX 套接字。PostgreSQL 和 Redis 是主机上的服务。这与默认设置有很大不同,但它是开箱即用的。

使用 compose 部分可行,也许可以通过那个设计不佳的 profile 功能来实现。但即使那样,它也很混乱。或者你需要为每种变体提供不同的 compose 文件。

你只是在转移问题。

一个干净的 Discourse compose 设置将是以下服务在单独的容器中:

  • Discourse
  • nginx
  • PostgreSQL
  • Redis

Discourse 和 nginx 需要共享一个卷,这没什么大不了的。

PostgreSQL 和 Redis……这些是你可能想托管在别处的东西,而不是为它们提供一个 Discourse 特定的容器。现在 docker compose 成了一个问题 docker compose up -d 将会启动你不需要的 PostgreSQL。好的,所以我们将其设置为 docker compose --profile postgresql up -d 来启动基本的 discourse 设置和一个 postgresql 容器。对于“完整”的自包含 Discourse 容器设置,使用 docker compose --profile postgresql --profile redis up -d。你最好不要忘记 --profile ... 参数,否则你会遇到更多问题。

所以为了更好的用户体验,你创建一个启动器来负责创建所需的 docker compose 命令。现在我们又回到了原点。除了对 nginx 容器的修改还不可能实现。所以我需要一个 nginx-http 容器和一个 nginx-unix 容器,它们应该是互斥的吗?……

当然,插件管理可以做得更好,但用 docker compose 来做这件事,那将是地狱。

1 个赞

所以,总结一下。不会有真正的 Docker 镜像。

至于对 Docker 是什么以及它是如何工作的令人难以置信的错误知识:What is Docker? | Docker Docs

你可以在工作时共享容器,并确保你共享的每个人都能获得相同的、以相同方式运行的容器。

另外——有了那个备受喜爱的“启动器”——如果我无法使用 Docker 镜像并在 k8s 集群上运行 Discourse,我该如何做到?

好吧……

必须以 root 用户身份运行此脚本。请先使用 sudo 或登录为 root。

不,谢谢。我不喜欢运行来自互联网的随机脚本。我只想拥有一个可以安全地在隔离环境中运行的漂亮 Docker 镜像 :slight_smile:

我已经成功地使用 Docker Compose 和已发布的镜像将 Discourse 部署到了生产环境,客户也是如此。

然而,是的,这很混乱,并且涉及相当多的定制工作。

除非你真的必须使用不同的方法,因为你有自己的观点、特定的架构或其他特殊要求,否则坚持使用 CDCK 启动器的标准安装会容易得多。

1 个赞

使用非向导式的“牵着我的手”的方法并不是“主观的、特定的或特殊的” :roll_eyes:

无论如何——线索是使用 Discourse 的原始 Docker 镜像。就这么简单。

我尝试使用官方指南和“启动器”来摆弄设置——但没有成功(除了一个非常愚蠢的检查用户是否为 root 的操作,这只会带来问题)。

然后我转向了 Bitnami 镜像(以及他们建议的 Compose 文件),来自 https://hub.docker.com/r/bitnami/discourse,在运行了一个 docker compose up 命令后(以及一堆 SQL 错误 [这不祥兆] 和 Ruby 的警告 [同理]),我运行了一个 Discourse 实例:

纯粹是曲折和“非标准的魔法”……

所以,再说一遍——为什么没有常规镜像?

通过查看源代码和存储库,我发现使用了基础镜像(https://hub.docker.com/r/discourse/base/),尽管它的版本控制/标记让我感到惊讶(https://hub.docker.com/r/discourse/base/tags)……我奇怪为什么没有合理的版本?确实,查看主存储库似乎没有任何发布,但嘿——至少有正确标记的版本(https://github.com/discourse/discourse/tags)。

现在有人想知道——为什么主 Docker Hub 中没有匹配的镜像?

所以,是的——看看事情的组织方式,我同意:

:smiley:


另一方面(或者更确切地说:“事情应该如何进行”),示例项目(范围较小,但理由是相同的):https://github.com/miniflux/v2。

它有合理的发布:Releases · miniflux/v2 · GitHub

并且有相应正确标记的镜像:https://hub.docker.com/r/miniflux/miniflux/tags

然后升级只是将版本从 x 切换到 y(或者使用 latest 标签,这样简单的 stop/pull/start 就会提供更新的版本(它会自动运行所有必需的迁移))。

(哦,而且镜像小了大约 70 倍,但这又是另一回事了)

干得好!

只有两个问题……什么是 SQL 错误和 ruby 警告?我对此不熟悉。但也许是因为我完全错误地使用了 docker 和其他东西 :thinking:

你可以这样做:

./launcher bootstrap myimage
# 将该镜像推送到你首选的镜像启动位置的命令
./launcher start-cmd

这会为你提供启动镜像所需的 ENV 变量。

这真的不难。你甚至可以将其集成到 GitHub Actions 中,以便它构建你的镜像并将其推送到你的 docker-repo thingy。查看 docker_compose 的提交记录,似乎正在努力生成一个无需引导的镜像,或者至少使其更容易完成一些必需的任务(迁移数据库、预编译资源并推送到 s3 等)。我已经为希望使用 k8s 或 AWS 镜像启动器 thingy(我不记得它的名字了)的客户完成了这项工作。

我曾几次考虑提供这种预构建镜像作为服务,但从未找到愿意为此付费的人。

但这里有很多零散的部分。据我所知,CDCK 使用启动器来构建镜像,但他们使用其他工具来启动和管理它们,就像你想要的那样。当他们开始时,docker-compose 还不是一个不错的选择,等到它成为一个不错的选择时,他们已经让启动器工作了,所以从启动器迁移到其他东西并不是一个真正的选择。

如果 bitnami 镜像对你有用,那就使用它们,但如果它们不起作用,你将需要获得使用它们的人的帮助,而这里的大多数人都不使用它们。

2 个赞

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

这是一个很好的观点。这个脚本实际上并没有什么好理由不能以非 root 用户身份运行。

设置脚本是唯一真正需要 root 权限的脚本,因为它涉及从互联网执行 docker 安装脚本的危险部分。所以即使是那个也可以更改为以非 root 用户身份执行。

启动脚本不需要 root 权限,它只需要对 /var/discourse 的写入访问权限以及管理 docker 容器的权限。

1 个赞

嗯…… :slight_smile:

脚本甚至不需要访问 /var/discourse(为什么需要?!)。

整个问题源于几件事:

  1. 对 docker 是什么、它是如何工作的以及它提供了什么功能存在巨大的误解
  2. 将 docker 和 docker-compose 的概念混为一谈(它们不一样!)

你可以拥有一个完全隔离的设置,它几乎不接触主机环境……

经过大量的研究,似乎整个“设置”脚本是为了让非常不熟悉技术的人能够尽可能简单地进行安装而创建的。它会进行检查,指导用户并设置好一切。这可能是一件好事,但它在任何试图偏离设想路径哪怕一丁点的情况下都会完全失效。

在最基本的设置中,你甚至可能不需要访问任何主机目录——所有内容都将包含在有限的环境中(镜像将用于创建容器,所有必需的存储都将通过 docker 卷处理 [当你想要迁移到其他地方或访问文件时会存在问题,但我们现在讨论的是基础知识])。

它还试图确保 DNS 正确,尝试设置证书、反向代理、SMTP 等等——同样,提供这种简单的设置是完全没问题的。

但是!

问题不在于放弃这些,而是 另外 提供一个纯粹的 docker 镜像(它已经存在了,脚本和脚本使用的模板都在使用它!discourse_docker/templates/postgres.template.yml at main · discourse/discourse_docker · GitHubdiscourse_docker/launcher at main · discourse/discourse_docker · GitHub

  1. 正确的版本控制:将镜像标记为已发布的 discourse 版本(3.4.5 或其他)
  2. 对预期的环境变量(驱动数据库/redis/etc 连接)以及可以挂载到主机的可能路径/卷的合理、简单的文档。

仅此而已……

看看上面提到的 miniflux 指南:Miniflux Installation with Docker - 它提供了关于镜像(以及哪些仓库提供它们)和可配置的环境变量的详细信息。
或者 MySQL docker 镜像:https://hub.docker.com/_/mysql - 同样 - 提供了一个解释可配置内容的指南(特别是查看“环境变量”部分)。

没有人会说:“你必须使用 mysql 启动器来构建 mysql 镜像才能使用它”,或者 Redis 也是如此——在这种情况下,你只需使用现有的镜像,这就是使用 docker 的关键和要点。然而,在 discourse 的情况下,突然之间这变成了一个“坏”的解决方案,每个人都在喊:“你必须构建自己的镜像!”——为什么?!

不。因为插件。

1 个赞

嗯……我不得不花点时间研究了一下插件,再次不得不说/引用:

:smiley:

所以我做了——去了插件部分,点击了第一个看起来像说明和安装指南的插件(Plugin directory | Discourse - Civilized DiscussionSign in with Apple | Discourse - Civilized DiscussionDiscourse Apple Authenticationhttps://meta.discourse.org/t/install-plugins-on-a-self-hosted-site/19157),然后……我的天啊——多么令人费解的“一团糟”。

为什么你需要一个新镜像才能使用插件?使用 docker 你可以只指定一个插件的挂载目录,然后把它放在那里……

我不是 Ruby 开发者,所以事情在这里可能更奇怪,但例如在 Java 世界里,你只需要丢一个包含插件的 jar 文件,它就会被加载,然后你就有了运行的插件。而且你使用的是和大家一样的镜像……

(并非说它不混乱,只是解释一下事情为什么是这样)

因为 Ember 资产管道。

这也会很混乱,因为您不希望将这些依赖项放在外部。

2 个赞

这个吗:GitHub - ember-engines/ember-asset-loader: Asset loading support for Ember applications?

为什么不行呢?

插件可以动态处理,升级插件时也是如此。通过一些技巧,您还可以在不重新构建容器的情况下向运行实例添加新插件。因此,挂载插件卷到容器应该是可行的(需要进行大量更改)。

我看到的主要问题在于升级 Discourse。目前可以对运行实例进行此操作。升级基本上会重新构建 Discourse。如果 Discourse 实际上来自预构建镜像,您将无法更改这些文件。因此,实现零停机/极少停机升级可能需要大量工作。

这是我不明白的一点(可能是在 Ruby 方面缺少上下文……)。

通常,使用 docker/容器/编排,您可以进行蓝绿/红黑部署,即准备一个带有新版本的新容器,并在其准备就绪后切换流量。但是,对于较小的部署来说,这通常不是问题,因为大多数时候服务(容器)启动只需要几秒钟,因此切换版本的停机时间应该很短(最大的问题是必须运行模式升级,但这无论您是否重新构建映像都适用)。

是的,但目前并非如此工作,所以这部分需要改进。你打算如何从 Discourse 管理界面内部进行此操作?你打算如何在启动绿色容器的同时缩减蓝色容器(系统资源并非无限,因此在启动蓝色容器之前,你需要减少绿色容器中的 unicorn 工作进程。)或者你也可以直接让绿色容器下线,然后启动蓝色容器。

有很多事情需要弄清楚并解决。无论是从技术角度还是从管理员角度来看。从管理界面进行一键升级是一个有价值的功能。

1 个赞

插件和自定义镜像仍需构建,但对于原生 Compose 构建而言,在这些日子里已触手可及——我在这里做了一个小概念验证实验 here,供有兴趣的人参考。

显然,由于这些都是我的仓库(不是 Discourse 的™),这并非官方内容,因此您的体验可能有所不同,并且绝对不要期望获得官方支持 :dragon: 我在这里发布它,因为有人提到大家已经在运行 bitnami 和其他非官方的运行方式。

现成的 postgres(或 pgvector)镜像不适用于 Discourse——Discourse 需要更改默认配置,不通过超级用户连接,支持区域设置,并且需要在无需 Discourse 管理员进行转储/恢复的情况下支持 postgres 升级。

4 个赞

嗯……我认为这是关键区别所在,“从管理界面更新”有点让人回想起过去,那时你只有“网络托管”和 PHP 解释器,所以一切都围绕这个概念构建。我认为这延续到了 Discourse 的工作方式以及人们期望的管理方式。

嗯,这是我注意到的另一件事——Discourse 非常消耗资源(容器在启动时就开始以惊人的速度消耗资源),所以是的——这可能是一个问题。

在 Ruby(这是一种主要是解释型而非编译型语言)的上下文中,这些是如何“构建”的?

尝试使用现成的解决方案难道不是更好吗?即使是 postgres 配置,也可以通过简单地提供/挂载自定义 postgresql.conf 文件来轻松更改,无需完全自定义镜像并烘焙配置……甚至——如果需要,Discourse 可以提供这样的预构建镜像,只需拉取而不是每次都重新构建……

这个“管理员升级界面”是一个插件(称为“docker manager”)。如果你有其他在线更新方式,则无需包含它。