Ghost 博客部署及问题处理
我之前的网站,是部署在 Cloudflare 上的静态网页。每次的发布的流程是先在本地编写内容,然后上传到 Github,触发 Cloudflare 构建,根据内容生成静态页面。这太麻烦了。如果需要上传图片,还需要额外的图床管理流程。我一直很不喜欢,我甚至认为,这是我文章更新频率过低的原因之一(其实是懒🤔)。
直到我发现了 Ghost 系统,它简洁优雅,专注于文章编写。我本地测试之后发现这就是我想要的,因此我把网站迁移过来。
Ghost 简介
先介绍一下 Ghost 是什么,它是一个开源的内容管理系统(CMS),专注于为创作者、博主和出版者提供简洁、高效的博客和网站搭建平台。它使用 Node.js 构建,使用 Markdown 为核心写作方式;同时也支持卡片、HTML、等高级排版方式。界面干净、性能优异,特别适合注重内容创作而非复杂功能的用户。
自带电子邮件通信会员系统,是 Ghost 系统的特色之一,这允许用户直接订阅网站,后续可以收到更新通知。因此我也希望你能订阅我的网站,绝无消息打扰。
使用 Ghost 博客的主要好处:
- 专注写作体验
Ghost 的后台编辑器基于 Markdown,界面清爽无干扰,专注于内容本身。 - 高性能与轻量
基于 Node.js,Ghost 启动快、资源占用低,页面加载速度远超许多传统 CMS(如 WordPress),对 SEO 和用户体验更友好。 - 原生支持会员与订阅
Ghost 内置会员系统,可轻松设置免费或付费订阅、邮件通讯(Newsletter),非常适合打造个人品牌或知识付费内容,不过目前 Ghost 正式版只支持国外的支付系统,好在 Beta 版已经有支持微信、支付宝的计划。 - 现代化技术栈
Ghost 采用现代化 Web 技术,支持 API(Headless 模式),便于与前端框架(如 React、Vue)集成,适合有开发能力的程序员进行深度定制。 - 安全与维护简单
Ghost 核心功能精简,插件生态克制,减少了安全漏洞和兼容性问题。官方提供托管服务(Ghost(Pro)),美元支付,体验略贵,好在支持自建部署。 - 开源且社区活跃
作为开源项目,在 Github 上有 5.3万 Star,Ghost 有活跃的社区和持续更新,你既可以免费自建,也可以选择官方托管服务获得更省心的体验。
如果你有编程能力,Headless 模式的 API 可以让你随心所欲,你可以通过 API,控制 Ghost 的一切,为以后可能的博客迁移,提供了支持。我这次的内容迁移就是写个脚本,生产 Ghost 要求的 JSON 格式直接导入。
Ghost 生产环境安装
官方提供了多种方式,我建议选择 Docker 安装方式。非常简单,10 分钟即可配置完成,会自动申请配置 HTTPS 证书。
- 克隆 Ghost Docker Compose 仓库。
git clone https://github.com/TryGhost/ghost-docker.git /opt/ghost && cd /opt/ghost这是一个包含了 Caddy、Ghost、Mysql 的 Docker Compose。
- 复制并修改配置文件
cp .env.example .env
cp caddy/Caddyfile.example caddy/Caddyfile
vim .env主要修改 .env 中域名、Mysql 用户名密码、邮件 SMTP(非常重要) 信息。
- 域名为 Ghost 网站自定义的域名,例如 mysite.com
ADMIN_DOMAIN:(可选)为你的 Ghost 管理员单独建立一个域名,例如 admin.mysite.comDATABASE_ROOT_PASSWORD:Mysql ROOT 用户密码DATABASE_PASSWORD:Ghost 使用的 Mysql 用户密码- SMTP 邮件部分:所选择的 SMTP 服务的配置,这非常重要(参见 :邮件配置文档 )
3.配置 DNS 解析到你的机器
4.Docker Compose 启动。
# 后台启动
$ docker compose up -d
# 如果遇到启动失败,可以不要后台启动,观察启动日志
$ docker compose up5.访问 `https://mysite.com/ghost` 进入 Ghost 后台配置信息。
如果一切顺利,你的 Ghost 博客已经安装完成了。
但人生总有意外,如果你遇到了问题可以向下看。
Ghost Dcoker 启动失败
使用 docker compose up 启动服务,发现 Mysql 总是启动失败, Ghost 容器连接 Mysql 不断报错如下:
[2025-11-26 21:33:58] INFO Ghost server started in 1.55s
[2025-11-26 21:33:59] ERROR connect ECONNREFUSED 192.168.144.2:3306
connect ECONNREFUSED 192.168.144.2:3306
"Unknown database error"
Error ID:
500
Error Code:
ECONNREFUSED
----------------------------------------
Error: connect ECONNREFUSED 192.168.144.2:3306
at /var/lib/ghost/versions/6.8.1/node_modules/knex-migrator/lib/database.js:57:19
at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1637:16)
[2025-11-26 21:33:59] WARN Ghost is shutting down
[2025-11-26 21:33:59] WARN Ghost has shut down
[2025-11-26 21:33:59] WARN Your site is now offline排查分析后,发现原因是:我购买的云服务器配置过低,内存只有 1 G,Mysql 启动会因为内存不足启动失败。
解决方案:
- 查看机器内存,若无 swap 内存,则增加 SWAP 内存。
# 创建 swap 文件
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效(可选)
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstabfree -h 查看内存,最后一行的 swap 是增加的 1 G 内存。
$ free -h
total used free shared buff/cache available
Mem: 896Mi 720Mi 123Mi 1.0Mi 196Mi 175Mi
Swap: 1.0Gi 144Mi 879Mi- 限制 Mysql 内存占用,增加启动时间。
编辑 compose.yml 中的 db 配置,为 Mysql 增加 command 和 mem_limit 限制内存占用。同时修改 healthcheck 增加健康检查时间。
修改后的 docker compose db 配置如下:
db:
image: mysql:8.0.44@sha256:f37951fc3753a6a22d6c7bf6978c5e5fefcf6f31814d98c582524f98eae52b21
restart: always
expose:
- "3306"
environment:
MYSQL_ROOT_PASSWORD: ${DATABASE_ROOT_PASSWORD:?DATABASE_ROOT_PASSWORD environment variable is required}
MYSQL_USER: ${DATABASE_USER:-ghost}
MYSQL_PASSWORD: ${DATABASE_PASSWORD:?DATABASE_PASSWORD environment variable is required}
MYSQL_DATABASE: ghost
MYSQL_MULTIPLE_DATABASES: activitypub
mem_limit: 400m # 限制容器最多使用 400MB 内存
command: >
--innodb-buffer-pool-size=32M
--innodb-log-file-size=16M
--key-buffer-size=4M
--max-connections=10
--table-definition-cache=100
--table-open-cache=100
--performance_schema=0
--skip-name-resolve
volumes:
- ${MYSQL_DATA_LOCATION:-./data/mysql}:/var/lib/mysql
- ./mysql-init:/docker-entrypoint-initdb.d
healthcheck:
test: mysqladmin ping -p$$MYSQL_ROOT_PASSWORD -h 127.0.0.1
interval: 10s
start_period: 120s
start_interval: 10s
retries: 120
networks:
- ghost_networkmem_limit 、command 、healthcheck 为修改部分。
这时,你的 docker 就可以成功启动了,Mysql 启动较慢,耐心等待。
Member discussion