用第三方平台写博客,最大的问题是:你不知道它哪天会改规则、涨价,或者干脆关掉。数据不在自己手里,样式也由别人说了算。所以我把博客搬到了一台自己的服务器上,用 Docker 跑 Ghost。
这篇记录一下整个过程,包括几个容易忽略的细节。
一、为什么是 Ghost + Docker
选 Ghost 的理由很简单:它是专门为写博客做的,后台干净,内容用编辑器写,主题是标准的 Handlebars 模板,想改前端随时可以改,不需要动后端。
选 Docker 的理由更简单:博客这种东西装一次可能几年不动,但服务器上还会跑别的东西。用容器隔离,升级 Ghost 的时候不用担心把系统里的 Node 版本搞乱。
二、起一个 Ghost 容器
Ghost 官方镜像直接可用,一条命令就能跑起来:
docker run -d \
--name ghost \
--restart always \
-p 127.0.0.1:2368:2368 \
-v /opt/ghost/content:/var/lib/ghost/content \
-v /opt/ghost/config/config.production.json:/var/lib/ghost/config.production.json \
-e NODE_ENV=production \
ghost:6
这里有两个细节值得说:
-p 127.0.0.1:2368:2368里前面的127.0.0.1不要省。只写-p 2368:2368的话,Docker 会把它绑到0.0.0.0,也就是对整个公网开放,并且绕过你的反向代理和 HTTPS。- 数据一定要挂出来。
/var/lib/ghost/content里有文章图片、主题、上传的文件;config.production.json里有数据库密码和邮件配置。这两样不挂载,容器一删就全没了。
三、反向代理和 HTTPS
Ghost 自己不管 HTTPS,前面要放一个反向代理。用 Nginx 或者 OpenResty 都行,核心就三件事:转发到 2368、把 X-Forwarded-Proto 设成 https、别把上传大小限制得太小。
location / {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
client_max_body_size 50m;
proxy_pass http://127.0.0.1:2368;
}
X-Forwarded-Proto 这行漏掉的话,Ghost 会以为自己跑在 HTTP 上,登录后台时会出现重定向死循环,或者 Cookie 死活存不上。
四、数据库别用默认的
Ghost 默认用 SQLite,小站够用,但如果服务器上已经有 MySQL,直接复用更好,备份和迁移都方便。配置写在 config.production.json 的 database 段里:
{
"database": {
"client": "mysql",
"connection": {
"host": "127.0.0.1",
"port": 3306,
"user": "ghost",
"password": "……",
"database": "ghost"
},
"pool": {
"min": 0,
"max": 10,
"idleTimeoutMillis": 60000
}
}
}
注意 pool 这一段。Ghost 默认的连接池配置不一定适合低流量的站,写清楚比较省事——具体原因可以看另一篇《MySQL 连接池的坑》。
五、备份
自己管服务器,备份就得自己负责。至少要备两样东西:
- 数据库:用
mysqldump导出一份 SQL /opt/ghost/content:图片、上传的文件和主题
特别是主题目录。用现成主题还好,自己改过的主题不备份,哪天手滑就白改了。改动之前先 cp 一份带时间戳的备份,成本几乎为零,救命的次数不少。
六、小结
整个流程其实不复杂:起容器、挂数据、配反代、接数据库。真正花时间的不是「怎么装」,而是「装完之后怎么让它稳定跑着不出事」——连接池、备份、证书续期,这些才是自己管服务器的日常。
换来的是:数据在自己手里,前端想怎么改就怎么改。
评论