
FrankenPHP 这名字我听了快小半年了,
总有人夸它是 “PHP 环境里的轻量狠角色”,把 PHP 和 Caddy 服务器捆一块儿,
不用再像以前那样费劲搭 Nginx+PHP-FPM 的组合,
还能直接跑 PHP 脚本,内存占用也比老一套少不少。
之前总觉得 “老环境用着顺手,没必要折腾”,
可今儿看着 PHP8.5 的新特性,突然想试试了...
感觉网上的文档确实有点少呢,记录下吧。
我用的是ubuntu22.04LTS,所以直接用docker来跑,
毕竟frankenphp是绑定caddy和php的,哪天升级,只要改一下配置build一下就好了
安装Docker
这个老一套了,就是装装装...
# 更新系统
sudo apt update && sudo apt upgrade -y
# 安装 Docker 依赖
sudo apt install -y ca-certificates curl gnupg lsb-release
# 添加 Docker 官方 GPG 密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
# 添加 Docker 软件源
echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 Docker 和 Docker Compose
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin
# 验证安装(无报错则成功)
docker --version
docker compose version
# (可选)添加当前用户到 docker 组,避免每次用 sudo
sudo usermod -aG docker $USER
newgrp docker # 立即生效(无需重启)
建立用户组和用户
先查看是否存在用户组和用户
id www如果存在,会显示www用户名称,id和对应的用户组名称,id
就可以直接跳过,下一步了,如果没有,就建立新用户和组
# 创建www用户组
sudo groupadd www
# 创建www用户,并且取消登陆权限
sudo useradd -g www -M -s /sbin/nologin www创建Web目录
我个人习惯于web目录放在/www下,所以
# 创建目录
sudo mkdir /www && cd /www
# 创建项目目录
sudo mkdir html
# 创建caddy数据目录,用来存放证书之类的
sudo mkdir caddy_data
# 创建caddy日志目录
sudo mkdir caddy_logs
# 如果你要使用sqlite,请再建一个db,用来放置数据库文件
sudo mkdir db编写Docker文件
FROM dunglas/frankenphp:1.9.1
# 安装系统依赖(解决 gd、curl 等扩展的依赖问题)
RUN apt-get update && apt-get install -y --no-install-recommends \
libpng-dev \
libjpeg-dev \
libcurl4-openssl-dev \
libxml2-dev \
libzip-dev \
&& rm -rf /var/lib/apt/lists/*
# 安装 PHP 扩展(只保留易安装、核心必需的扩展)
RUN install-php-extensions \
mysqli \
pdo_mysql \
pdo_pgsql \
redis \
gd \
curl \
mbstring \
xml \
zip \
json \
sqlite3 \
opcache \
exif \
fileinfo
# 可选:复制你本地的 php.ini 到容器,可选,因为frankenphp支持用环境变量设置
# COPY ./php.ini /usr/local/etc/php/php.ini这里的php.ini,如果你要自定义的比较多,建议你来写,目前frankenphp1.9.1带的php版本是8.4.15,要php.ini去官网下载源码里把php.ini.product改成php.ini放在这里就好
编写 Caddyfile
比如你的域名是 a.com
a.com {
# 无需手动写 :443,Caddy 默认 HTTPS 端口就是 443
# 自动监听 IPv4+IPv6(如需强制仅 IPv4,保留 bind 0.0.0.0 即可)
# bind 0.0.0.0 # 可选:如需禁用 IPv6,取消注释这行
# 禁用 Caddy 自动 HTTPS(证书由 EdgeOne/Cloudflare 处理)
# 当你开了EO加速以及CF的小黄云时,就把这个打开,因为验不过证书
# 避免 Caddy 自动申请 Let's Encrypt 证书
# tls off
# 如果你有CF15年证书,就这么写,指定好证书和私钥,
# tls /etc/caddy/certs/bsay.de/cf-cert.pem /etc/caddy/certs/bsay.de/cf-key.key
# Typecho 根目录(保持不变)
root * /app
# 显式定义静态资源匹配器(Caddy 2.10 语法,保持不变)
@static {
file # 匹配实际存在的文件(排除 PHP 动态路径)
# 列出所有静态文件后缀(按需增减)
path *.css *.js *.html *.htm *.json *.xml *.txt
path *.png *.jpg *.jpeg *.gif *.ico *.svg *.webp *.avif
path *.woff *.woff2 *.ttf *.eot *.otf
}
handle @static {
file_server
encode br
# HTTPS 环境下静态资源缓存策略(immutable 更安全)
header Cache-Control "public, max-age=31536000, immutable"
# 强制 HSTS:让浏览器永久优先用 HTTPS(推荐)
header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
}
# Typecho 友好伪静态(保持不变,核心路由)
try_files {path} {path}/ /index.php?{query}
# 站点压缩(保持不变,兼容旧版 Caddy)
encode zstd br gzip
# FrankenPHP PHP 配置(保持不变,Caddy 会自动让 PHP 处理 HTTPS 请求)
php_server
# 可选:自定义 PHP 版本(如你用 PHP8.5,可指定,需 FrankenPHP 支持)
# php_server {
# php_fastcgi unix//run/php/php8.5-fpm.sock # 如需绑定 FPM sock,按需调整
# }
# HTTPS 访问日志(明确区分 HTTPS 日志)
log {
output file /var/log/caddy/https-access.log
format json
level info
}
# HTTPS 安全增强头(推荐,无需额外依赖,直接生效)
header X-Content-Type-Options "nosniff"
header X-Frame-Options "SAMEORIGIN" # 禁止跨域嵌套 iframe
header X-XSS-Protection "1; mode=block"
header Referrer-Policy "strict-origin-when-cross-origin" # 合理控制 Referrer 信息
}
# 强制 HTTP (80) 跳转 HTTPS(必加,让用户自动访问加密链接)
http://a.com {
# 301 永久重定向,不丢失 SEO 权重
redir https://{host}{uri} permanent
# 可选:记录 HTTP 跳转日志
log {
output file /var/log/caddy/http-redirect.log
format json
level info
}
}最后编写docker-compose.yml
services:
frankenphp:
build: . # 使用本地的Dockerfile进行打包
container_name: frankenphp-typecho # 这个是你的容器名字,你自己起
user: "www:www" # 这里是容器里需要运行的用户组
restart: always
ports:
- "80:80"
- "443:443"
environment:
- PHP_WORKER_MODE=true # 开启worker模式
- APP_RUNTIME_DIR=/app # 这是指的运行时目录,如果是多项目,就注释
# 用环境变量来设置PHP,而不是引入php.ini
- PHP_MEMORY_LIMIT=128M
- PHP_UPLOAD_MAX_FILESIZE=50M
- PHP_POST_MAX_SIZE=50m
volumes:
# 映射 Typecho 源码,将容器的app目录设置为/www/html
- ./html:/app
# 映射自定义的 Caddyfile
- ./Caddyfile:/etc/caddy/Caddyfile
# 使用命名卷引用,存放证书和配置
- caddy_data:/data
- caddy_logs:/var/log/caddy
# 如果你使用sqlite,请一定映射SQLite数据目录(防止数据丢失)
- db:/app/usr/data
networks:
- typecho_net
# 命名卷定义
volumes:
# caddy_data 存放证书和 Caddy 自动配置
caddy_data:
# caddy_logs 存放日志文件
caddy_logs:
networks:
typecho_net:PS. 请不要用Docker跑数据库...
数据库选择
本地数据库
# 安装MySQL
sudo apt install mysql-server -y
# 安装PGSQL
sudo apt install postgresql postgresql-client -y远程数据库
推荐1: aiven.io,免费1G的mysql/pgsql,选一个离你小鸡近的节点就好了
推荐2: supabase.com,免费500MB的pgsql,一样,选一个离你近的节点
其它
请将你的博客放到html目录下,即 html目录里直接就是 typecho根目录,而非叫typecho的文件夹
给对应目录的权限,因为指定了容器的用户
# 同时给几个目录给www:www
sudo chown www:www -R /www/html /www/caddy_data /www/caddy_logs
# 如果你还使用了sqlite,还要给db也指定为www
sudo chown www:www -R /www/db最终的目录结构
/www
├── Caddyfile # Caddy配置文件
├── Dockerfile # Docker配置文件
├── caddy_data # Caddy的数据文件
├── caddy_logs # Caddy的日志文件
├── docker-compose-yml # docker-compose文件
├── php.ini # php.ini,如果你需要
└── html # 博客根目录命令说明
所有命令请在/www下运行
# 启动
docker compose up -d
# 停止
docker compose down -v
# 重启
docker compose restart
# 查看日志
docker logs [你的容器名字]
# 重新构建启动(除非你修改了Dockerfile,才用这个启动)
docker compose up -d --build 好了,你现在只要运行启动命令,再访问域名就好了...
如何知道他是否启用了呢,可以查看phpinfo,

暂无评论