使用 FrankenPHP 将 PHP 应用打包为独立二进制文件:Embed 功能完整实战指南

发布时间:2026/9/15 10:16:54
使用 FrankenPHP 将 PHP 应用打包为独立二进制文件:Embed 功能完整实战指南
使用 FrankenPHP 将 PHP 应用打包为独立二进制文件Embed 功能完整实战指南【免费下载链接】frankenphp The modern PHP app server项目地址: https://gitcode.com/GitHub_Trending/fr/frankenphpFrankenPHP 提供了一项极具特色的能力将 PHP 应用的全部源码与静态资源、PHP 解释器以及生产级 Web 服务器 Caddy一并打包进一个自包含的静态二进制文件中。部署时你只需分发这一个文件无需在目标机器上安装 PHP、Composer 或任何 Web 服务器。本文以官方文档 docs/it/embed.md 为主体结合仓库中的 embed.go、build-static.sh 与两个静态构建 Dockerfile完整讲解应用准备、Linux/macOS 二进制构建、运行方式、PHP 扩展选择与构建定制读完后你可以亲手将一个 Symfony / Laravel 等任意 PHP 应用封装为可移植的单一可执行文件。嵌入原理一个二进制包含 PHP、Caddy 与应用FrankenPHP 之所以能把应用塞进二进制核心机制在 embed.go 中体现得淋漓尽致构建时应用目录被打包成app.tar并生成校验文件app_checksum.txt通过 Go 的//go:embed指令编译进二进制见 embed.go二进制启动时init()函数会把app.tar解压到系统临时目录os.TempDir()/frankenphp_校验和随后 FrankenPHP 与 Caddy 直接从该目录加载应用见 embed.go解压路径以校验和命名意味着不同内容的应用会落在不同目录可避免版本冲突你还可以在编译期通过-ldflags -X github.com/dunglas/frankenphp.EmbeddedAppPath/app指定固定的解压路径适用于应用内含 OPcache 文件缓存等引用绝对路径的预编译产物见 embed.go。正是这套构建期打包 运行期解压的设计让最终交付物变成单一二进制里面既有 PHP 解释器ZTS 线程安全模式也有 Caddy还包含你的整个应用。官方在 SymfonyCon 2023 上专门演示过这一特性对应文档第一段所述若你使用的是 Laravel 应用可进一步阅读 docs/laravel.md 中Laravel 应用作为独立二进制的专门章节。第一步准备待嵌入的应用在构建二进制之前务必先把应用收拾干净。官方建议做到以下几点安装应用的生产依赖转储 autoloaderdump autoloader开启应用的生产模式如果有删除.git、测试等冗余文件减小最终二进制体积。以 Symfony 应用为例官方给出的完整准备命令如下# 导出项目去掉 .git/ 等文件 mkdir $TMPDIR/my-prepared-app git archive HEAD | tar -x -C $TMPDIR/my-prepared-app cd $TMPDIR/my-prepared-app # 设置合适的环境变量 echo APP_ENVprod .env.local echo APP_DEBUG0 .env.local # 删除测试及其他多余文件以节省空间 # 另一种做法在 .gitattributes 中为这些文件添加 export-ignore 属性 rm -Rf tests/ # 安装依赖 composer install --ignore-platform-reqs --no-dev -a # 优化 .env composer dump-env prod其中git archive HEAD只导出已被 Git 跟踪的文件天然剔除.git/与未跟踪的临时文件--ignore-platform-reqs用于跳过平台相关的依赖检查因为最终运行环境是静态二进制而非当前开发机。最后通过composer dump-env prod把.env编译为针对生产环境的优化配置。定制嵌入配置Caddyfile 与 php.ini为了让嵌入的二进制按你的意图工作可以直接在待嵌入应用的主目录即上例中的$TMPDIR/my-prepared-app放置两个配置文件Caddyfile用于定制 Caddy / FrankenPHP 行为例如站点域名、php_server指令、worker 模式、线程数等完整语法可参考 docs/config.mdphp.ini用于定制 PHP 运行时如memory_limit、max_execution_time、zend_extension等。构建脚本会把整个应用目录含这两个文件一起打包。运行时 FrankenPHP 会依次从当前工作目录与/etc/frankenphp/查找配置详见 docs/config.md 中静态二进制一节。第二步创建 Linux 二进制Docker 构建创建 Linux 二进制最省事的方式是使用官方提供的 Docker 构建镜像。完整流程分三步1. 在应用仓库中新建static-build.Dockerfile# static-build.Dockerfile FROM --platformlinux/amd64 dunglas/frankenphp:static-builder-gnu # 如果打算在 musl-libc 系统上运行二进制改用 static-builder-musl # 复制应用 WORKDIR /go/src/app/dist/app COPY . . # 构建静态二进制 WORKDIR /go/src/app/ RUN EMBEDdist/app/ ./build-static.sh[!CAUTION]注意部分项目的.dockerignore例如 Symfony Docker 默认的那份会忽略vendor/目录和.env文件。构建前务必调整或删除.dockerignore否则这些内容不会被复制进镜像最终二进制里就没有依赖和配置了。2. 执行构建docker build -t static-app -f static-build.Dockerfile .3. 从镜像中取出二进制docker cp $(docker create --name static-app-tmp static-app):/go/src/app/dist/frankenphp-linux-x86_64 my-app ; docker rm static-app-tmp构建完成后当前目录下名为my-app的文件就是你要交付的独立二进制。从源码看上述构建过程实际执行的是仓库根目录下的 build-static.sh它会调用 static-php-cli 下载对应版本的 PHP 源码、以--enable-zts --build-embed --build-frankenphp参数编译嵌入版 PHP并通过 xcaddy 把 Caddy 与 FrankenPHP 组合成最终可执行文件见 build-static.sh。static-builder-gnu镜像基于 CentOS 7 / glibc产物是大部分静态的二进制可运行在所有 glibc 2.17 的系统上但无法在 musl 系如 Alpine Linux运行static-builder-musl镜像则产出完全静态、可在任何 Linux 发行版上运行的二进制详见 static-builder-gnu.Dockerfile 与 static-builder-musl.Dockerfile。第三步为其他系统构建macOS 与免 Docker 方案如果不想用 Docker或者需要构建 macOS 二进制可以直接使用仓库提供的脚本git clone https://github.com/php/frankenphp cd frankenphp EMBED/path/to/your/app ./build-static.sh生成的二进制位于dist/目录命名为frankenphp-os-arch例如 macOS 上为frankenphp-mac-arm64或frankenphp-mac-amd64。该脚本在 Linux 上同样可用Docker 镜像内部也是用它构建的因此是跨平台构建的统一入口。需要注意的是macOS 构建依赖 Homebrew 安装的 Composer、Go 等工具链见 build-static.sh。第四步运行嵌入的二进制构建完成之后一切就绪——my-app或其他系统上的dist/frankenphp-os-arch就是一个自包含应用。启动 Web 应用./my-app php-server如果你的应用包含 worker 脚本worker 模式会让应用常驻内存、大幅提升吞吐用类似下面的方式启动 worker./my-app php-server --worker public/index.php如需启用 HTTPS自动签发 Lets Encrypt 证书、HTTP/2 与 HTTP/3指定要使用的域名即可./my-app php-server --domain localhost还可以直接运行二进制内嵌的 PHP CLI 脚本例如 Symfony 的bin/console./my-app php-cli bin/console这相当于把 CLI 入口也打进了二进制非常适合在容器scratch镜像或最小化环境中执行 artisan、console 等命令。关于 worker 模式的更多细节num、env、watch等选项可参考 docs/config.md 中的worker指令说明。PHP 扩展自动检测与手动定制嵌入二进制的 PHP 扩展选择遵循以下优先级对应文档PHP 扩展一节逻辑实现在 build-static.sh如果设置了PHP_EXTENSIONS环境变量直接使用你指定的扩展列表否则如果应用目录中存在composer.json、composer.lock以及vendor/composer/installed.json脚本会调用 static-php-cli 的dump-extensions自动解析项目依赖的扩展忽略--no-dev开发依赖只编译项目真正需要的扩展如果连composer.json都没有则编译一组默认扩展见 build-static.sh 中的defaultExtensions涵盖 opcache、pdo_mysql、redis、mbstring、gd、intl 等主流扩展。手动定制扩展时使用PHP_EXTENSIONS环境变量例如EMBED/path/to/your/app PHP_EXTENSIONSopcache,pdo_sqlite ./build-static.sh注意 build-static.sh 中有一条硬性规则Brotli 库brotli始终会被加入构建因为它是 Caddy 的 cbrotli 压缩模块的编译依赖即使你没在PHP_EXTENSION_LIBS里声明也会自动补上。定制构建环境变量一览嵌入构建的定制能力来自 build-static.sh 支持的一组环境变量同时适用于 Docker 构建与脚本构建完整说明见 docs/static.md环境变量作用FRANKENPHP_VERSION指定要构建的 FrankenPHP 版本默认取当前 Git 提交PHP_VERSION指定 PHP 版本默认自动解析最新的 8.x 版本PHP_EXTENSIONS要编译进二进制的 PHP 扩展列表PHP_EXTENSION_LIBS额外编译的库为扩展提供附加功能如libjpeg,libwebp之于 gdXCADDY_ARGS传递给 xcaddy 的附加参数用于添加 Caddy 模块EMBED要嵌入二进制的 PHP 应用路径相对路径会自动转换为绝对路径CLEAN设置后从零构建 libphp 及其依赖不使用缓存DEBUG_SYMBOLS设置后保留调试符号不剥离二进制COMPRESS设为1时用 UPX 压缩最终 Linux 二进制设置DEBUG_SYMBOLS时忽略MIMALLOC实验性仅 Linux用 mimalloc 替换 musl 的 mallocng提升高并发场景性能RELEASE仅维护者使用设置后将产物上传到 GitHub Release举例想用 glibc 构建、只带opcache扩展、并用 UPX 压缩docker build --build-arg EMBEDdist/app/ \ --build-arg PHP_EXTENSIONSopcache,pdo_sqlite \ --build-arg COMPRESS1 \ -t static-app -f static-build.Dockerfile .如果你需要加载 Xdebug 这类动态扩展则必须使用 glibcstatic-builder-gnu或 macOS 构建的二进制并且扩展需要以 ZTS 模式手工编译完全静态的 musl 二进制无法加载动态扩展。具体的手工编译步骤在static-builder-gnu容器内用./configure --with-php-config/go/src/app/dist/static-php-cli/buildroot/bin/php-config构建 Xdebug 的完整命令序列见 docs/static.md 的在静态二进制中动态加载 PHP 扩展一节。分发与体积优化Linux通过设置COMPRESS1环境变量构建脚本会用 UPX 压缩最终二进制对应 build-static.sh 中--with-upx-pack的逻辑可显著减小分发体积macOS建议在分发前用xz对二进制进行压缩例如xz -9 my-app分发时只需把这一个压缩包或直接解压后的二进制放到目标机器上执行即可——目标机器无需 PHP、无需 Composer、无需 Caddy。这也使得嵌入二进制的应用可以直接跑在 Dockerscratch空基础镜像上对应 docs/static.md 中关于完全静态二进制的说明是极简部署的理想形态。【免费下载链接】frankenphp The modern PHP app server项目地址: https://gitcode.com/GitHub_Trending/fr/frankenphp创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考