如何备份和还原整个 /var/discourse 应用文件夹?

如何备份和还原整个 /var/discourse 文件夹?

由于常规的备份和还原过程存在问题,我在想是否可以直接备份整个 /var/discourse 文件夹,并在另一台服务器上复用。以下是我所做的操作……

在生产服务器上:

rsync_opts="\
   --recursive \
   --links \
   --hard-links \
   --safe-links \
   --owner \
   --group \
   --perms \
   --times \
   --delete \
   --sparse \
   --compress \
   --partial \
   --rsh=ssh
"
dir=/var/discourse
rsync  $rsync_opts "$dir/" root@xx.xx.xx.xx:"/var/production-backup/$dir"

在测试服务器上:

安装 Docker。

rsync --recursive --links --hard-links --safe-links --owner --group --perms --times --delete --sparse --compress --partial /var/production-backup/var/discourse/ /var/discourse

但遇到了 502 Bad Gateway 错误。

正在尝试排查。

cd /var/discourse

./launcher start app

root@whonix-app:/var/www/discourse# service postgresql status
12/main (port 5432): down
root@whonix-app:/var/www/discourse# service postgresql start
[....] 正在启动 PostgreSQL 12 数据库服务器:main[....] 错误:该集群由不存在的用户 ID 116 拥有 [FAIL] ... 失败!

猜测一些修复方法:

chown -R postgres.postgres /etc/postgresql
chown -R postgres.postgres /shared/postgres_*
chown -R postgres.postgres /var/lib/postgresql
chown -R postgres.postgres /var/log/postgresql
chown -R redis.redis /etc/redis/redis.conf
chown -R redis.redis /shared/redis_data
chown -R redis.redis /var/run/redis
chown -R redis.redis /var/lib/redis
chown -R redis.redis /var/log/redis
chgrp -R ssl-cert /etc/ssl/private

但并未奏效。

root@whonix-app:/var/www/discourse# service postgresql start
[....] 正在启动 PostgreSQL 12 数据库服务器:main[....] 错误:/usr/lib/postgresql/12/bin/pg_ctl /usr/lib/postgresql/12/bin/pg_ctl start -D /shared/postgres_data -l /var/log/postgresql/postgresql-12-main.log -s -o -c config_file="/etc/postgresql/12/main/postgresql.conf" 退出状态为 1: 2020-05-25 10:20:10.501 UTC [603] FATAL: 数据库文件与服务器不兼容 2020-05-25 10:20:10.501 UTC [603] DETAIL: 数据目录由 PostgreSQL 版本 10 初始化,与当前版本 12.2 (Debian 12.2-2.pgdg100+1) 不兼容。pg_ctl: 无法启动服务器。请检查日志输出。[FAIL] ... 失败!

为什么会出现这些文件权限问题?

为什么仅仅通过将一个服务器的整个文件夹复制到另一个服务器,PostgreSQL 就从版本 10 更新到了版本 12?我肯定哪里做错了。

能否请您分享如何在一台服务器上备份整个 Discourse 应用并将其迁移到另一台服务器的详细步骤?

Discourse 不使用 Phabricator 吗?

1 个赞

打错了,我指的是 Discourse。已修正拼写错误。原问题保持不变。

2 个赞

这并不会移动整个 /var/discourse 文件夹。我知道这些说明,但它们并不适用于我。因此,我想要一种更“完整”的 1 对 1“硬拷贝”方式来备份。

您可以关闭容器,并将整个容器复制到新服务器上,但需排除 tmp、backup 和 cache 目录(我想还有一个?)。这样应该可以。我最近也做过类似的操作,原因可能也差不多。

不过,您仍然需要彻底解决索引损坏的问题。

2 个赞

我认为 Docker 版本引入了差异。(这进而导致了失败。)

原服务器
docker-engine 17.05.0~ce-0~debian-stretch

对比更新的(预发布)服务器
docker-engine 17.05.0~ce-0~debian-stretch

这导致原服务器上的 PostgreSQL 版本为 10,而更新的(预发布)服务器上已经是 PostgreSQL 12。

这是必须的吗?有没有更简单的方法?为什么不能直接全部复制并恢复?

这会导致我无法解释的权限问题。理论上应该可以在不破坏权限的情况下进行复制。而且我也不确定是否已经完全修复了所有权限问题。

是的,但我认为,在我至少能够复现当前仍能正常运行的部分之前,贸然处理该问题会不太安全。

你不能简单地将 /var/discourse 目录打包(tar),然后移动到另一台机器上解包并启动 Discourse 应用。

主要原因之一是,当你构建/引导 Discourse 时(据我记忆,这是启动器做的事),它会检查是否存在基础的 Discourse 容器(镜像),如果不存在,就会拉取基础的 Discourse Docker 镜像,并将该基础 Docker 镜像启动为容器。

在完成基础 git pull 之后,构建过程会构建另一个 Docker 镜像(即应用镜像)。

这两个 Docker 镜像(基础镜像和应用镜像)并不存在于 /var/discourse 内部,因此将 /var/discourse 打包只是一种部分的“解决方案”(此处“解决方案”一词的使用较为宽松)。

这些 Discourse Docker 镜像是作为 Docker 镜像构建的,并作为 Docker 的一部分;它们并不“驻留”在 /var/discourse 中,而是在那里构建,然后作为 Docker 镜像移交给 Docker。

也许你可以编辑容器 yml 文件并从零开始重新构建,但更常规的做法是保存你的:

  • 容器 yml 文件
  • 包含上传文件的完整备份

然后编辑你的容器 yml 文件,克隆 discourse-docker 仓库并重新构建。

接着,从容器内的命令行恢复你的完整备份(包括上传文件)。

使用 GitHub 作为仓库是一种比旧式的 Unix 风格 方法(即“打包整个东西”并“将整个东西迁移”到另一台服务器)更干净的解决方案。然而,即使采用这种“旧式 Unix 方法”,通常也无法提供完整的解决方案,因为系统中往往存在共享库、共享库用户目录等,它们不属于分发目录;此外,还有一些位于发行版根目录之外的 etc 文件等。

因此,即使在大多数现代 Linux 系统上,我们也使用 apt(例如在 Ubuntu 上)来拉取仓库。就 Discourse Docker 而言,你拉取(并构建)的是 discourse-docker 以设置基础容器,并拉取另一个 Discourse 仓库来构建应用。因此,/var/discourse 是一个“构建位置”(用于构建镜像)和一个“共享位置”(用于存储数据、备份、公共静态文件等)。

希望这个总结能在某种程度上有所帮助。

2 个赞

当然,你可以用 rsync -rav 复制所有内容。

如果你将应用改为使用 PostgreSQL 10 模板,可能会更顺利。但听起来,最简单的办法可能还是直接修复现有的数据库。

4 个赞

可以移动该文件夹,它能正常工作。但这并不是首选方案,因为它绕过了 discourse-setup 及其沿途执行的任何调整或测试。

2 个赞

在我的情况下,这行不通,因为升级后的 Docker 导致 Docker 容器内的 PostgreSQL 版本更新,进而由于 PostgreSQL 迁移问题导致论坛无法使用。我不得不从 Postgres 模板改为 Postgres 10 模板。

How to backup and restore a whole /var/discourse app folder? - #8 by neounix 对此进行了详细解释。

我想我可能还需要备份和恢复 /var/docker 文件夹。但即便如此,由于以下原因,仍有失败的可能:

你正在钻牛角尖。
如果我是你,我会专注于解决你最初的备份/恢复问题。

4 个赞

也许甚至是一个 :rat: :rat: :rat: 的坑。

同意……绝对如此……

@adrelanos

备份/恢复过程没有任何“问题”。看看你本人 @neounix 几个月前在这个话题上写的这段“赞誉”:

1 个赞

尊敬的 @adrelanos

回到您上面第 1 条帖子中的原始问题,出于好奇心,我对之前的回复并不完全满意,因此今天进行了一些测试。

简而言之,我刚刚确认我们可以使用 docker save(针对基础容器和应用容器)以及 tar 命令来处理 /var/discourse 目录,从而完整地保存、转移(备份)并恢复应用程序。

我有 99.99% 的把握认为,这种方法并未得到官方支持,但您值得获得一个答案,所以我为您进行了测试:

基本上,步骤总结如下:

  1. 使用 docker save 保存您的容器。

例如,如果您运行的是独立应用,可以保存基础容器和应用容器,如下所示(基于您的配置):

docker save -o /tmp/my.discourse.docker.app.tar  discourse/base:2.0.20200512-1735

以及:

docker save -o /tmp/my.discourse.docker.app.tar local_discourse/app:latest  
  1. 您也可以像您提到的那样,将 /var/discourse 目录打包为 tar 文件:
cd /var/
tar -cvzf /tmp/my.var.discourse.tar.gz discourse

然后,如果您愿意,可以将 docker tar 文件压缩并归档:

gzip /tmp/my.discourse.docker*.tar
  1. … 随后,您可以将这些文件移动到另一台服务器,或在同一台服务器上进行归档,或者按您希望的任何方式操作。只需反向执行上述步骤,即可毫无问题地启动 Discourse 应用。

我通过实际操作确认了这一点:删除了所有容器镜像和 /var/discourse 目录。基本上,我清除了所有内容,并从备份中重新启动(由于域名未变更等原因,无需重新构建)。

例如,要恢复,您可以加载之前保存的 docker 镜像,如下所示:

gzip -d /tmp/my.discourse.docker.app.tar.gz
docker load -i /tmp/my.discourse.docker.app.tar

gzip -d /tmp/my.discourse.docker.base.tar.gz
docker load -i /tmp/my.discourse.docker.base.tar
  1. 然后,解压您原始的 /var/discourse 目录:
cd /var
tar -xvzf /tmp/my.var.discourse.tar.gz
  1. 接下来,您需要检查您的镜像,确保它们已正确标记:
docker images
  1. 如果镜像未正确标记,请确保为其添加正确的标签,例如针对您的应用镜像:
docker tag 58ffc74989af local_discourse/app:latest
  1. 最后,执行以下操作:
cd /var/discourse
./launcher start app

一切运行正常。我刚刚测试了两次。

希望这对您有所帮助。

仅供参考:我尝试了两种不同的方式执行此方法,即先执行上述备份步骤,然后清除所有 docker 容器、镜像以及 /var/discourse 目录(每次都彻底清除所有内容)。

在每种情况下,我都能成功加载保存的 docker 镜像,解压 /var/discourse 目录,运行 ./launcher start app,Discourse 顺利启动。为了证明这一点,我还可以从 UI 执行常规备份,证明一切正常。

我不确定这是否回答了您的问题(我也未参与 Postgres 10 到 12 的升级或相关讨论);但关于您提出的仅通过tar打包应用作为备份并恢复的问题,答案是是的,但您不仅需要归档 /var/discourse 目录,还必须使用 docker save 保存您的镜像。

主要的“陷阱”是保持镜像仓库名称和标签的正确性,之后您就能顺利操作了。

希望这在一定程度上回答了您的问题:

如何备份和恢复整个 /var/discourse 应用文件夹?

答案是:您必须同时归档您的文件夹和 docker 镜像(如上述示例所示),使用 docker save 保存镜像(用于备份),并使用 docker load 进行恢复。

请记住,这种方法并未得到官方支持;但出于好奇,我想从系统管理员的角度了解如何操作,结果发现这比我之前的回复所暗示的要简单得多。

注意 1:

在将 /var/discourse/ 目录整体打包为 tar 文件之前,您可能希望将所有备份从 backups/default 目录移出(脱离目录树),并单独保留这些备份,因为这些文件非常大……

注意 2:

此类备份不受支持,因此不建议大多数 Discourse 系统管理员采用。我推荐用户遵循官方推荐的(且得到官方支持的)Discourse 备份和恢复方法。

保持好奇!

保重。


如需更多详细信息(包括屏幕截图),请查看我的完整帖子:

6 个赞

这是一个极好的方法!谢谢!

恢复服务器上有一个问题。

./launcher logs app

2020-06-18 13:33:56.434 UTC [127] FATAL: 数据目录 “/shared/postgres_data” 的权限归属错误
2020-06-18 13:33:56.434 UTC [127] HINT: 服务器必须由拥有数据目录的用户启动。
./run: 3: echo: echo: I/O 错误
2020-06-18 13:33:57.448 GMT [128] LOG: 跳过缺失的配置文件 “/shared/postgres_data/postgresql.auto.conf”


这可能是由于缺少某些 tar 选项?我在解压时添加了 -p-s,但并未奏效。

原始服务器(Docker 外部):

ls -la /var/discourse/shared/standalone/postgres_data/

drwx------ 7 messagebus messagebus 4096 5 月 25 日 13:16 base

原始服务器(Docker 内部(./launcher enter app)):

ls -la /var/lib/postgresql/10/main/

drwx------ 5 root postgres 4096 5 月 25 日 23:28 base


恢复服务器(Docker 外部):

ls -la /var/discourse/shared/standalone/postgres_data/

drwx------ 7 messagebus messagebus 71 5 月 25 日 11:16 base

恢复服务器(Docker 内部):

drwx------ 5 root postgres 41 5 月 25 日 23:28 base


./launcher rebuild app 可以解决这个问题,但这不是重点。

有什么建议吗?

根据你的恢复流程,我认为你指的是 docker save -o /tmp/my.discourse.docker.base.tar discourse/base:2.0.20200512-1735。无论如何,解释得很清楚!

不过,正如你所说,我认为这并非官方支持的方法(但我也认为除非 Discourse 团队在重建过程中开始使用多个基础镜像,否则不太可能有其他导致错误的因素)。

看起来在以下链接中也存在相同的问题:

https://meta.discourse.org/t/postgresql-12-update/151236/298?u=lucasbasquerotto

虽然常见问题解答(FAQ)中尚未针对此特定问题提供答案,但考虑到有多人遇到此问题,Discourse 团队可能会添加解决方案。关于源集群未正常关闭的常见问题解答可能与您的问题相关。

1 个赞

我使用的一种方法,不涉及 docker save 或对 /var/discourse 进行完整的 tar+untar 操作: