腾讯云 Ubuntu 服务器部署 Typecho 全流程实战
从零开始在全新 Ubuntu 24.04 腾讯云服务器上用 Docker Compose 部署 Typecho 博客,并解决途中遇到的所有问题。本文按完整流程逐步记录,附每一步的操作命令、遇到的问题和对应解决方案。
目录
- 环境概览
- 第一步:安装 Docker 与 Compose
- 第二步:搭建项目目录与配置文件
- 第三步:下载 Typecho 源码
- 第四步:启动容器并验证
- 常见问题与解决方案(重点)
- 最终成果与常用命令
1. 环境概览
| 项目 | 值 |
|---|---|
| 操作系统 | Ubuntu 24.04.4 LTS |
| 云服务商 | 腾讯云 |
| 服务器架构 | 50G 磁盘 / 1.9G 内存 |
| 虚拟化 | Docker + Docker Compose |
| Typecho 版本 | v1.3.0(latest) |
| 数据库 | MariaDB 11 |
| Web 服务器 | Nginx 1.27 |
| PHP | 8.3-fpm |
目标架构:三个 Docker 容器(Nginx + PHP-FPM + MariaDB),通过 Compose 统一编排,Typecho 源码挂载共享。
2. 第一步:安装 Docker 与 Compose
2.1 安装 Docker
腾讯云默认源里没有 Docker,官方安装脚本是:
curl -fsSL https://get.docker.com | sh⚠️ 遇到的问题:
curl: (35) Recv failure: Connection reset by peer原因:get.docker.com 域名在服务器上无法连通(网络受限)。
✅ 解决方案:改用 Ubuntu 官方 apt 源安装 Docker:
sudo apt-get update
sudo apt-get install -y docker.io docker-compose-v2验证安装:
docker --version # Docker version 29.1.3
docker compose version # Docker Compose version 2.40.3将当前用户加入 docker 组,避免日后每次敲 sudo:
sudo usermod -aG docker ubuntu注:加入 docker 组需要重新登录后才生效,本流程后续用 sudo 操作。
3. 第二步:搭建项目目录与配置文件
3.1 创建项目目录
mkdir -p /home/ubuntu/typecho/www结构规划:
/home/ubuntu/typecho/
├── docker-compose.yml # 容器编排
├── nginx.conf # Nginx 站点配置
├── daemon.json # Docker 镜像加速(临时)
├── docker-php/ # 自定义 PHP 镜像
│ └── Dockerfile
└── www/ # Typecho 源码(挂载共享)3.2 编写 docker-compose.yml
services:
db:
image: mariadb:11
container_name: typecho-db
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD: typecho_root_pwd
MARIADB_DATABASE: typecho
MARIADB_USER: typecho
MARIADB_PASSWORD: typecho_pass
volumes:
- ./db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 5s
timeout: 5s
retries: 20
php:
build: ./docker-php
container_name: typecho-php
restart: unless-stopped
depends_on:
db:
condition: service_healthy
volumes:
- ./www:/var/www/html
web:
image: nginx:1.27
container_name: typecho-web
restart: unless-stopped
depends_on:
- php
ports:
- "8080:80"
volumes:
- ./www:/var/www/html
- ./nginx.conf:/etc/nginx/conf.d/default.conf:ro3.3 编写 PHP 自定义镜像(Dockerfile)
PHP 官方镜像不带 Typecho 需要的扩展,需要自行编译:
FROM php:8.3-fpm
# 替换为国内 Debian 源加速
RUN sed -i 's/deb.debian.org/mirrors.ustc.edu.cn/g' /etc/apt/sources.list.d/debian.sources
# 安装 PHP 扩展编译所需的系统依赖
RUN apt-get update && apt-get install -y --no-install-recommends \
libonig-dev \
libgd-dev \
libpng-dev \
libjpeg-dev \
libfreetype-dev \
libzip-dev \
libxml2-dev \
&& rm -rf /var/lib/apt/lists/*
# 配置并编译 PHP 扩展
RUN docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install pdo_mysql mbstring gd exif zip
WORKDIR /var/www/html3.4 编写 nginx.conf
server {
listen 80;
server_name _;
root /var/www/html;
index index.php index.html index.htm;
client_max_body_size 30M;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# 处理 PHP 文件及 PATH_INFO 路由(如 /index.php/action/login)
location ~ ^(.+\.php)(.*)$ {
try_files $1 =404;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$1;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_index index.php;
fastcgi_pass php:9000;
}
location ~ /\. {
deny all;
}
}4. 第三步:下载 Typecho 源码
4.1 查询最新版本
curl -s https://api.github.com/repos/typecho/typecho/releases/latest | grep tag_name
# "tag_name": "v1.3.0"4.2 下载并解压
cd /home/ubuntu/typecho
wget https://github.com/typecho/typecho/releases/download/v1.3.0/typecho.zip
sudo apt-get install -y unzip
unzip -o typecho.zip -d www压缩包中的 index.php、install.php、admin/、usr/、var/ 等文件即 Typecho 程序本体。
⚠️ 遇到的问题:
unzip: command not found✅ 解决方案:服务器缺少 unzip 工具,用 apt 安装:
sudo apt-get install -y unzip5. 第四步:启动容器并验证
5.1 启动
cd /home/ubuntu/typecho
sudo docker compose up -d首次启动会拉取三个镜像(mariadb、nginx、php),并构建自定义 PHP 镜像。
5.2 验证
sudo docker compose ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
NAME STATUS PORTS
typecho-db Up (healthy) 3306/tcp
typecho-php Up 9000/tcp
typecho-web Up 0.0.0.0:8080->80/tcp检查 PHP 扩展与数据库连接:
sudo docker exec typecho-php php -m | grep -E "pdo_mysql|mbstring|gd|exif|zip"
# exif gd mbstring pdo_mysql zip
sudo docker exec typecho-php php -r "new PDO('mysql:host=db;dbname=typecho','typecho','typecho_pass'); echo 'OK';"
# OK浏览器访问 http://服务器IP:8080 应看到 Typecho 安装向导。
6. 常见问题与解决方案(核心章节)
这一章汇总了部署过程中遇到的全部问题,按出现的顺序整理。
6.1 Docker Hub 镜像拉取超时
现象:docker compose up 拉取镜像超时:
Pulling db (mariadb:11)...
Error response from daemon: Get https://registry-1.docker.io/v2/: i/o timeout原因:服务器访问 Docker Hub(registry-1.docker.io)网络受限,和 get.docker.com 不通是同一类问题。
✅ 解决:配置国内镜像加速器。
// /etc/docker/daemon.json
{
"registry-mirrors": [
"https://docker.m.daocloud.io",
"https://docker.1ms.run",
"https://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"https://mirror.baidubce.com"
]
}sudo cp daemon.json /etc/docker/daemon.json
sudo systemctl restart docker
# 验证
sudo docker info | grep -A6 "Registry Mirrors"重启后重新 docker compose up -d 即可成功拉取。
6.2 PHP 扩展编译失败(mbstring 缺 oniguruma)
现象:容器启动后网页返回 502 Bad Gateway,日志显示:
configure: error: Package requirements (oniguruma) were not met:
Package 'oniguruma', required by 'virtual:world', not found原因:Typecho 需要 mbstring 扩展,但 PHP 镜像里没有编译它所需的基础库(libonig)。
✅ 解决:改用 Dockerfile 方式,先把编译依赖装好再编译扩展(见上文 Dockerfile)。这种方式把 apt 源也换成了中科大国内源,解决网络慢的问题。
6.3 腾讯云安全组未开放端口,公网访问不了
现象:本机 curl localhost:8080 正常(302),但从公网 IP 无法访问。
原因:腾讯云在云控制台层面用安全组过滤入站流量,8080 默认未放行(服务器内 ufw 未启用、iptables 也不控端口,不是服务器本身的问题)。
✅ 解决:登录腾讯云控制台 → 云服务器 → 安全组 → 添加入站规则:
协议: TCP
端口: 8080
来源: 0.0.0.0/0
策略: 允许6.4 安装程序提示 uploads 目录不可写
现象:
提示上传目录无法写入,请手动将安装目录下的 /usr/uploads 目录的权限设置为可写
原因:源码解压后由 ubuntu 用户拥有(drwxr-xr-x ubuntu ubuntu),而 PHP 容器运行时用户是 www-data,对该目录没有写权限。
✅ 解决:设置目录权限为所有人可读写执行:
sudo chmod -R 777 /home/ubuntu/typecho/www/usr/uploads
sudo chmod -R 777 /home/ubuntu/typecho/www/usr6.5 安装程序无法自动创建 config.inc.php
现象:
安装程序无法自动创建 config.inc.php 文件
原因:config.inc.php 要写在根目录 /var/www/html 下,该目录同样没有 www-data 写权限。
✅ 解决:放开根目录写权限:
sudo chmod 777 /home/ubuntu/typecho/www6.6 后台登录 404(PATH_INFO 路由问题)
现象:后台登录请求 /index.php/action/login 返回 404,后台无法登录。
原因:Typecho 使用 PATH_INFO 路由(/index.php/action/login 这种带路径参数的写法)。最初的 nginx.conf 用 location /index.php {} 加 try_files $uri =404,它把整个路径当成一个真实文件去寻找,找不到就 404。正则 \.php$ 也只匹配以 .php 结尾的 URL,匹配不到这类带后缀路径的请求。
✅ 解决:修改 nginx.conf,用能匹配 PATH_INFO 的正则,并正确处理路径参数:
location ~ ^(.+\.php)(.*)$ {
try_files $1 =404;
include fastcgi_params;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_param SCRIPT_FILENAME $document_root$1;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_index index.php;
fastcgi_pass php:9000;
}⚠️ 附带坑:修改 nginx.conf 后 nginx -s reload 不生效。原因是 write_file 改写文件时会更换文件的 inode,而 Docker bind mount 仍指向旧 inode,容器内读到的还是旧配置。需要重启容器让挂载刷新:
cd /home/ubuntu/typecho && sudo docker compose restart web修正后 /index.php/action/login 从 404 变为 302(正常跳转)。
6.7 Handsome 主题导致白屏
现象:切换 Handsome 主题后首页白屏,实际是 PHP 抛错但被主题自身屏蔽错误显示。
问题一:旧类名未注册
日志报错:
ERROR: Class "Widget_Abstract_Metas" not found原因:Handsome 主题大量使用旧式类名(如 Widget_Abstract_Metas),而 Typecho 1.3.0 已改用命名空间写法(\Widget\Base\Metas)。虽然 Typecho 定义了 __TYPECHO_CLASS_ALIASES__ 常量数组描述映射,但没有实际执行 class_alias(),旧类名并未真正注册。
✅ 解决:在主题 functions.php 开头补充别名注册:
// 兼容 Typecho 1.3.0:注册旧类名别名
$classAliases = defined('__TYPECHO_CLASS_ALIASES__') ? __TYPECHO_CLASS_ALIASES__ : [];
foreach ($classAliases as $oldName => $newName) {
if (!class_exists($oldName) && class_exists($newName)) {
class_alias($newName, $oldName);
}
}问题二:PHP 8.3 方法签名不兼容
开启错误显示后:
Fatal error: Declaration of Handsome_Widget_Comments_Archive::select():
Typecho\Db\Query must be compatible with Widget\Base\Comments::select(...$fields):
Typecho\Db\Query原因:PHP 8 起方法签名必须与父类兼容。父类 Widget\Base\Comments::select(...$fields) 带可变参数,而主题里对应的方法写成 select(): Query,缺少 ...$fields,PHP 8.3 视为致命错误。
✅ 解决:修正签名,补上可变参数:
public function select(...$fields): Typecho\Db\Query6.8 Handsome 主题授权拦截
现象:整站(含首页)显示 Handsome 主题的授权校验页,要求在授权平台添加域名。
原因:Handsome 是付费主题,首次使用需要到 https://auth.ihewro.com/admin 授权平台绑定博客域名,并在后台主题设置页刷新授权状态。此外还要登录后台手工触发一次授权接口。
✅ 解决:按提示在授权平台添加域名 → 打开后台 Handsome 外观设置界面刷新,授权通过后正常显示。
7. 最终成果与常用命令
7.1 访问地址
- 网站首页:
http://IP:8080/ - 后台:
http://IP:8080/admin/login.php - 文章固定链接:
http://IP:8080/index.php/archives/{cid}/
(暂未开启伪静态 rewrite,所以链接带 index.php 前缀。)
7.2 数据库连接信息(安装时填写)
| 参数 | 值 |
|---|---|
| 数据库地址 | db(Docker 内部网络域名) |
| 端口 | 3306 |
| 数据库名 | ****** |
| 用户名 | ****** |
| 密码 | ****** |
7.3 常用管理命令
cd /home/ubuntu/typecho
sudo docker compose ps # 查看容器状态
sudo docker compose logs -f # 查看实时日志
sudo docker compose restart web # 重启某容器
sudo docker compose down # 停止所有容器
sudo docker compose up -d # 启动所有容器
sudo docker exec typecho-db mariadb -utypecho -ptypecho_pass typecho # 进数据库7.4 关键目录
/home/ubuntu/typecho/
├── www/ # 网站源码(改这里=改网站)
├── db_data/ # 数据库数据(备份这个)
├── docker-compose.yml # 编排配置
├── nginx.conf # Nginx 站点配置
└── docker-php/Dockerfile # 自定义 PHP 镜像结语
整个部署过程最大的体会是:看似简单的 "一条 docker compose up 拉起来",实际坑都在网络和兼容性上——Docker Hub 网络受限、PHP 扩展编译依赖、腾讯云安全组、PATH_INFO 路由、旧主题与新版 Typecho / PHP 8.3 的兼容,每一个都需要对症排查。
搞定这些之后,Typecho + Docker 的组合非常轻量顺手:升级、迁移、备份都快,以后换机器一个 compose 文件就能复现整个环境。希望这篇实战记录对你有帮助。