博客迁移历程

之前我的博客托管在外网的Linode上,Linode整体还是挺好的,支持一键迁移,服务器也很稳定,网站上教程资源很丰富;缺点就是国内访问的网速总是不理想,延迟很大,其间我尝试了 Linode 不同地区的机房,问题都没有解决,网速不稳定,经常会很慢。

近期,我下定决心迁移博客,彻底解决这个问题,后续也准备将博客继续维护起来;经过广泛调研,并综合考量性价比等多方面因素,决定将博客迁移到阿里云。接下来,我将详细分享博客迁移的全过程,其中我也踩了不少坑,希望能给大家提供一些参考。

博客运行环境

博客的运行环境主要涉及以下技术栈:

  • 操作系统:Ubuntu 16.04
  • 编程语言及框架:Ruby 2.3.8、Rails 4.2.4
  • 数据库:MySQL 5.7
  • 搜索服务:Solr 5.5.4
  • Web 服务器及应用服务器:Nginx + Passenger

此外,Rails依赖的需要本地编译的包如下:

  • nokogiri 1.6.6.2
  • mysql2 0.3.20

部署工具方面

  • ansible 2.0.0.2
  • bundler 1.17.2
  • capistrano 3.6.1

迁移目标及方案

如果是将上述系统直接部署到Ubuntu16.04上会很简单,因为我前期已经整理了功能完善的ansible部署工具,可以实现一键部署,完成所有的依赖安装和环境配置。但考虑到Ubuntu16.04已停止维护,为了让这次迁移更加彻底,我决定将操作系统升级到最新的Ubuntu24.04。

不得不说,我前期严重低估了迁移的难度,从过年到现在,竟然花了将近两周时间(原本预计只需两天)。

方案一、 折腾本地虚拟机,重新启用ansible部署工具(失败)

  • 安装Mac版Ubuntu  24.04 虚拟机:需要装arm版的【解决】。难点:arm版本导致很多依赖包无法使用或默认缺失,需要单独下载和编译。
  • 使用最新版ansible软件(2.18.2):仅因为不想安装太久的版本【艰难解决】。难点:和老版本不兼容,部分需要修改代码解决。
  • ~~原计划安装最新版的Ruby 4.1 ,之后因为很多依赖包不兼容,放弃。~~
  • 安装Ruby-2.3.8版本【解决】。难点:缺少libssl1.0-dev,需要源码编译安装,然后才能编译安装Ruby,建议使用rvm来安装。
  • 安装bundler包:使用1.17.2版本。
  • 安装依赖gem包 - nokogiri【艰难成功】。nokogiri编译安装依赖部分本地包,需要通过源码编译安装iconv、 libxml2-2.9.2、libxslt-1.1.28等。
  • 安装依赖gem包 - mysql2:其编译依赖mysql5.7的dev包
  • 安装Mysql 8.0 ,与mysql2 0.3.20包冲突,但这个是底层包无法更新。【冲突】
  • 安装mysql 5.7 成功,但安装依赖的dev包,和其他dev包冲突。【冲突】

在解决了无数问题后,发现这条路走下去,即使编译通过并安装成功,运行过程中也难免出现各种问题,于是决定放弃方案一。

方案二、使用docker镜像安装

为了避免上面遇到的各种编译及依赖问题,我决定将博客主体继续运行在Ubuntu16.04上,但又不想放弃升级到Ubuntu24.04的想法。经过综合考虑,决定采用Docker来部署,这样外部的主机使用Ubuntu24.04,后续有时间再对博客做全面升级,以支持最新的操作系统。具体步骤如下:

  1. 本地安装Ubuntu镜像
    • 开发环境:采用 arm 架构安装 Ubuntu 16.04 镜像,用于博客工程的开发测试和更新,目前使用过程中未发现问题。
    • 准生产环境:为了与生产服务器架构保持一致,采用amd64架构安装Ubuntu镜像。
    • 模拟生产宿主环境:本地安装Ubuntu24.04镜像,用于模拟生产环境的宿主服务器。
  2. 初始化镜像环境:安装必要的包、创建用户、配置ssh服务器。
  3. 安装应用程序:在镜像中安装Rails、solr等应用程序,可以使用之前做的ansible工具直接安装。
  4. 保存镜像:将安装好的容器保存为镜像,使用commit命令。
    • 镜像可以认为是稳定的、可复用、持久化的系统。
    • 容器可以认为是可以丢弃的、不稳定的存在,可以很方便用来试错。
    • commit前尽量删除无用的文件、安装程序等,减小镜像的体积。
  5. Docker向宿主机器暴露端口,进行端口映射:
    • 开发环境:为方便开发,开放了多个端口(前面为宿主机端口、后面为镜像中开放的端口):
      • 10022:22 :SSH服务,便于上传和编辑文件。可通过SSH支持VSCode远程开发代码,但无法使用 AI 是个小缺点,后续可考虑通过 SSH 同步工具实现代码同步。
      • 10080:80 :HTTP服务
      • 13000:3000:Rails server端口,便于在宿主机进行调试
      • 13306:3306:MySQL数据库端口,便于通过Mac的图形化界面进行管理
      • 18983:8983:Solr搜索端口,便于在宿主机调试
      • 8086:8086 和 8087:8087 :作为备用端口,避免每次开放新端口都需要 commit 镜像的麻烦。
    • 生产环境:出于安全性考虑,仅开放最少的端口:
      • 33000:3000:Passenger服务器的默认端口
      • 30022:22 :SSH服务器的端口,为保障安全,关闭了密码登录,仅允许证书登录,并安装了 Fail2ban 软件。
  6. 数据库配置:出于性能考虑,使用宿主机的MySQL服务器。避免在Docker容器中直接运行MySQL。
    • 为了安全,通过设置ufw防火墙,仅允许容器固定IP远程访问MySQL。
  7. 防火墙配置:配置docker-ufw,防止外网访问docker暴露的端口。安装完正常无需特殊配置。
  8. 镜像迁移:将生产镜像导出,上传到生产环境,再导入到生产服务器。

至此,博客主体部署已完成,下面简单列举一下生产服务器的其他配置内容,供大家参考:

  1. SSH登录配置
    • 禁止以root身份登录
    • 取消使用密码登录,改用SSH证书登录
  2. 设置虚拟内存,参考:Ubuntu实例中添加swap分区的方法
  3. 设置ufw防火墙
  4. 安装Fail2ban软件
  5. Web 服务器配置:配置nginx,安装https证书。

参考教程

  1. Ubuntu使用certbot配置nginx服务器的ssl证书
  2. Deploying a Ruby app on a Linux/Unix production server
  3. Installing Older Ruby Versions on Ubuntu 24.04 and 22.04
  4. How to install MySQL 5.7 on ubuntu 20.04 or later
  5. Ubuntu实例中添加swap分区的方法
  6. UFW-Docker 使用教程

文章未经特殊标明皆为本人原创,未经许可不得用于任何商业用途,转载请保持完整性并注明来源链接 《ITechLib》

留言:

(lesstile enabled - surround code blocks with ---)