警告: 如果您不习惯担任 Linux 系统管理员,且没有使用 Docker 容器的经验,迁移到多容器部署将会给您带来困难。届时,工作人员和志愿者将合理地要求您回退到由
launcher脚本完全管理的独立单容器部署。如果您迁移到多容器部署且系统因此崩溃,您很可能会面临“两个坏部件都得留着”的局面。如果您阅读了下面的说明,却感觉像是在施展魔法,而不是在阐明容器内部的实际运作方式,那么请立刻前往最近的默认独立部署,这将是您为自己做的一件好事。
从单容器部署迁移到多容器部署的推荐方法 本质上如下:
- 备份您的 Discourse
- 彻底删除所有内容
- 从头开始使用多容器部署
- 恢复您的备份
如果您像我一样拥有一个需要数小时才能恢复的大型站点,您可能会想知道是否有更快的方法。无需再想!我从独立部署迁移到包含 Web、数据和 Redis 的三容器部署所花费的时间,甚至比通常对该站点执行 ./launcher rebuild app 的时间还要短。(总停机时间为 12 分钟,而重建应用有时需要 30 分钟以上。)根据我的经验,未来我会建议将 Redis 与 Postgres 保留在单个 data 容器中。
如果您这样做,您就需要自行负责了解何时需要重建其他容器(数据容器,以及如果您像我一样愚蠢地分离了 Redis,则还包括 Redis 容器)。 您将不再能通过 ./launcher rebuild app 免费获得所有组件的升级——如果您没有资源来管理此过程,请使用独立部署或购买托管 Discourse 服务。
测试
除非在阅读本文后,您同时也明白了如何从多容器快速迁移回单容器,否则请勿使用此过程迁移到多容器。如果阅读后这还不明显,那么这篇文章的技术含量就足够高(即“与魔法无异”),您可能无法识别此过程是否在中间步骤出错了,从而导致您得到一个很久之后才意识到的损坏的 Discourse。如果发生这种情况,您就得“两个坏部件都得留着”了。正如人们常说的:弄坏了,就得负责!
备份
首先进行备份,并先开启缩略图备份,这样在恢复时就不需要重新生成它们。如果您在此处出错,很容易陷入一种境地,即最简单、最安全且最快的恢复方式是切换回正常方法。请随时准备在出现问题时回退到 推荐方法。
下载您的备份。下面的命令涉及在 Discourse 数据中移动文件,如果您出错,可能会删除您的备份。所以请下载它。此外,如果您的备份不包含上传文件,请也备份它们。它们也位于您将要移动文件的位置。
说真的,请务必备份。
当我执行此操作时,首先我进行了备份,然后进行了远程系统备份,之后才继续下一步。
设置新的多容器配置
您至少需要 containers/web_only.yml 和 containers/data.yml,如果您还想分离 Redis,还需要 containers/redis.yml。首先将 samples/data.yml(以及可选的 samples/redis.yml)复制到 containers/ 目录。
如果您单独部署 Redis,请从 containers/data.yml 文件顶部移除 Redis 模板。(但如果没有充分理由请不要这样做;这只是额外的工作。)
您有两种创建 web_only.yml 的方法。
- 将
samples/web_only.yml复制到containers/;然后将两者与containers/app.yml进行比较,在您的新containers/data.yml中保留params:中的任何 Postgres 配置
- 将
containers/app.yml中 Postgres 的任何params:复制到containers/data.yml - 创建一个唯一的密码来替换
SOME_SECRET
- 或者,将
containers/app.yml复制到containers/web_only.yml并将其与samples/web_only.yml进行比较
- 移除任何对 Postgres 和 Redis 模板的引用
- 移除仅包含 Postgres 设置的整个
params:部分 - 添加
links:部分,内容完全照搬samples/web_only.yml或根据您的情况进行修改(见下文,如果您将 Redis 部署在单独的容器中) - 从
samples/web_only.yml添加数据库部分,并创建一个唯一的密码来替换SOME_SECRET - 将卷定义从
standalone更改为web_only
如果您将 Redis 分离到其自己的容器中,而不是使用将其与 Postgres 捆绑在数据容器中的合理默认设置,请使用以下 links: 部分:
# 使用 'links' 键将容器链接在一起,即使用 Docker --link 标志。
links:
- link:
name: data
alias: data
- link:
name: redis
alias: redis
如果您将 Redis 和 Postgres 容器合并为单个数据容器,则不需要 redis 链接;这里展示的是如果您需要分离时应做的操作。
以下是 samples/data.yml 中 env 里当前的 Postgres 设置副本,您需要在此处更改 SOME_SECRET:
## TODO: 配置数据库连接
DISCOURSE_DB_SOCKET: ''
#DISCOURSE_DB_USERNAME: discourse
DISCOURSE_DB_PASSWORD: SOME_SECRET
DISCOURSE_DB_HOST: data
## 如果您使用单个 data+redis 容器,以下内容将是 "data"
DISCOURSE_REDIS_HOST: redis
请注意,对于正常部署(非多站点),您不需要修改任何其他行。DISCOURSE_DB_SOCKET 是用于 Postgres 的 Unix 域套接字,它不是端口号。
以下是 web_only.yml 末尾卷定义变更的示例,如果您是从 app.yml 而不是 samples/web_only.yml 复制该文件,则需要使用此变更:
@@ -75,10 +80,10 @@
## Docker 容器是无状态的;所有数据都存储在 /shared 中
volumes:
- volume:
- host: /var/discourse/shared/standalone
+ host: /var/discourse/shared/web_only
guest: /shared
- volume:
- host: /var/discourse/shared/standalone/log/var-log
+ host: /var/discourse/shared/web_only/log/var-log
guest: /var/log
现在,在 containers/data.yml 中设置与 containers/web_only.yml 中使用的相同秘密密码,替换 SOME_SECRET。
现在您已准备好进行迁移。
现在,在您尝试快速迁移之前,请进行并下载您的最终备份。 请记住,如果此处出现任何问题,请立即前往 推荐方法。我再怎么强调这一点都不为过。
分离数据(Postgres)和 Redis 容器:
cd /var/discourse
./launcher stop app
cd shared
mkdir data
mkdir redis
mv standalone/postgres_* data/
mv standalone/redis_data/ redis/
mv standalone web_only
mkdir -p data/log/var-log
mkdir -p redis/log/var-log
cd ..
./launcher destroy app
./launcher bootstrap data
./launcher bootstrap redis
./launcher start redis
./launcher start data
./launcher bootstrap web_only
./launcher start web_only
合并 Postgres+Redis 数据容器:
cd /var/discourse
./launcher stop app
cd shared
mkdir data
mv standalone/postgres_* data/
mv standalone/redis_data/ data/
mv standalone web_only
mkdir -p data/log/var-log
cd ..
./launcher destroy app
./launcher bootstrap data
./launcher start data
./launcher bootstrap web_only
./launcher start web_only
另外请注意,如果您之前设置过外部 Nginx,则需要更改 proxy_pass 路径以匹配新的 web_only 套接字位置;例如从 http://unix:/var/discourse/shared/standalone/nginx.http.sock: 更改为 http://unix:/var/discourse/shared/web_only/nginx.http.sock:。
对我来说,在拥有 2 核 CPU、4GB RAM 的虚拟机上,对于一个没有下载内容、备份大小为 600MB 的站点,此过程导致的停机时间为 12 分钟。您的情况可能有所不同。
请注意,到目前为止,这些操作都没有更新 launcher。您可能不是最新版本。(例如,我在 Postgres 12 更新可用之后但在应用之前运行了此操作。此过程使我的 Postgres 版本停留在 10。然后我做的第一件事就是重建数据应用,这更新了 launcher 并成功带我完成了 Postgres 12 更新过程。)
未来更新时该做什么
在此迁移之后,如果您需要更新 Redis 或数据,首先需要停止 Web 应用。操作如下:
./launcher stop web_only
./launcher rebuild data # 和/或 redis
./launcher rebuild web_only
请注意,如果您重建 data(或 postgres,或 redis)容器,则需要创建一个新的 Web 容器以将其与新数据容器重新连接。您可以通过重建 web_only 来实现,或者,如果您认为不需要重建它,执行 ./launcher destroy web_only; ./launcher start web_only 即可(如果您收到关于“缺少数据容器”或类似的错误,这就是您需要做的)。
然而,当 Postgres 和 Redis 都不需要更新时,不重建这些容器会快得多,大多数应用重建只需 ./launcher rebuild web_only。
或者,为了进一步减少停机时间(据报告在 15 秒到 2 分钟之间):
./launcher bootstrap web_only
./launcher destroy web_only && ./launcher start web_only
再次强调,通过迁移到多容器部署,跟踪何时进行更新现在是您的工作。 您会在管理控制台中收到有关更新的通知,但它们仅适用于 web_only 容器。没有任何提示会告诉您何时需要更新 Postgres 或 Redis。如果您这样做,请在每次版本升级之前阅读 公告类别,并在每次升级到或经过的新版本时阅读 发布说明。也就是说,如果您跳过了某个版本更新,请不要跳过阅读您跳过的该版本的发布说明。(考虑在发布说明上设置关注,或将您的阅读器订阅到 https://meta.discourse.org/tag/release-notes.rss 以保持最新。)
请注意,重建 web_only 容器要求数据库正在运行,因此您无法通过并行重建所有两个或三个容器来加快速度。如果您打算每次都重建所有容器,请坚持使用标准的推荐独立部署;这比同时管理多个容器要快。
备份审查
如果您将上传文件与数据库分开备份,我希望您有一个基于文件的远程备份机制用于上传文件,以便在发生灾难时将其备份并恢复。
审查您的远程备份实现,确保它会将 /var/discourse/shared/web_only 中的上传文件而不是 /var/discourse/shared/standalone 中的文件进行备份,以便在新的多容器实现中保持备份的更新。