Billchenchina 标签 联系 朋友们

电脑110官网删站事故复盘

Posted by Billchenchina on September 6, 2021

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

MySQL 从删库到跑路

事故缘由

2019 年 9 月 27 日,电脑 110 俱乐部的 Wordpress 实例交给了我。我使用了 Docker Compose 来部署应用:docker-compose.yml 当时的内容为:

version: "2.3"

services:
  wordpress:
    image: wordpress
    restart: always
    ports:
      - "127.0.0.1:8090:80"
    environment:
      WORDPRESS_DB_PASSWORD: root
  mysql:
    image: mysql:5.7
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: root

2021 年 8 月 30 日,因为希望给容器添加 healthcheck,添加了以下几行:

@@ -8,6 +8,12 @@
       - "127.0.0.1:8090:80"
     environment:
       WORDPRESS_DB_PASSWORD: root
+    healthcheck:
+      test: "curl -f http://127.0.0.1"
+      interval: 30s
+      timeout: 5s
+      retries: 1
+      start_period: 10s
   mysql:
     image: mysql:5.7
     restart: always

由于此前多次重启机器,容器均会自动重启(restart: always),我放低了警惕,没有考虑到更新 docker-compose.yml 后重启服务会删除之前容器。

于是我运行了 docker-compose down && docker-compose up -d,此时原容器被删除了(访问 127.0.0.1 显示 Wordpress 安装界面,使用 mysql 工具打开数据库显示 wordpress 数据库为空)。

数据找回

为找回数据,我立即停止了被新创建的容器。以 recover deleted docker container 的关键词在 Google 搜索,搜索到了一个 Stackoverflow 上的问题。按照提示在 /var/lib/docker/volumes/ 下查找是否有尚未删除的 volume。查看了一下每个 volume,发现了两个 wordpress 目录和一个 mysql 目录。最终通过 mtime 确定了两个最后修改于当日的 volume,且 cd 进去后发现确实一个是 Wordpress,一个是 MySQL。因为不了解,担心 Docker 会有 GC 机制将 unused volume 删除,我便先把这两个 volume 直接复制到了 /

好了,现在至少 volume 还在,即使再差也能从文件系统级恢复数据库和 Wordpress 文件。那现在问题变成了:如何恢复服务呢?

服务恢复

  1. 复制 volume 数据到 named volume。

    我使用了 docker_clone_volume.sh,这个 Shell Script 创建了一个 Alpine 容器,将原 volume 和新 volume 挂载到容器内,使用 cp -av src dst 直接复制。

  2. 修改 docker-compose.yml 文件挂载新的 named volume

     @@ -14,8 +14,17 @@
           timeout: 5s
           retries: 1
           start_period: 10s
     +    volumes:
     +      - wordpress:/var/www/html
       mysql:
         image: mysql:5.7
         restart: always
         environment:
           MYSQL_ROOT_PASSWORD: root
     +    volumes:
     +      - mysql:/var/lib/mysql
     +volumes:
     +  wordpress:
     +    external: true
     +  mysql:
     +    external: true
    
  3. 重启并恢复服务 docker-compose up -d

后续

  1. 运维角度最好从 Docker 级别也做好备份
  2. 问了下林科学家,还好整站在 Dropbox 上有完整备份,不至于删站
  3. 在涉及到操作之前没有做 volume 的容器的时候一定要谨慎

使用 BackWPup 插件进行的备份日志