我的gitea服务器的数据持久化是-v绑定挂载目录实现的,个人使用因此只用了sqlite数据库。

在之前的脚本中,我通过在正在运行的alist容器内执行gitea dump命令来备份gitea的数据。经过检查后发现_经常_会因为各种锁和文件不存在之类的问题(其实都算并发问题)导致备份失败。现在重新读了gitea文档之后发现了问题。

根据gitea文档所说

To ensure the consistency of the Gitea instance, it must be shutdown during backup.

每次备份gitea的实例时是要关闭的,但是我没有,这就导致了前文说的问题。所以现在尝试按照官方推荐的先关闭再备份的方式备份数据。由于我的gitea是以容器的形式运行的,现在又出现了几个新问题

kill gitea进程后,容器也将停止运行

此问题导致gitea容器无法在停止进程后直接进行备份,有一种先有鸡还是现有蛋的尴尬感觉。

其解决方案是创建一个新的gitea容器,挂载gitea容器相同的卷后在这个容器内进行备份。

由于docker run具有flag--volumes-from,允许新创建的容器直接挂载已存在的容器的卷(查了一圈没发现它是否支持绑定挂载,也就是映射目录。但是我尝试后发现发现新容器信息的Mount字段和已存在容器的Mount字段完全相同,包含bind类型的挂载,所以大概支持?)可以很方便地创建一个挂载的参数完全和已存在容器相同的容器。

甚至在官方文档中也强调了这个flag可以用于备份和恢复。

让新创建的gitea容器执行备份操作

默认情况下启动容器后会直接运行gitea服务。可以通过修改entrypoint的方式来指定某个程序被运行,替换镜像默认的entrypoint,这也是entrypoint的重要意义。

在当前情况下,就是使用–entrypoint flag:--entrypoint '/app/gitea/gitea',然后传参dump -c ...来进行备份操作。

其他

  • 需要指定git用户运行gitea:--user git
  • 创建一个映射目录(绑定挂载),直接备份到宿主FS中:--volume $(pwd)/backups:/backups
  • 需要指定工作目录,默认情况下gitea dump会将备份文件放在当前工作目录:--workdir /backups
  • 运行完毕容器后立刻删除:--rm
  • 传参进行备份:dump -c /data/gitea/conf/app.ini

拼在一起就成了

docker run --rm --volumes-from gitea --volume $(pwd)/backups:/backups --user git --workdir /backups --entrypoint '/app/gitea/gitea' gitea/gitea:latest dump -c /data/gitea/conf/app.ini