Typecho 1.3.0 新版本尝鲜 - docker 容器部署
前言
Typecho 1.3.0 之前跟 outline 一起安装好了,一直没时间去整理,并且安装过程中的问题也不少。最近有时间开始解决问题,也顺便把基本的 docker 容器部署的方案整理一下。
docker 项目配置文件和解决方案主要来自于 deepseek,个人主要调整一些配置,还有调通服务。
PS:不建议普通用户升级,尤其是主题和插件重度使用者。
docker 部署 Typecho 1.3.0
docker compose 配置文件 /root/typecho_project/docker-compose.yml:
services:
typecho:
image: joyqi/typecho:nightly-php8.2-apache # 使用包含PHP 8.2和Apache的镜像[4](@ref)
container_name: typecho-app
restart: always
depends_on:
- typecho-db
environment:
- TIMEZONE=Asia/Shanghai
- MAX_POST_BODY=64M
- TYPECHO_DB_HOST=typecho-db
- TYPECHO_DB_PORT=3306
- TYPECHO_DB_NAME=typecho
- TYPECHO_DB_USER=typecho
- TYPECHO_DB_PASSWORD=xxxxxxxxx # 请修改为强密码[5](@ref)
- TYPECHO_DB_DATABASE=typecho
- TYPECHO_DB_ENGINE=InnoDB # 可选,指定数据库引擎
- PHP_UPLOAD_MAX_FILESIZE=64M
- PHP_POST_MAX_SIZE=64M
- PHP_MEMORY_LIMIT=256M
# ports:
# - "8080:80" # 将宿主机的8080端口映射到容器的80端口[3,8](@refi)
expose:
- "80"
volumes:
- ./typecho-uploads:/app/usr/uploads # 挂载上传目录,便于持久化主题、插件和上传的文件[1,4](@ref)
- ./typecho-themes:/app/usr/themes # 主题
- ./typecho-plugins:/app/usr/plugins # 插件
- ./typecho-config.inc.php:/app/config.inc.php # 可选,挂载自定义配置文件[1](@ref)
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost/"]
interval: 30s
timeout: 10s
retries: 3
networks:
- internal
- shared
typecho-db:
image: mysql:8.0 # 使用MySQL 8.0镜像[5](@ref)
container_name: typecho-mysql
restart: always
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: xxxxxxxx # 请修改并妥善保管
MYSQL_DATABASE: typecho
MYSQL_USER: typecho
MYSQL_PASSWORD: xxxxxxxx # 需与typecho服务中的配置一致[5](@ref)
volumes:
- typecho-mysql-data:/var/lib/mysql # 使用命名卷持久化数据库数据[5,7](@ref)
- ./mysql/conf.d:/etc/mysql/conf.d:ro
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
interval: 30s
timeout: 10s
retries: 3
start_period: 40s
networks:
- internal
- shared
volumes:
typecho-mysql-data: # 定义命名卷,用于数据库持久化[7](@ref)
networks:
internal: # 创建自定义网络,便于容器间通信[3,5](@ref)
driver: bridge
shared:
external: true
name: shared-services
joyqi/typecho:nightly-php8.2-apache 是 deepseek 搜索到的,官方不知道在什么地方推荐过的 docker 镜像,内部包含了 php8.2 和 apache 服务,并且提供了最新的源码 /app/*。服务启动需要数据库服务,在环境变量中数据库连接信息(账号密码)。这里做了多个需要的 volumes 共享文件夹,其实也可以整个 app 映射出来,方便手动修改源码。
数据库采用了 mysql:8.0,之前是 mysql 5.5.3。可以指定 root 账号密码,还有一个独立的连接用户和密码。给 typecho 和 tyecho-db 都加了 healthcheck,这样在容器启动后会自动检测服务是否可用。command: --default-authentication-plugin=mysql_native_password 是后面另外一个项目 [使用 docker 部署一个 laravel 5.2 的项目
][1],完整导入数据库时做的兼容处理,重新安装不需要修改。
networks 网络部分增加了一个共享网络 shared-services,是为了让 mysql 数据库可以被其他的服务复用。需要提供对外服务的,就在服务的网络部分增加一个共享网络。
配置 https-portal 访问
之前 outline 项目安装过 https-portal 的镜像,该镜像可以自动对配置的域名进行 SSL 证书申请,非常适合当前这种 3 个月就要重新搞的测试证书情况。
https-portal:
image: steveltn/https-portal:1
...
environment:
DOMAINS: 'xx.seasidecrab.com -> http://outline:3000, blog.seasidecrab.com -> http://typecho:80'定义之后发现,博客的域名 blog 无法正常访问到。
通过指令确认 blog 域名没有生成相应的配置文件:docker exec outline-https ls -la /etc/nginx/conf.d/,查询环境变量 DOMAINS 也没有生成对应的映射关系:
docker inspect outline-https --format='{{range .Config.Env}}{{println .}}{{end}}' | grep DOMAINS
docker exec outline-https env | grep DOMAINS
DOMAINS=xx.seasidecrab.com -> http://outline:3000最终发现是域名指向的服务地址有问题,http://typecho:80 中 typecho 是服务名或者容器名,端口使用 expose 端口即可(处于共享网络内)。
把域名指向 typecho 服务,blog.seasidecrab.com -> http://typecho:80,又报错:
nginx: [emerg] host not found in upstream "typecho" in /etc/nginx/conf.d/blog.seasidecrab.com.ssl.conf:36
[cont-init.d] 20-setup: exited 0.
[cont-init.d] 30-set-docker-gen-status: executing...
[cont-init.d] 30-set-docker-gen-status: exited 0.
[cont-init.d] done.
[services.d] starting services
[services.d] done.
nginx: [emerg] host not found in upstream "typecho" in /etc/nginx/conf.d/blog.seasidecrab.com.ssl.conf:36
s6-svscanctl: fatal: unable to control /var/run/s6/services: supervisor not listening
[cont-finish.d] executing container finish scripts...
[cont-finish.d] done.
[s6-finish] waiting for services.
[s6-finish] sending all processes the TERM signal.deepseek 的解析是:
https-portal 容器无法解析 Docker 网络内的主机名!
https-portal 容器没有正确连接到共享网络!
很可能的问题是:typecho 容器根本没有连接到 shared-services 网络!
测试确实不在共享网络里:
docker inspect outline --format='{{.NetworkSettings.Networks.shared-services.IPAddress}}' 2>/dev/null || echo "typecho 不在 shared-servic
es 网络中!"
typecho 不在 shared-services 网络中!
docker inspect typecho --format='{{.NetworkSettings.Networks.shared-services.IPAddress}}' 2>/dev/null || \
echo "typecho 不在 shared-services 网络中!"
typecho 不在 shared-services 网络中!检查确定 typecho 服务下的 networks 没有添加 shared 共享网络(别称,项目配置 yml 最下面有定义)
networks:
- internal
- shared添加之后重启更新,OK!
连接数据库
此时 typecho 访问报错:Error establishing a database connection。检查发现是数据库连接配置的问题,因为使用的是镜像自带的最新的源码,所以默认配置需要修改成 typecho-db 定义的账号密码。之后得创建数据库,不然还是会连接报错。
到这里有两种备份方法,一种是原来的数据库全量保存备份到新的库里,另一种是从管理后台备份管理里导出一份。注意:两者是有很大区别的,全量备份可以保留一些系统配置、插件配置等等,而后台导出的备份仅是文章、独立页面、评论等数据。
使用的是 typecho 后台的一个备份功能,从 mysql 5.5 到 mysql 8.0,然后报错了:
恢复过程中遇到如下错误: SQLSTATE[22001]: String data, right truncated: 1406 Data too long for column 'title' at row 1这是 MySQL 5.5 到 8.0 的兼容性问题!字符集编码差异导致的
根本原因: MySQL 5.5 默认字符集是 utf8(实际上是 utf8mb3,最多3字节),而 MySQL 8.0 的 utf8mb4(最多4字节)对某些特殊字符的处理不同。
使用了方案3:临时禁用严格模式(最快速):
cd /root/typecho_project
# 1. 导入前临时禁用严格模式
source .env
docker compose exec db mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "
SET GLOBAL sql_mode = 'NO_ENGINE_SUBSTITUTION';
"
# 2. 恢复数据(现在应该能成功)
docker compose exec -T db mysql -u root -p"${MYSQL_ROOT_PASSWORD}" < your_backup.sql
# 这里从后台导入数据
# 3. 恢复严格模式(可选)
docker compose exec db mysql -u root -p"${MYSQL_ROOT_PASSWORD}" -e "
SET GLOBAL sql_mode = 'STRICT_TRANS_TABLES,NO_ENGINE_SUBSTITUTION';
" 本作品采用 知识共享署名-相同方式共享 4.0 国际许可协议 进行许可。
海滨擎蟹
微信
支付宝