本文记录 Typecho 博客从容器构建、数据库接入、反向代理到 HTTPS 上线的完整流程,并整理部署过程中出现的问题及对应处理方式。
1. 部署架构
博客采用 Typecho 1.3.0,并使用 Butterfly 风格的 Typecho 主题。
当前请求链路如下:
用户浏览器
-> blog.sjhibqi.cn
-> Nginx HTTPS 反向代理
-> blog-typecho 容器
-> site-mysql 容器
-> personal_blog 数据库博客使用独立域名:
https://blog.sjhibqi.cn/MySQL 和 Docker 网络由服务器上的多个站点共用,但博客使用独立的数据库、数据库用户、容器和镜像。
2. 服务器目录
博客部署目录为:
/opt/typecho-blog主要结构如下:
/opt/typecho-blog
├── html
│ ├── admin
│ ├── usr
│ │ ├── plugins
│ │ ├── themes
│ │ └── uploads
│ ├── var
│ └── config.inc.php
├── Dockerfile
├── docker-compose.yml
├── docker-entrypoint.sh
└── .envhtml 目录挂载到容器的 /var/www/html,用于保存:
- Typecho 程序文件
- 站点配置
- 主题文件
- 插件文件
- 上传资源
容器重建不会删除宿主机上的 html 目录。
3. 构建 Typecho 镜像
Typecho 运行环境基于 PHP 8.2 和 Apache。
镜像中启用了以下组件:
mysqlipdo_mysql- Apache Rewrite 模块
当前镜像名称为:
blog-typecho:latest当前容器名称为:
blog-typecho容器通过 Compose 管理,并将站点目录挂载到 Apache 的网站根目录:
services:
blog-typecho:
build:
context: .
dockerfile: Dockerfile
image: blog-typecho:latest
container_name: blog-typecho
restart: unless-stopped
env_file:
- .env
ports:
- "${TYPECHO_HOST_PORT:-8091}:80"
volumes:
- ./html:/var/www/html
networks:
- site_net
networks:
site_net:
external: true
name: site-netsite-net 是服务器上的共享 Docker 网络,Nginx、博客和数据库通过该网络通信。
4. 配置数据库
数据库运行在共享 MySQL 容器中:
site-mysql博客使用独立的数据库和用户:
数据库:personal_blog
用户:blog_appMySQL 数据保存在 Docker Volume 中:
site-mysql-dataTypecho 的 config.inc.php 使用以下连接关系:
数据库主机:site-mysql
数据库名称:personal_blog
数据库用户:blog_app数据库密码只保存在服务器配置中,不写入文章或代码仓库。
5. 启动博客容器
在部署目录执行 Compose 启动:
cd /opt/typecho-blog
docker compose up -d启动后可检查容器状态:
docker ps --filter name=blog-typecho
docker logs blog-typecho容器内部由 Apache 提供 HTTP 服务,宿主机默认映射到 8091 端口。
正式访问流量不直接使用该端口,而是经过 Nginx 反向代理。
6. 配置 Nginx 反向代理
博客域名为:
blog.sjhibqi.cnNginx 根据 server_name 将博客请求转发到 blog-typecho 容器:
server {
listen 443 ssl;
server_name blog.sjhibqi.cn;
location / {
proxy_pass http://blog-typecho:80;
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 https;
}
}其中:
Host用于保留原始域名。X-Real-IP用于传递客户端地址。X-Forwarded-For用于保留代理链路。X-Forwarded-Proto用于通知 Typecho 外部请求使用 HTTPS。
如果缺少 Host 或 X-Forwarded-Proto,可能出现后台跳转异常、HTTP 和 HTTPS 混用或静态资源地址错误。
7. 配置 HTTPS
HTTPS 使用 Let's Encrypt 证书。
证书文件路径为:
/etc/letsencrypt/live/sjhibqi.cn/fullchain.pem
/etc/letsencrypt/live/sjhibqi.cn/privkey.pem证书需要包含以下域名:
sjhibqi.cn
blog.sjhibqi.cnHTTP 入口保留 ACME 校验路径,其余请求跳转到 HTTPS:
server {
listen 80;
server_name blog.sjhibqi.cn;
location /.well-known/acme-challenge/ {
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}服务器通过定时任务执行证书续期。续期成功后重新加载 Nginx,使新证书生效:
定时任务
-> certbot renew
-> reload Nginx8. 部署和调整主题
线上主题目录为:
/opt/typecho-blog/html/usr/themes/butterfly主题部署后进行了以下调整:
- 静态资源使用 CDN
- 用户头像直接通过
src加载,不使用懒加载 - 未设置文章缩略图时不显示默认马赛克图片
- 增加网站 favicon
- 配置文章、标签和分类入口
- 配置备案信息
- 增加文章阅读量统计
- 修复空文章状态下初始化
views字段导致首页报错的问题
当前头像资源为:
/usr/uploads/2026/07/417480796.jpg?v=20260724主题的部分配置保存在数据库中。修改或重新安装主题时,需要同时检查数据库中的主题配置,避免头像、首页图片和导航链接被覆盖。
9. 阅读量统计
每篇文章的阅读量保存在 Typecho 内容表的 views 字段中。
访问文章详情页时,主题执行以下逻辑:
- 获取当前文章 ID。
- 检查浏览器会话 Cookie 中是否已经记录该文章。
- 未记录时,将文章阅读量增加一次。
- 将文章 ID 写入 Cookie。
- 同一浏览器会话内重复刷新不重复计数。
该方案按浏览器会话去重,不按账号或 IP 去重。无痕窗口、新设备、Cookie 被清除或不保留 Cookie 的爬虫可能产生新的计数。
侧栏的“本站总访问量”为已发布文章阅读量之和,并使用缓存减少数据库查询。
10. 备份与回滚
修改以下内容前需要创建备份:
config.inc.php.envdocker-compose.yml- Butterfly 主题文件
usr/uploadspersonal_blog数据库
现有备份目录为:
/opt/backups/20260724-naming数据库数据实际保存在 site-mysql-data Volume 中。数据库 dump 用于逻辑恢复,Volume 用于容器级持久化。
主题文件修改前应单独复制原文件。回滚时恢复原文件即可,不需要重建整个站点。
11. 部署过程中出现的问题
| 现象 | 原因 | 处理方式 |
|---|---|---|
| HTTPS 配置完成后外网无法访问 | 云服务器安全组未开放 TCP 443 | 增加 443 入方向规则 |
| 页面跳转到 HTTP | Typecho 站点地址或代理协议头配置错误 | 将站点地址设为 HTTPS,并传递 X-Forwarded-Proto |
| 静态资源地址异常 | 反向代理未传递原始 Host | 配置 proxy_set_header Host $host |
| 修改主题配置后首页返回 500 | 主题配置内容或格式不符合预期 | 恢复主题配置并检查错误日志 |
| 删除全部文章后首页返回 500 | 主题通过第一篇文章判断 views 字段,空表时无法取得文章 | 改为直接检查数据库表结构 |
| 首页出现默认马赛克缩略图 | 主题在文章无图片时使用默认图 | 调整缩略图逻辑,无真实图片时不输出缩略图 |
| 用户头像加载异常 | 头像使用懒加载属性,但相关脚本未正确处理 | 将头像调整为标准 src 加载 |
| 网站图标为空 | 主题 favicon 配置未设置 | 增加默认 64×64 PNG favicon |
| 更改容器名称后服务无法通信 | Compose、Nginx 和 Docker 网络中的服务名未同步 | 统一使用 blog-typecho 和 site-net |
12. 上线验证
部署完成后需要检查以下项目:
curl -I http://blog.sjhibqi.cn/
curl -I https://blog.sjhibqi.cn/
curl -I https://blog.sjhibqi.cn/admin/预期结果:
- HTTP 自动跳转到 HTTPS。
- 博客首页返回
200。 - 后台入口返回登录页或跳转到登录页。
- CSS、JavaScript、图片和 favicon 返回
200。 - 发布文章后首页和文章详情页可以正常访问。
- 上传文件写入
html/usr/uploads。 - 容器重建后文章、配置和上传资源仍然存在。
13. 日常维护
后续维护主要包括:
- 通过 Typecho 后台发布和管理文章
- 定期备份
personal_blog数据库 - 定期备份
usr/uploads - 检查 HTTPS 证书续期状态
- 检查
blog-typecho和site-mysql容器状态 - 修改主题前备份目标文件
- 更新 Typecho 或主题后检查现有定制逻辑
- 定期验证首页、后台、静态资源和数据库连接
当前线上正式命名为:
容器:blog-typecho
镜像:blog-typecho:latest
数据库:personal_blog
数据库用户:blog_app
Docker 网络:site-net