CTFd 删站事故复盘


CTFd 删站事故复盘

本删站事故发生于 2021 年 8 月 30 日。

事故缘由

2021 年 6 月起,我负责打理学校实验室的 CTFd 站点。

站点使用了 Docker Compose 来部署应用,再使用 Nginx 负责反代。

2022 年 11 月 25 日,由于服务器使用的是 CentOS 8 的操作系统,已经 EoL 了。我想解决服务器上一团糟的依赖地狱还有源镜像的问题。

事故过程

由于现存的 docker 是由宝塔安装的,并不是跟随 docker-ce 的最新版本,于是我选择使用 yum --allowerasing upgrade加入官方源进行覆盖安装。这时 yum 使用了旧的宝塔版本覆盖了我后来引入的官方源。再次覆盖安装回去即可。

截止目前都没有问题,只是导致服务发生了分钟级别无关紧要的离线罢了。

这时,由于宝塔面板 docker 的一些前端bug。我重启了下防火墙,并再次重装了 docker.

紧接着,站点发生了 502 Bad Gateway.

思考了下,这是由于 Nginx 无法与容器通信导致的网络问题。果断使用 docker logs <CTFd 容器 ID> | tail 查看了下最近的几条日志。发现是无法连接 MariaDB 数据库,关闭防火墙后解决。

这时,使用 docker compose up -d 启动服务时会提示 strconv.Atoi: parsing "": invalid syntax 错误,上 StackOverflow 搜索后发现了一篇帖子。

https://stackoverflow.com/questions/73948802/strconv-atoi-parsing-invalid-syntax

敲完了 docker compose down --remove-orphans 命令后马上觉得不对,往下翻发现了……

这里已经意识到发生惨剧了,立马关闭了所有容器。尽量减少操作以防 Docker 有什么 GC 机制。

发生了什么

https://docs.docker.com/engine/reference/commandline/compose_down/

Name, shorthand Description
--remove-orphans Remove containers for services not defined in the Compose file.

--remove-orphans 会删除 compose 文件中未定义的容器。

使用 docker ps 看了下,只剩一个 CodiMD 的容器了……

该做什么呢

万幸的是,CTFd 在建设的时候就使用了 Volume 将目录映射到宿主机目录,所以不出意外的话 MariaDB, Redis 和 CTFd 的数据是都在的。只是重新部署服务的事情了。

先将仅存的备份做一份镜像,然后再次 docker compose up -d

-d 为后台启动。同时可以酌情使用 --no-recreate 以不重新创建已经停止的容器)

网络问题

CTFd 默认会配置端口转发,可能会启动失败,建议先清空 iptables chains 再重启 docker 服务。

sudo iptables -t filter -F
sudo iptables -t filter -X
sudo systemctl restart docker

然后服务恢复正常了。

类似的故事

电脑110官网删站事故复盘 - Billchenchina

Before the Accident

容器备份

可以使用 docker commit 创建容器的快照

docker commit -p <容器 ID> container-backup

命令会生成一个作为Docker镜像的容器快照,可以通过 docker images 查看创建的Docker镜像。为了备份该快照,我们有两个选择,一个是我们可以登录进 Docker 注册中心,并推送该镜像;另一个是我们可以将 Docker 镜像打包成tar包备份,以供今后使用。

国内访问速度慢的可怜,所以建议选择本地备份,这也是绝大多数人的选择。要完成该操作,我们需要运行以下 docker save 命令。

docker save -o /Volumes/work/docker/backup/nginx-backup.tar nginx-backup

容器恢复

在注册中心推送了这些 Docker 镜像,那么我们仅仅需要把那个 Docker 镜像拉回本地。

docker pull arunpyasi/container-backup:test

将这些 Docker 镜像作为 tar 包文件备份到了本地,那么我们只要使用 docker load tar 包的备份路径以加载该镜像。

docker load -i ~/container-backup.tar

现在,为了确保这些Docker镜像已经加载成功,我们来运行 docker images 命令。

docker images
# 镜像被加载后,用加载的镜像去运行容器。
docker run -d -p 80:80 nginx-backup

文章作者: sfc9982
版权声明: 本博客所有文章除特別声明外,均采用 CC BY-NC-ND 4.0 许可协议。转载请注明来源 sfc9982 !
  目录