使用 Deployer 零停机部署 Shopware 6:recipe/shopware.php 完整实战指南
发布时间:2026/9/24 2:31:58 作者:尧图编辑部 阅读量:1,286

DevOpsCI/CDCLI开发工具运维【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址https://gitcode.com/gh_mirrors/de/deployer点击查看免费下载Deployer 是一个用 PHP 编写的开源部署工具其内置的 Shopware 配方reciperecipe/shopware.php 为 Shopware 6 商城项目提供开箱即用的零停机部署、数据库迁移、插件更新与主题编译等完整流程。本文以该配方的官方文档 docs/recipe/shopware.md 为主线结合仓库源码深入剖析其配置项、任务编排与执行原理帮助你在一份deploy.php中完成 Shopware 项目的可重复、可回滚的自动化部署。Deployer 与 Shopware 配方概览Shopware 配方是 Deployer 官方为 Shopware 6 定制的一套部署任务集合。文档开篇即给出引入方式require recipe/shopware.php;该配方基于 common 配方recipe/common.php构建后者又聚合了 provision、cleanup、clear_paths、copy_dirs、env、info、lock、push、release、rollback、setup、shared、symlink、update_code、vendors、writable 等基础配方模块。因此只要引入recipe/shopware.php你就同时获得了 Deployer 的完整基础能力。Deployer 的核心能力在文档中被概括为三大特性Provisioning服务器配置自动为服务器完成环境准备PHP、Node.js、Web 服务器等参见 provision 配方文档。Zero downtime deployment零停机部署通过 release 目录 符号链接切换的方式让新版本在后台准备完成后一次性切换部署过程不影响线上服务。Rollbacks回滚出现问题时可以快速回滚到上一个可用版本见 rollback 文档。此外还有易用简单直观的 PHP 语法、快速并行连接执行任务、安全基于 SSH 连接、以及支持所有主流 PHP 框架等特点。其基础使用方式可参考 Getting Started。快速开始最小可用配置在deploy.php中先声明仓库地址set(repository, gitgithub.com:shopware/production.git);然后配置目标主机文档中的示例注释为原文所附host(SSH-HOSTNAME) -set(remote_user, SSH-USER) -set(deploy_path, /var/www/shopware) // 这是 deployer 将创建其目录结构的位置 -set(http_user, www-data) // 如果 SSH 登录用户与 Web 服务器运行用户相同则无需设置 -set(http_group, www-data) -set(writable_mode, chmod) -set(writable_recursive, true) -set(become, www-data); // 出于新建缓存文件的访问权限考虑你可能希望切换用户来执行远程任务其中deploy_path是 Deployer 在服务器上创建目录结构releases/、shared/、current 符号链接等的根路径属于必需参数——从源码看recipe/common.php 中deploy_path未设置时会抛出异常common 文档 中标记为Required。writable_mode指定可写目录的处理方式常见取值有chown、chgrp、chmod、acl、sticky、skip默认是acl见 writable 文档writable_recursive控制是否使用-R递归模式默认false。文档还特别提示Shopware 安装必须经过修改使其能够“无数据库构建”build without database。这意味着前端Storefront的编译过程不依赖数据库中的配置与数据从而保证 Deployer 可以先上传代码、在服务器上完成构建而不需要先接入生产数据库。这一前提是整个“上传代码 → 构建 → 切换”流程能够闭环的关键。配置项详解Shopware 配方在 recipe/shopware.php 中定义了一系列覆盖通用配方的配置项。bin/console控制台命令路径{{bin/php}} {{release_or_current_path}}/bin/console它组合了 common 配方 的bin/php默认优先使用/usr/bin/php{{php_version}}否则回退到which(php)检测到的路径与release_or_current_path部署时为当前 release 目录回滚等场景下为 current 目录。配方的所有sw:*任务都通过它执行 Shopware 的 CLI 命令。default_timeout覆盖 common 配方 中默认 300 秒的超时设置set(default_timeout, 3600); // 当任务耗时超过该值时增大此参数Shopware 部署中的数据库迁移、插件更新、主题编译都是耗时操作1 小时超时能避免长任务被提前中断设置为null可禁用超时。shared_files跨 release 共享的文件[ .env.local, install.lock, public/.htaccess, public/.user.ini, ]这些文件存放于{{deploy_path}}/shared目录通过符号链接挂载进每个 release。其机制可从 recipe/deploy/shared.php 源码确认deploy:shared任务会先在 shared 目录创建目标文件首次部署时从 release 复制初值之后保留再从 release 中删除原文件并建立符号链接。install.lock被共享意味着安装锁只在首次初始化时生效避免每次部署触发重新安装.env.local共享则保证环境差异如数据库凭据不随代码版本变化。shared_dirs跨 release 共享的目录[ config/jwt, files, var/log, public/media, public/plugins, public/thumbnail, public/sitemap, ]与 shared_files 同理这些目录首次部署时迁移到 shared 目录之后以符号链接形式共享。例如public/media用户上传的媒体文件、public/sitemap搜索引擎生成的站点地图、var/log运行日志、config/jwtJWT 私钥都属于“运行时产生、与代码无关”的数据必须跨 release 持久化。writable_dirs需保持可写的目录[ config/jwt, custom/plugins, files, public/bundles, public/css, public/fonts, public/js, public/media, public/plugins, public/sitemap, public/theme, public/thumbnail, var, ]这些目录会在deploy:writable阶段按writable_mode指定的方式被赋予写权限。源码注释特别提醒“writable”的定义需要关注且config/jwt/*下的文件会得到sw:writable:jwt任务的特别处理详见下文任务节。shopware_version动态探测 Shopware 版本供其他任务如缓存预热做版本分支判断$versionOutput run(cd {{release_path}} {{bin/console}} -V); preg_match(/(\d\.\d\.\d\.\d)/, $versionOutput, $matches); return $matches[0] ?? 6.6.0;该配置在首次访问时通过远程执行bin/console -V提取形如6.6.x.x的版本号若正则匹配失败则回退到6.6.0。任务编排deploy 主流程文档给出了 Shopware 配方的核心——deploy任务的完整执行树deploy ├── deploy:prepare common 配方 │ ├── deploy:info — 显示部署信息 │ ├── deploy:setup — 准备主机目录结构 │ ├── deploy:lock — 锁定部署防止并发 │ ├── deploy:release — 创建新 release 目录 │ ├── deploy:update_code — 拉取/上传代码 │ ├── deploy:env — 配置 .env 文件 │ ├── deploy:shared — 创建共享文件/目录符号链接 │ └── deploy:writable — 设置可写目录权限 ├── sw:writable:jwt — 修正 config/jwt 文件权限 ├── sw:deploy │ ├── sw:database:migrate — 执行全部数据库迁移 │ ├── sw:plugin:refresh — 刷新插件列表 │ ├── sw:theme:refresh — 刷新主题 │ ├── sw:scheduled-task:register — 注册定时任务 │ ├── sw:cache:clear — 清空缓存不预热 │ ├── sw:plugin:update:all — 更新所有可升级插件 │ └── sw:cache:clear — 再次清空缓存 ├── deploy:clear_paths — 清理 release 中的多余文件 ├── sw:cache:warmup — 预热缓存 └── deploy:publish common 配方 ├── deploy:symlink — 将 current 指向新 release ├── deploy:unlock — 解除部署锁 ├── deploy:cleanup — 清理旧 release └── deploy:success — 输出成功信息对应源码recipe/shopware.php 第 160-168 行desc(Deploys your project); task(deploy, [ deploy:prepare, sw:writable:jwt, sw:deploy, deploy:clear_paths, sw:cache:warmup, deploy:publish, ]);整个流程体现了“先在 release 目录中完成全部变更数据库迁移、插件、缓存最后一步原子切换符号链接”的零停机思路。各基础任务的定义与原理可查阅 common 配方 及各基础文档info、setup、lock、release、update_code、env、shared、writable、symlink、cleanup。各 sw:* 任务逐一解析sw:cache:clear 与 sw:cache:warmup清空与预热缓存源码 第 84-97 行task(sw:cache:clear, static function () { run(cd {{release_path}} {{bin/console}} cache:clear --no-warmup); }); task(sw:cache:warmup, static function () { run(cd {{release_path}} {{bin/console}} cache:warmup); // Shopware 6.6 已移除 http:cache:warmup 命令仅在版本低于 6.6 时执行 if (version_compare(get(shopware_version), 6.6.0) 0) { run(cd {{release_path}} {{bin/console}} http:cache:warm:up); } });cache:clear --no-warmup只清不预热cache:warmup则在切换前把缓存构建好避免第一个访问用户等待缓存生成。这里利用前面介绍的shopware_version配置做版本分支Shopware 6.6 起废弃了http:cache:warm:up命令低于 6.6 才执行 HTTP 缓存预热。注意deploy流程中sw:cache:clear出现两次分别在插件更新前后用于保证插件变更后缓存状态正确。sw:database:migrate执行全部数据库迁移task(sw:database:migrate, static function () { run(cd {{release_path}} {{bin/console}} database:migrate --all); });--all会执行所有待应用的迁移包括所有插件在sw:deploy中排在第一位确保新代码运行前数据库结构已就绪。这是“先迁移、后切换”的典型做法。sw:plugin:refresh 与 sw:plugin:update:all刷新插件列表与批量更新插件task(sw:plugin:refresh, function () { run(cd {{release_path}} {{bin/console}} plugin:refresh); }); function getPlugins(): array { $output run(cd {{release_path}} {{bin/console}} plugin:list --json); $plugins json_decode($output); return $plugins; } task(sw:plugin:update:all, static function () { $plugins getPlugins(); foreach ($plugins as $plugin) { if ($plugin-installedAt $plugin-upgradeVersion) { writeln(infoRunning plugin update for . $plugin-name . /info\n); run(cd {{release_path}} {{bin/console}} plugin:update . $plugin-name); } } });plugin:refresh让 Shopware 重新扫描custom/plugins目录新代码可能带来新插件。sw:plugin:update:all通过plugin:list --json拿到插件列表仅对“已安装installedAt非空且存在可升级版本upgradeVersion非空”的插件逐个执行plugin:update并在执行前输出信息便于排障。sw:theme:refresh 与 sw:theme:compiletask(sw:theme:refresh, function () { run(cd {{release_path}} {{bin/console}} theme:refresh); }); // 该任务默认不被使用但可与 SHOPWARE_SKIP_THEME_COMPILE1 组合 // 用于在远端而非本地构建主题 task(sw:theme:compile, function () { run(cd {{release_path}} {{bin/console}} theme:compile); });theme:refresh在sw:deploy中默认执行用于同步主题信息。sw:theme:compile默认不在sw:deploy之列——文档说明它与SHOPWARE_SKIP_THEME_COMPILE1环境变量搭配使用当你在构建build阶段设置该环境变量跳过本地主题编译时可以用这个任务在服务器上远程编译主题从而让 Storefront 的编译产物在目标环境中生成。sw:scheduled-task:registertask(sw:scheduled-task:register, function () { run(cd {{release_path}} {{bin/console}} scheduled-task:register); });注册 Shopware 的定时任务确保新代码中定义的计划任务如订单清理、索引重建在部署后能够被调度执行。sw:writable:jwt对config/jwt目录下文件做权限修正源码 第 140-145 行task(sw:writable:jwt, static function () { if (!test([ -d {{deploy_path}}/config/jwt/ ])) { return; } run(cd {{release_path}} find config/jwt/ -type f -exec chmod -R 660 {} ); });只有{{deploy_path}}/config/jwt/目录存在时才执行用find -type f找出所有文件并chmod 660所有者与同组可读写其他用户无权限这是对 JWT 私钥类敏感文件的加固处理——这正是writable_dirs注释中所说的“config/jwt/*的特别关注”。sw:deployShopware 部署任务组task(sw:deploy, [ sw:database:migrate, sw:plugin:refresh, sw:theme:refresh, sw:scheduled-task:register, sw:cache:clear, sw:plugin:update:all, sw:cache:clear, ]);顺序逻辑先迁移数据库 → 再让新插件/主题可见 → 注册定时任务 → 清缓存 → 更新所有插件 → 再清缓存。两次清缓存分别覆盖插件更新前与更新后的状态避免残留缓存影响新版本。无数据库构建sw-build-without-db为满足“build without database”的前置要求配方提供了完整的远端配置拉取 本地构建方案源码 第 170-204 行task(deploy:update_code)-setCallback(static function () { upload(., {{release_path}}, [ options [ --exclude.git, --excludedeploy.php, --excludenode_modules, ], ]); }); task(sw-build-without-db:get-remote-config, static function () { if (!test([ -d {{current_path}} ])) { return; } // 将 .env 文件复制到构建目录避免构建期间回退到 APP_ENVdev 与 APP_DEBUG1 download({{current_path}}/, ./, [ options [--copy-links, --include.env*, --exclude*], ]); within({{current_path}}, function () { run({{bin/php}} ./bin/console bundle:dump); download({{current_path}}/var/plugins.json, ./var/); run({{bin/php}} ./bin/console theme:dump -n); download({{current_path}}/files/theme-config, ./files/); }); }); task(sw-build-without-db:build, static function () { runLocally(CI1 SHOPWARE_SKIP_BUNDLE_DUMP1 ./bin/build-js.sh); }); task(sw-build-without-db, [ sw-build-without-db:get-remote-config, sw-build-without-db:build, ]); before(deploy:update_code, sw-build-without-db);流程拆解拉取远端运行时配置sw-build-without-db:get-remote-config从 current 目录下载.env*文件用--include.env* --exclude*白名单方式避免把整个站点拉下来防止构建时因缺少环境变量而回退到APP_ENVdev、APP_DEBUG1的开发模式随后在远端执行bundle:dump、theme:dump并下载var/plugins.json与files/theme-config让本地构建能拿到与生产一致的 bundle/主题配置。本地构建sw-build-without-db:build在本地以CI1 SHOPWARE_SKIP_BUNDLE_DUMP1环境执行./bin/build-js.sh完成 Storefront 编译跳过 bundle dump因为已从远端获取。挂钩时机before(deploy:update_code, sw-build-without-db)确保构建在代码上传前完成。与此同时配方的deploy:update_code被改写为直接上传本地目录而非 git 拉取通过upload(., {{release_path}}, ...)把整个项目上传到 release 目录并排除.git、deploy.php、node_modules。这与无数据库构建流程天然配套——本地完成编译后把包含构建产物的完整目录上传上去。对比 update_code 文档默认策略是archive从远端仓库拉取代码Shopware 配方覆盖了这一行为属于该配方的关键差异点。与基础配方的对比与适用前提与 common 配方的差异Shopware 配方在 recipe/common.php 基础上覆盖了bin/console、default_timeout、shared_files、shared_dirs、writable_dirs等配置并新增了整套sw:*任务与sw-build-without-db构建流程deploy:update_code也从 git 拉取改为本地上传。适用前提与限制目标项目需为 Shopware 6 架构使用bin/console与custom/plugins目录版本判断如http:cache:warm:up、version_compare阈值 6.6.0以配方源码为准若升级到 Shopware 6.6缓存预热会自动跳过已废弃命令。安装必须支持“无数据库构建”否则远端/本地构建流程无法成立。default_timeout默认 3600 秒若服务器性能较差导致迁移或编译超时需要调大该值。权限设置依赖主机上的工具acl模式需要setfaclLinux或 macOS 的chmod a支持见 recipe/deploy/writable.php 源码若服务器无法自动检测http_user/http_group通过ps axo comm,user匹配 apache/httpd/nginx 等进程需要在主机配置中显式指定。writable_mode各取值chown/chgrp/chmod/acl/sticky/skip与writable_use_sudo、writable_recursive、writable_chmod_mode等参数的行为均可在 writable 文档 与源码中核对。常见问题与排障建议部署慢/超时优先检查是否为数据库迁移或插件更新耗时过长适当增大default_timeoutDeployer 支持多主机并行连接多台服务器场景可并行执行任务。上传文件权限不足确认http_user/http_group与become配置正确缓存文件由www-data生成时需要以该用户执行远程任务这正是文档主机示例中-set(become, www-data)的用途。切换后页面异常先确认sw:cache:warmup是否完成若缓存未预热首个用户可能触发较慢的缓存构建。也可手动执行dep sw:cache:warmup补做预热。构建时意外使用开发环境确认sw-build-without-db:get-remote-config已把.env*下载到本地构建目录避免APP_ENVdev、APP_DEBUG1进入产物。回滚出现问题时Deployer 的回滚机制可将current切回上一个 release见 rollback 文档配合deploy:lock的锁机制保证操作安全。小结recipe/shopware.php以“准备 release → Shopware 专属变更 → 缓存预热 → 原子切换”为主线把数据库迁移、插件生命周期、主题、定时任务、JWT 权限与缓存管理全部编排进一次dep deploy调用sw-build-without-db系列任务则把“无数据库构建”这一前置条件落成了可执行的本地编译流水线。对于需要频繁迭代的 Shopware 商城项目这是一套开箱即用、可回滚、可审计的部署方案其详细任务与配置定义可继续查阅 docs/recipe/shopware.md 及仓库内对应的源码文件。赞分享DevOpsCI/CDCLI开发工具运维【免费下载链接】deployerThe PHP deployment tool with support for popular frameworks out of the box项目地址https://gitcode.com/gh_mirrors/de/deployer点击查看免费下载相关推荐使用 Deployer 零停机部署 CodeIgniter 4recipe/codeigniter4 完整实战指南使用 Deployer 零停机部署 CodeIgniter 4recipe/codeigniter4 完整实战指南 本指南讲解如何在 Deployer 中引入DevOpsCI/CDCLI开发工具运维使用 Deployer 零停机部署 Contao 项目完整 Recipe 配置与实战指南使用 Deployer 零停机部署 Contao 项目完整 Recipe 配置与实战指南 导读 本文聚焦于 Deployer 项目中的 Contao 专属部署DevOpsCI/CDCLI开发工具运维使用 Deployer 零停机部署 TYPO3 项目完整实战指南使用 Deployer 零停机部署 TYPO3 项目完整实战指南 TYPO3 是德国企业级 PHP CMS其 Composer 化项目结构 public/DevOpsCI/CDCLI开发工具运维创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考