ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

Deployer 实战:使用 Symfony 配方(Recipe)零停机部署 PHP 应用

2026/9/24 1:13:01 拓冰建站 浏览量
Deployer 实战:使用 Symfony 配方(Recipe)零停机部署 PHP 应用 DevOpsCI/CDCLI开发工具运维【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址https://gitcode.com/gh_mirrors/de/deployer点击查看免费下载本篇技术指南基于 Deployer 开源仓库中的 Symfony 部署配方文档 及其源码 recipe/symfony.php系统讲解如何通过require recipe/symfony.php将 Symfony 应用部署到服务器。你将掌握该配方的全部配置参数shared_dirs、writable_dirs、bin/console、migrations_config等、核心任务deploy、database:migrate、deploy:cache:clear、deploy:dump-env以及它们在源码层面的真实调用链从而能独立编写、定制并排查自己的deploy.php。一、Symfony 配方是什么Deployer 是一个用 PHP 编写的免费开源部署工具帮助你把 Symfony 应用发布到远程服务器。它的设计目标是“开箱即用”只要在部署脚本里引入 Symfony 配方就能立刻获得一套针对 Symfony 项目结构优化过的部署流程。配方recipe本质上是一个可复用的 PHP 文件通过require引入后它会自动注册任务task和配置项configuration// deploy.php require recipe/symfony.php;从源码看recipe/symfony.php的第一行就加载了common.php见 recipe/symfony.php同时通过add(recipes, [symfony])把自己注册进配方列表。因此Symfony 配方是基于 common 配方的扩展common 提供的基础能力详见 docs/recipe/common.md在 Symfony 配方中全部可用。三大核心特性Provisioning服务器预配置在部署之前先把服务器环境准备好如安装 PHP、创建用户、配置网站相关配方见 docs/recipe/provision.md。Zero downtime deployment零停机部署代码先发布到新 release 目录全部就绪后再一次性切换符号链接整个过程旧版本持续对外服务。Rollbacks回滚某个版本出问题时可以一键回滚到上一个可用版本。此外Deployer 语法简单直观、易于上手通过并行连接加速部署全程基于 SSH 连接服务器保证安全并支持所有主流 PHP 框架Laravel、Symfony、CakePHP、Magento 等对应配方见 docs/recipe 目录。更多基础概念可参考 docs/getting-started.md。二、deploy 任务的整体流水线Symfony 配方的核心是deploy任务源码见 recipe/symfony.php它是一个组任务group task按顺序执行四个子任务task(deploy, [ deploy:prepare, deploy:vendors, deploy:cache:clear, deploy:publish, ]);与 common 配方的通用deploy只包含deploy:prepare和deploy:publish见 recipe/common.php相比Symfony 配方在中间插入了deploy:vendors安装依赖和deploy:cache:clear清缓存完全贴合 Symfony 应用的发布节奏。展开后完整的调用树如下deploy ├─ deploy:prepare # 准备新 release │ ├─ deploy:info # 显示部署信息 │ ├─ deploy:setup # 准备主机目录结构 │ ├─ deploy:lock # 加部署锁防止并发部署 │ ├─ deploy:release # 创建新 release 目录 │ ├─ deploy:update_code # 拉取/更新代码 │ ├─ deploy:env # 配置 .env 文件 │ ├─ deploy:shared # 为共享文件/目录创建软链 │ └─ deploy:writable # 设置可写目录权限 ├─ deploy:vendors # 安装 Composer 依赖 ├─ deploy:cache:clear # 清空并预热缓存 └─ deploy:publish # 发布 release ├─ deploy:symlink # 切换 current 软链到新 release ├─ deploy:unlock # 解除部署锁 ├─ deploy:cleanup # 清理旧 release └─ deploy:success # 输出成功信息其中deploy:prepare与deploy:publish的定义在 recipe/common.php子任务的逐个说明分散在 docs/recipe/deploy 目录的对应文档中。理解这条链路是排查部署问题的关键例如deploy:release源码见 recipe/deploy/release.php负责创建releases/N目录并建立release软链而release_or_current_pathrecipe/deploy/release.php在部署期间指向release、平时回落到current这正是后面所有 Symfony 命令都能“在正确目录里执行”的机制基础。三、配置项详解ConfigurationSymfony 配方通过set()定义了若干配置项覆盖了部署 Symfony 应用时需要定制的一切目录结构、可写权限、控制台命令路径等。下面逐项说明其默认值与作用。3.1 symfony_version — 自动探测 Symfony 版本set(symfony_version, function () { $result run({{bin/console}} --version); preg_match_all(/(\d\.?)/, $result, $matches); return $matches[0][0] ?? 5.0; });该配置在访问时才自动计算autogenerated它执行{{bin/console}} --version从输出中用正则(\d\.?)提取第一个版本号若提取失败则回退到5.0。它是后续按版本差异化处理如不同 Symfony 版本采用不同的缓存预热参数的基础一般无需手动覆盖但如果远程环境特殊比如bin/console输出格式异常也可以手动set(symfony_version, 6.4)。3.2 shared_dirs — 跨 release 共享的目录set(shared_dirs, [ var/log, ]);它覆盖override了 recipe/deploy/shared.php 中同名配置默认空数组。含义是var/log目录在每次发布时不做复制而是软链到deploy_path/shared下统一维护这样日志在版本切换、回滚后依然连续不丢失。如果你还需要共享其他目录如上传文件目录在deploy.php中追加即可set(shared_dirs, [ var/log, var/uploads, ]);共享机制的细节见 docs/recipe/deploy/shared.md每个 release 里的共享目录/文件都会是指向deploy_path/shared下实体的软链。3.3 shared_files — 跨 release 共享的文件set(shared_files, [ .env.local, ]);同样覆盖 recipe/deploy/shared.php 的同名配置。.env.local保存着每个环境的敏感配置数据库密码、密钥等绝不应随代码发布而变动因此必须放在共享区——首次部署时 Deployer 会基于.env.exampledotenv_example配置见 docs/recipe/deploy/env.md初始化后续发布则始终复用同一份。需要共享其他文件比如自签名证书、业务配置文件时按同样方式追加即可。3.4 writable_dirs — 需要 Web 服务器可写的目录set(writable_dirs, [ var, var/cache, var/log, var/sessions, ]);它覆盖 recipe/deploy/writable.php 的同名配置默认空数组。Symfony 的var/下缓存、日志、会话目录必须让运行 PHP-FPM 的 http 用户可写否则应用会直接报权限错误。具体以哪种方式设置权限由writable_mode决定可选值包括chown、chgrp、chmod、acl、sticky、skip默认acl相关配套配置还有http_user自动探测、writable_use_sudo默认false、writable_recursive默认false、writable_chmod_mode默认0755等详见 docs/recipe/deploy/writable.md。在 CentOS/RedHat 系服务器上若 ACL 不可用可改成set(writable_mode, chmod);3.5 log_files — 应用日志文件匹配模式set(log_files, var/log/*.log);该配置被 common 配方的logs:app任务使用见 recipe/common.php执行dep logs:app时会在current_path下对var/log/*.log执行tail -f实时跟踪应用日志。Symfony 的标准日志路径恰好是var/log/*.log因此该默认值开箱即用。3.6 migrations_config — 迁移配置文件路径set(migrations_config, );默认为空字符串。它是database:migrate任务的开关只有显式设置了迁移配置文件如config/packages/doctrine_migrations.yaml对应的 XML/JSON 配置时迁移命令才会附带--configuration参数源码见 recipe/symfony.phpif (get(migrations_config) ! ) { $options $options --configuration{{release_or_current_path}}/{{migrations_config}}; }3.7 doctrine_schema_validate_config — Schema 校验配置set(doctrine_schema_validate_config, );默认为空字符串。它直接作为doctrine:schema:validate命令的附加参数使用recipe/symfony.php。当你的 Doctrine 映射需要额外配置如指定--emdefault或多个实体管理器时在此传入。3.8 bin/console — Symfony 控制台命令路径set(bin/console, {{bin/php}} {{release_or_current_path}}/bin/console);定义了远程执行 Symfony 命令时使用的完整命令前缀。其中{{bin/php}}来自 common 配方recipe/common.php默认用which(php)探测若主机设置了php_version则使用/usr/bin/php{{php_version}}{{release_or_current_path}}在部署期间指向新 release、平时指向 currentrecipe/deploy/release.php保证命令始终在正确目录执行。如需指定 PHP 版本可在deploy.php中覆盖host(prod) -set(php_version, 8.2); // 使 bin/php 解析为 /usr/bin/php8.23.9 console_options — console 命令通用选项set(console_options, function () { return --no-interaction; });同样在访问时自动生成默认给所有bin/console调用附加--no-interaction避免部署过程中远程命令因等待交互输入而挂起。CI/CD 环境下尤其重要。四、任务详解TasksSymfony 配方定义了五个任务三个是 Symfony 专属业务任务两个是扩展/重定义的部署任务。4.1 database:migrate — 执行数据库迁移desc(Migrates database); task(database:migrate, function () { $options --allow-no-migration; if (get(migrations_config) ! ) { $options $options --configuration{{release_or_current_path}}/{{migrations_config}}; } run(cd {{release_or_current_path}} {{bin/console}} doctrine:migrations:migrate $options {{console_options}}); });默认携带--allow-no-migration即使没有待执行迁移也不会报错退出配置了migrations_config时会追加--configuration指定配置文件该任务不在默认deploy组任务内需要手动挂载。推荐放在deploy:cache:clear之后、deploy:publish之前task(deploy, [ deploy:prepare, deploy:vendors, deploy:cache:clear, database:migrate, // 手动插入 deploy:publish, ]);也可以单独执行dep database:migrate。4.2 doctrine:schema:validate — 校验 Doctrine 映射desc(Validate the Doctrine mapping files); task(doctrine:schema:validate, function () { run(cd {{release_or_current_path}} {{bin/console}} doctrine:schema:validate {{doctrine_schema_validate_config}} {{console_options}}); });等价于在服务器上执行bin/console doctrine:schema:validate用于检查实体映射与数据库 schema 是否一致常在发布前作为质量门禁使用dep doctrine:schema:validate。4.3 deploy:cache:clear — 清空缓存desc(Clears cache); task(deploy:cache:clear, function () { if (false ! strpos(get(composer_options, ), --no-scripts)) { run({{bin/console}} cache:clear {{console_options}}); } });这个任务体现了 Deployer 对性能的精细考虑Composer 的install脚本通常已经清空并预热了 Symfony 缓存所以默认什么都不做只有当composer_options中包含--no-scripts即跳过了 Composer 脚本时才会手动执行cache:clear。composer_options的默认值来自 recipe/deploy/vendors.phpset(composer_options, --verbose --prefer-dist --no-progress --no-interaction --no-dev --optimize-autoloader);4.4 deploy:dump-env — 优化环境变量desc(Optimize environment variables); task(deploy:dump-env, function () { within({{release_or_current_path}}, function () { run({{bin/composer}} dump-env ${APP_ENV:-prod}); }); });在release_or_current_path目录内执行composer dump-env把.env中的环境变量按APP_ENV默认prod编译进.env.local.php避免每次请求动态解析.env带来的开销。{{bin/composer}}来自 recipe/deploy/vendors.php它会自动探测远程 Composer若.dep/composer.phar存在则优先使用否则用系统composer都没有时自动下载安装到.dep/composer.phar。4.5 deploy — 一键部署如前所述deploy组任务按deploy:prepare → deploy:vendors → deploy:cache:clear → deploy:publish的顺序执行其中deploy:vendorsrecipe/deploy/vendors.php在 release 目录内执行composer install若远程缺少unzip命令会给出提速提示deploy:publish依次完成软链切换deploy:symlink、解锁deploy:unlock、旧版本清理deploy:cleanup与成功提示deploy:success。命令行直接运行dep deploy五、编写自己的 deploy.php完整示例把以上配置与任务组合起来一个可用的 Symfony 部署脚本大致如下?php namespace Deployer; require recipe/symfony.php; // 项目信息 set(repository, gitgithub.com:yourname/yourproject.git); // 部署仓库 set(application, your-symfony-app); // 应用名用于目录与提示 // 主机配置 host(prod) -set(hostname, 1.2.3.4) -set(remote_user, deployer) -set(deploy_path, /var/www/your-symfony-app); // 必填部署根目录 // 覆盖 Symfony 配方默认值按需 set(shared_dirs, [var/log, var/uploads]); // 追加共享目录 set(shared_files, [.env.local]); // 共享环境配置文件 set(writable_mode, chmod); // 服务器不支持 ACL 时改用 chmod set(keep_releases, 5); // 只保留 5 个历史 release默认 10 // 在发布前插入数据库迁移 task(deploy, [ deploy:prepare, deploy:vendors, deploy:cache:clear, database:migrate, deploy:publish, ]);需要注意的要点deploy_path是必填项缺失时 common 配方会抛出ConfigurationException见 recipe/common.php首次部署前可先用dep deploy:setup初始化目录结构或用dep provision直接预配置整台服务器部署出错后回滚dep rollback查看发布历史dep releases表格形式展示时间、release 号、作者、目标与提交实现见 recipe/deploy/release.php跟踪日志dep logs:app。六、源码级原理补充release 目录结构理解 Symfony 配方的部署行为关键在于 Deployer 的 release 机制。一次部署会在deploy_path下形成如下结构由deploy:setup、deploy:release等任务协同创建参见 recipe/deploy/release.php/var/www/your-symfony-app ├── current - releases/4 对外服务的版本 ├── release - releases/5 正在部署的版本 ├── releases/ │ ├── 1/ 2/ 3/ 4/ 5/ ├── shared/ │ ├── var/log/ 共享目录实体 │ └── .env.local 共享文件实体 └── .dep/ ├── latest_release └── releases_logdeploy:symlink只做一次原子性的ln -nfs切换把current指向新 release这就是“零停机”的本质deploy:cleanup则依据keep_releases默认 10见 recipe/common.php清理过期版本。shared_dirs、shared_files中的条目会在每个 release 内被软链到shared/下的实体从而保证日志、环境配置在版本间持续可用——这正是 Symfony 配方默认把var/log与.env.local放进共享区的原因。结语recipe/symfony.php用不到 80 行代码把 Deployer 的通用部署能力与 Symfony 的项目约定var/目录体系、bin/console、Doctrine 迁移、Composer 依赖无缝对接。掌握本文介绍的配置项与任务你既可以开箱即用地执行dep deploy也能按业务需要自由组合任务链如插入迁移、调整共享目录、切换权限模式。当出现部署问题时从 recipe/symfony.php 出发沿deploy:prepare → deploy:vendors → deploy:cache:clear → deploy:publish这条主线逐段核对对应文档见 docs/recipe/deploy 目录即可快速定位问题所在。赞分享DevOpsCI/CDCLI开发工具运维【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址https://gitcode.com/gh_mirrors/de/deployer点击查看免费下载相关推荐使用 Deployer 的 Laravel 配方实现零停机部署recipe/laravel.php 全解析使用 Deployer 的 Laravel 配方实现零停机部署recipe/laravel.php 全解析 本指南以 Deployer 开源项目中的 LaraDevOpsCI/CDCLI开发工具运维使用 Deployer 零停机部署 Shopware 6recipe/shopware.php 完整实战指南使用 Deployer 零停机部署 Shopware 6recipe/shopware.php 完整实战指南 Deployer 是一个用 PHP 编写的开源部DevOpsCI/CDCLI开发工具运维使用 Deployer 零停机部署 CodeIgniter 4recipe/codeigniter4 完整实战指南使用 Deployer 零停机部署 CodeIgniter 4recipe/codeigniter4 完整实战指南 本指南讲解如何在 Deployer 中引入DevOpsCI/CDCLI开发工具运维创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考