Ghost 博客系统默认采用本地存储方式处理上传的图片和媒体信息。为便于数据维护和迁移工作,同时也为改善访问体验,提高可靠性和加载速度,需要对 Ghost 进行必要的设置,以便支持对象存储服务。

为什么使用对象存储

Ghost 默认是将上传的图片和多媒体信息按年份和月份打包放置在 content/ 目录下。当博客仅工作在一台设备上时,默认存储简单便捷,但与此同时也暴露出很多问题,如多次上传同一张图片时会默认作为多个不同的图片处理,造成页面加载体验不能最优化。同时,存放在某一具体机器中的数据既不能保障安全,又会在密集访问时占用大量带宽,特别是在距服务器物理位置较远的地点访问时,网站数据有可能加载时间大幅延长甚至于不可达。为避免这些问题,提高信息安全性、可靠性,加快实际加载速度,应当尽可能选择对象存储服务。

第三方对象存储将本应保存在本地的数据保存在云端,通过调用特定 API 实现上传、管理和下载。一般地,被上传的数据将分配到唯一的资源位置,以便在不同的网站或同一网站的不同位置使用这些数据。配合内容分发网络(CDN)服务,这些数据将被缓存在不同区域,为不同地区的用户提供资源加载的支持。

接入阿里云 OSS 服务

Ghost 官方有提供第三方存储方案的设置文档,并附带了若干第三方存储开源插件。考虑到官方提供的阿里云 OSS 服务插件仅支持 1.x 版本,已不适用于目前的 3.x 版本,于是选用了作者苏洋完成的兼容 Ghost 3.x 存储插件 ghost-aliyun-oss-store

第三方插件基本是以官方提供的存储插件模板为准,调用存储商提供的接口或集成环境完成的,本例使用插件使用阿里云提供的 SDK。

使用第三方存储插件需要将插件安装在 Ghost 安装目录下 current/content/adapters/storage/ 目录内,同时在该目录需要新建一个与插件同名的入口文件。current 目录重定向至当前版本的 Ghost 程序位置,如后续对 Ghost 进行升级,需要重新设置存储插件。

> cd $GHOST_INSTALL
> mkdir -p current/content/adapters/storage/
> cd current/content/adapters/storage/
> yarn add ghost-aliyun-oss-store
> echo "module.exports = require('ghost-aliyun-oss-store');" > ./ghost-aliyun-oss-store.js

部署插件后,需要修改博客配置文件,增加 storage 相关内容。

{
  "storage": {
    "active": "ghost-aliyun-oss-store",
    "ghost-aliyun-oss-store": {
      "accessKeyId": "YOUR_ACCESS_KEY_ID",
      "accessKeySecret": "YOUR_ACCESS_SERCET",
      "bucket": "YOUR_BUCKET_NAME",
      "region": "oss-cn-beijing",
      "domain": "https://your-public-domian",
      "notfound": "https://notfound-img-url.jpg"
    }
  }
}

上述设置完成后重启 Ghost 应用,即可在上传图片或多媒体资源时存储在阿里云 OSS 服务中。

存储服务集成镜像化

如也博客部署在容器服务的基础上,分为代理服务器容器、数据库容器和应用程序主容器。考虑到容器部署的特性,在上文中涉及的插件部署流程需要在应用程序镜像构建时一并处理,并作为容器的一部分对外提供服务。

RUN mkdir -p $GHOST_INSTALL/current/content/adapters/storage/
        \ cd $GHOST_INSTALL/current/content/adapters/storage/
        \ yarn --verbose add ghost-aliyun-oss-store
        \ echo "module.exports = require('ghost-aliyun-oss-store');" > ./ghost-aliyun-oss-store.js

关于博客的配置可以集中在 config.production.json 文件中设定,构建镜像时将该配置文件复制在 Ghost 安装目录下覆盖同名文件即可。

自定义后的 dockerfile 可以直接在本地构建,也可以使用 docker-compose 等容器集群编排服务进行构建。除手动构建外,可以部署后续 CI/CD 业务流程,在第三方容器镜像服务商进行自动化构建和应用部署。

完成

2020 年 8 月 28 日,如也博客升级改造基本完成。

在本次升级改造中,使用第三方对象存储服务作为主要内容。无奈在国内互联网关于 Ghost 博客相关的内容属实有限,特别是大部分用户目前依旧使用 1.x 历史版本或 0.7.4 中文版本。在 1.x 版本前,所有文章封面及配图均支持自定义 url,并不依赖本地存储,故使用这些历史版本的用户并不会考虑存储相关的问题。

关于 Ghost 3.x 的相关讨论数量少,内容重复,并不能满足改造需求。官方文档在关键设置上仅给出少量参考,在很多关键问题上没有提供必要的解释。上述问题导致升级改造推进缓慢,错误频出,甚至一度中断服务。

本次升级改造参考了作者苏洋发表的文章《让运行在 Docker 中的 Ghost 支持阿里云 OSS》 ,在此表示感谢。