从手足无措到一键启动:我的-Hexo-博客-Docker-迁移历险记
作为一个写了两年博客的 “半吊子技术人”,我之前一直把 Hexo 搭在 Ubuntu Server 上 —— 虽然能跑,但每次更新主题、升级插件都要 ssh 连服务器,改配置怕崩,备份怕漏文件,久而久之成了 “不敢动的遗产项目”。直到朋友说 “试试 Docker 吧,容器化后维护能省一半心”,我才咬咬牙开启了这场 “痛并快乐着” 的迁移之旅。
一、迁移前的小忐忑:先理清楚 “要带什么走”
迁移的第一步,我就犯了 “选择困难症”:Hexo 目录里那么多文件,哪些是必须带走的?总不能把整个文件夹一股脑复制吧?
翻了半天教程,才确定核心要备份的是这几样(后来证明少一个都不行):source/:所有 markdown 博客文章,这是 “命根子”;themes/:我折腾了好久的 Butterfly 主题配置,丢了要哭;_config.yml 和主题目录下的 _config.next.yml:所有个性化设置;package.json 和 package-lock.json:依赖清单,没这个后续装插件会崩。
于是在原服务器上执行备份命令时,我手都是抖的(怕漏文件):
进入原Hexo目录
1 | cd /home/hexo/my-blog |
打包核心文件(特意排除了node_modules,体积太大)
1 | tar -zcvf hexo-backup.tar.gz source/ themes/ _config.yml _config.next.yml package*.json |
接着用 scp 把压缩包传到新主机,看着进度条走满 100%,才松了第一口气 —— 但没想到,真正的坑还在后面。
二、Docker 配置:从 “照抄教程” 到 “报错连连”
新主机上我先按教程装了 Docker 和 Docker Compose,一切顺利。然后想把 Hexo 文件整理得整齐点,就建了个blog/二级目录,把备份文件解压进去,目录结构变成这样:
hexo-docker/
├── docker-compose.yml # 待写
├── Dockerfile # 待写
├── .dockerignore # 待写
└── blog/ # Hexo核心文件
├── source/
├── themes/
└── 其他配置文件
坑 1:镜像拉取时的 “401 Unauthorized”
按照之前的教程写了 Dockerfile(基础镜像用node:lts-alpine)和 docker-compose.yml,第一次执行docker-compose up -d --build时,终端突然跳红:
ERROR: pull access denied for node:lts-alpine, repository does not exist or may require 'docker login': denied: requested access to the resource is denied
我当时懵了:Docker Hub 的镜像怎么会 “未授权”?难道是我没登录?赶紧执行docker login输了账号密码,结果还是报错。查了半小时才发现,原来新主机的网络默认走公司代理,Docker 没配置代理导致拉取失败。
解决办法也简单:给 Docker 加代理配置(如果是国内网络,换国内镜像源更方便):
编辑Docker配置文件
1 | sudo nano /etc/docker/daemon.json |
加入代理地址(换成自己的):
{
“proxies”: {
“default”: {
“httpProxy”: “http://192.168.1.100:8080",
“httpsProxy”: “http://192.168.1.100:8080"
}
}
}
重启 Docker 后再拉取,终于看到了熟悉的 “Pull complete”。
坑 2:npm install 的 “enoent”错误,差点以为文件丢了
镜像拉取成功,以为接下来会顺利,结果又卡在npm install步骤,报错:
npm ERR! enoent ENOENT: no such file or directory, open '/app/package.json'
我当时冷汗都下来了:难道备份时漏了 package.json?赶紧去blog/目录下看 —— 文件明明在啊!再仔细看 docker-compose.yml 的 volumes 映射,才发现自己犯了低级错误:把./blog/package.json:/app/package.json写成了./blog/package.json:/app/package-lock.json,路径对应错了!
改对 volumes 配置后,npm install还是报错,这次是 “权限不足”。原来宿主机的blog/目录权限是700,容器内无法读取。执行chmod -R 755 ./blog后再试,终于看到“added 1234 packages”的提示,我差点拍桌子欢呼。
坑 3:“hexo: not found”—— 最让人崩溃的 “命令失踪案”
解决了依赖问题,新的报错又来了:
RUN hexo generate: /bin/sh: 1: hexo: not found
Hexo 命令怎么会找不到?我明明在 Dockerfile 里写了npm install -g hexo-cli啊!反复检查 Dockerfile,没发现问题;进入容器执行hexo -v,果然提示 “command not found”。
后来在论坛看到有人说 “宿主机的 node_modules 会覆盖容器内的依赖”,我才想起:备份时虽然没打包 node_modules,但之前解压后手动复制过旧的 node_modules 到blog/目录!容器启动时,./blog/node_modules:/app/node_modules的映射把容器内新安装的 hexo-cli 覆盖了。
赶紧删除宿主机blog/目录下的 node_modules:
1 | rm -rf ./blog/node_modules |
重新构建容器,这次hexo generate终于成功执行,看到 “Start processing” 的日志时,我长舒一口气 —— 折腾了 3 小时,终于看到希望了。
三、成功启动:当浏览器加载出博客的那一刻
最后执行docker-compose up -d,用docker ps看到hexo-blog容器状态是 “Up”,赶紧在浏览器输入http://新主机IP:4000—— 熟悉的博客首页慢慢加载出来,标题栏还是我去年改的 “小站”,侧边栏的阅读统计也还在。
那一刻突然觉得之前的折腾都值了:现在要更新博客,只需在宿主机blog/source/_posts/里写文章,执行docker exec -it hexo-blog hexo generate就能生效;要备份,直接打包hexo-docker/目录就行,再也不怕漏文件;甚至想换服务器,把整个目录复制过去,docker-compose up -d就能一键启动。
四、迁移后的小感悟:技术成长就是 “踩坑填坑”
这次迁移让我明白,“容器化” 不是 “高大上的名词”,而是真真切切能解决问题的工具。过程中虽然踩了不少坑 —— 镜像拉取失败、文件映射错误、命令失踪,但每解决一个问题,都对 Docker 的 “文件映射”“镜像构建” 理解更深一层。
如果你也想把 Hexo 迁到 Docker,别害怕报错:遇到问题时,先看日志(docker-compose logs -f是神器),再搜关键词,大部分坑前人都踩过。当你终于看到博客在容器里跑起来的那一刻,那种成就感,比写一篇博客还让人开心。
最后放一张容器成功运行的截图,纪念这次 “历险记”:
(此处可插入 docker ps 或博客首页截图)
未来,我还想试试给博客加 HTTPS、用 Nginx 反向代理,技术之路漫漫,慢慢折腾吧~



