在使用 Docker 部署现代版 Typecho 时,经常会遇到环境权限冲突、SSL 证书申请超时、以及国内服务器特有的“备案拦截”等坑点。

本教程使用 acme.sh 的 DNS 验证模式 + 高度集成的 rehiy/typecho 镜像,提供全场景适配方案,助你快速搭建一个自带安全小绿锁、极度稳定的 Typecho 博客。


阶段一:强制申请 Let's Encrypt HTTPS 证书

不论是国内还是国外服务器,使用常规的 HTTP 验证申请证书都容易因为端口占用或防火墙拦截报错 403 Forbidden。最稳妥的方式是利用 acme.sh 验证 DNS 记录。

1. 安装 acme.sh

# 替换为你的常用邮箱,接收证书过期通知
curl https://get.acme.sh | sh -s [email protected]

# 安装后重载环境变量,或者断开 SSH 重新连接
source ~/.bashrc

# 将默认 CA 切换为 Let's Encrypt(ZeroSSL 在国内极不稳定)
~/.acme.sh/acme.sh --set-default-ca --server letsencrypt

2. 申请证书(根据情况选择 A 或 B)

【方式 A】使用 Cloudflare API 全自动申请(推荐)

如果你域名托管在 Cloudflare,且 API Key 配置无误:

# 1. 登录 Cloudflare 获取 Global API Key,并在终端导出变量
export CF_Key="你复制的 37 位 Global API Key"
export CF_Email="你登录 Cloudflare 的邮箱"

# 2. 发起自动申请
~/.acme.sh/acme.sh --issue --dns dns_cf -d blog.ldlove.eu.org --force

(等待 120 秒验证成功即可进行下一步。)

【方式 B】纯手动添加 TXT 记录(万能绝招)

如果 API 调用报错(如 invalid domain),或你的域名不在大厂解析,可使用手动验证:

第 1 步:生成 TXT 验证要求

~/.acme.sh/acme.sh --issue --dns -d blog.ldlove.eu.org --yes-I-know-dns-manual-mode-enough-go-ahead-please

执行后,屏幕会输出类似信息:

Domain: _acme-challenge.blog.ldlove.eu.org
TXT value: rMwbm7fwJs-SmRvZpdOLUWj8...

第 2 步:去域名服务商后台添加解析
登录你的 DNS 控制台(如 Cloudflare / 阿里云),添加一条记录:

  • 类型: TXT
  • 名称/主机记录: _acme-challenge.blog
  • 内容/记录值: 刚才屏幕吐出的那一长串 TXT value

第 3 步:确认签发
等待约 1 分钟让 DNS 生效,然后回到终端执行:

~/.acme.sh/acme.sh --renew -d blog.ldlove.eu.org --yes-I-know-dns-manual-mode-enough-go-ahead-please

(看到绿色的 Cert success 表示签发完毕。)


阶段二:部署 Typecho 博客并注入证书

我们将使用集成了 SSL 和时区配置的优选镜像 rehiy/typecho

1. 建立数据挂载和证书存放目录

# 创建博客数据存放目录
mkdir -p /srv/myblog/home/certs

# 赋予读写权限,避免之后产生 Database Query Error
chmod -R 777 /srv/myblog/home

2. 提取证书并存入宿主机挂载目录

~/.acme.sh/acme.sh --installcert -d blog.ldlove.eu.org --ecc \
--key-file /srv/myblog/home/certs/key.pem \
--fullchain-file /srv/myblog/home/certs/cert.pem

3. 启动带 HTTPS 证书的 Docker 容器(请根据你的服务器地理位置选择)

确保执行前清理掉冲突的旧容器:docker rm -f typecho 2>/dev/null

【方案A】海外服务器(香港、台湾、日美等)

无备案限制,直接绑定标准 80 和 443 端口。

docker run -d \
  --name typecho \
  --restart always \
  -p 80:80 \
  -p 443:443 \
  -e TZ=Asia/Shanghai \
  -e SSL_CERT=/var/www/default/usr/home/certs/cert.pem \
  -e SSL_KEY=/var/www/default/usr/home/certs/key.pem \
  -v /srv/myblog/home:/var/www/default/usr/home \
  rehiy/typecho

访问方式:直接输入 https://blog.ldlove.eu.org

【方案B】中国大陆云服务器(阿里云、腾讯云等,且未做 ICP 备案)

规避备案拦截: 阿里云/腾讯云会监听 80443 端口的流量。如果探测到未备案域名,会强行阻断。我们将容器内的 443 端口映射到宿主机的非标准端口(如 8443)以绕过探测。

docker run -d \
  --name typecho \
  --restart always \
  -p 8080:80 \
  -p 8443:443 \
  -e TZ=Asia/Shanghai \
  -e SSL_CERT=/var/www/default/usr/home/certs/cert.pem \
  -e SSL_KEY=/var/www/default/usr/home/certs/key.pem \
  -v /srv/myblog/home:/var/www/default/usr/home \
  rehiy/typecho

访问方式:需要带端口后缀 https://blog.ldlove.eu.org:8443。记得去云服务器安全组放行对应端口。
(如果想去除端口号,需额外部署 Cloudflare Argo Tunnel 内网穿透隧道。)


阶段三:初始化安装与装载第三方主题

1. 网页端完成初始化

打开浏览器,访问你的博客地址(方案A正常访问,方案B带端口号)。
在安装向导中,数据库适配器务必选择 SQLite 3。填写管理员账号密码,完成安装。

2. 修复数据库权限(若出现 Database Query Error)

安装后如出现数据库查询报错,是因为宿主机和容器之间的账户权限冲突,导致 SQLite 写入失败。在服务器执行:

# 将容器内相关文件的权限重置归属给镜像默认运行账户 bin
docker exec typecho chown -R bin:bin /var/www/default/usr/home
chmod -R 777 /srv/myblog/home

(刷新网页即可恢复正常。)

3. 给 Typecho 安装现代主题(以 TypechoGlass 为例)

⚠️ 核心避坑:
很多镜像为了精简,会将网页读取的核心路径硬编码在容器内部。直接放进外部挂载的 themes 目录可能无法识别。必须直接将文件送入容器内部的 /var/www/default/usr/themes 目录!

# 1. 下载主题源码至服务器
cd /root
git clone https://github.com/Sandro-Z/TypechoGlass.git

# 2. 将主题直接塞进容器的正确隐藏路径
docker cp /root/TypechoGlass typecho:/var/www/default/usr/themes/TypechoGlass

# 3. 赋予读取权限,防止后台白屏不显示
docker exec typecho chown -R bin:bin /var/www/default/usr/themes/TypechoGlass
docker exec typecho chmod -R 755 /var/www/default/usr/themes/TypechoGlass

4. 启用主题

前往博客后台 https://你的域名(及端口)/admin,点击 控制台 -> 外观,即可看到 TypechoGlass,点击启用即可。