备份下载下来不算完:用 Docker 把官网备份完整还原一遍,才敢说"可恢复"
官网前阵子刚经历过一次托管套餐被误停的宕机(另一篇文章里写过),事后除了恢复托管,还多了一层后怕:手上的备份,真的能恢复出一个能跑的网站吗? 备份文件躺在硬盘里不算数——没有完整还原过一次的备份,只能算”疑似备份”。
于是做了一次完整的恢复演练:目标是只靠 cPanel 下载的备份文件,在本地 Docker 里把整个 Drupal 官网从零拉起来。
先搞清楚:一个 Drupal 站 = 文件夹 + 数据库
Drupal(以及几乎所有现代 CMS)把网站拆成两半存放:
- 文件夹:核心代码、主题、模块,以及用户上传的图片/PDF(
sites/default/files); - 数据库:每一篇文章、每一处文案修改、每个配置项、每个用户账号——全部只存在数据库里。
铁律:只备份文件夹,等于没有备份任何内容改动。 两半都要拿到:数据库从 phpMyAdmin 导出 .sql;文件这次直接用了 cPanel 的全量账户备份(.tar.gz)。
数据库先行:MariaDB 容器 + DBeaver 验货
本地不装任何数据库服务,直接一条命令拉一个 MariaDB 容器:
docker run --name drupal-mariadb -e MYSQL_ROOT_PASSWORD=<本地临时密码> -p 3306:3306 -d mariadb:latest
DBeaver 连上 localhost:3306,建一个空库,把导出的 .sql 执行导入。导入完成后抽查关键表:users 里的账号、file_managed 里的媒体文件清单都完整——数据库这一半,验货通过。
顺带搞明白一件事:数据库里没有图片文件本身,只有路径和元数据(public://.../logo.png 这类 URI)。实体文件在文件夹那一半的 sites/default/files 里,两边要对得上。
文件这一半:全量备份里多套了一层壳
解开 .tar.gz 之后一度找不到网站文件——因为全量账户备份和”手动压缩 public_html”的目录结构不一样,站点文件藏在 homedir/ 这一层下面,还包着邮件、SSL、日志等一堆别的东西。找到站点目录后,把它整个复制到 C:\ 下一个短路径——一是 Docker 挂载命令好写,二是避开 Windows 深层嵌套路径的长度限制。
三个坑,一个比一个经典
坑一:Windows 只读陷阱。 改 settings.php 把数据库指向本地容器,编辑器保存”成功”,实际上文件根本没变——Drupal 给这个文件加了只读属性,编辑器静默保存失败。右键属性去掉只读,重新改、重新存,这次真的写进去了。
坑二:localhost 不是你以为的 localhost。 网站容器起来后报 SQLSTATE[HY000] [2002] No such file or directory。这是 PHP 的一个著名怪癖:数据库 host 写 localhost 时,PHP 不走 TCP,而是去找本机的 Unix socket 文件——而 MariaDB 在另一个容器里,这个 socket 根本不存在。把 host 改成 host.docker.internal(容器访问宿主机的专用域名),连接立刻通了。
坑三:drupal:latest 跑不动 2021 年的代码。 第一次用最新镜像起站,满屏 Deprecated 和 Fatal error——最新镜像带的是 PHP 8.x,而这个 Drupal 9.1 时代的代码需要 PHP 7.4。删掉容器,换版本匹配的老镜像:
docker run --name drupal-web -p 8080:80 -v C:\<站点目录>:/var/www/html -d drupal:8-apache
drupal:8-apache 原生就是 PHP 7.4,web 根目录也和老代码的布局一致。
三个坑各自的报错都指向别处,真正原因都在环境差异上
刷新 localhost:8080——网站完整渲染出来了,栏目、文章、图片全部就位。页面顶部有几块粉色报错(Twig 缓存写不进 Windows 挂载目录的权限问题),删掉 files 下的 php/css/js 缓存目录、去掉只读属性后消失。
教训
- 备份的唯一验收标准是”完整还原成功”——这次演练等于做了一次裸机恢复测试,此后说”官网有备份”才有底气;
- 恢复老站点,容器版本要和代码年代匹配——
latest镜像是给新项目用的,遗留代码要找drupal:8-apache这类历史版本镜像,PHP 大版本对不上会直接 Fatal; - 三个环境差异坑背下来:Windows 只读属性会让编辑器静默保存失败;PHP 的
localhost走 socket 不走 TCP,跨容器要用host.docker.internal;从 Linux 服务器带下来的缓存文件(Twig/PhpStorage)在本地会产生无害但吓人的报错,清掉即可; - 全量账户备份的目录结构和手动打包不同——站点文件在
homedir/下,恢复文档里应该把这层壳写清楚,别让下一个恢复的人再找一遍。