部署链路的基本形态
中小团队常见的内网部署链路是 GitLab 托管代码,Jenkins 负责拉取和执行流水线,目标服务器使用 Laradock 提供 PHP、Nginx、MySQL、Redis 等运行环境。Jenkins 可以把代码同步到目标目录,然后进入 workspace 容器执行依赖安装和缓存命令。
这条链路的重点不是工具名,而是信任链、环境隔离和发布动作可重复。
- Jenkins 使用只读 Deploy Key 拉取代码。
- 目标服务器通过 SSH Key 接受 Jenkins 同步。
- .env 文件由目标环境维护,不进入仓库。
- vendor、storage 缓存和日志不直接从构建机覆盖。
流水线步骤
一个稳妥的流程通常包括拉取代码、安装前检查、rsync 同步、容器内 composer install、Laravel 缓存刷新、权限修正和健康检查。每一步都应该能从日志里看出成功或失败。
如果部署脚本只能在某个人电脑上跑,它就还不是团队资产。Jenkins 的价值在于把发布动作固化成可复用流程。
- 拉取指定分支或 Tag。
- 同步时排除 .env、vendor、storage/logs。
- 容器内执行 composer install --no-dev。
- 执行 config:cache、route:cache、queue 重启等收尾命令。
上线前后检查
部署成功不等于上线成功。上线前要确认分支、提交、数据库变更、环境变量和回滚方案。上线后要确认 HTTP 状态、队列、日志、关键接口和错误告警。
这些检查最好写进发布清单,而不是靠经验记忆。
- 确认 Migration 是否需要手动窗口。
- 确认队列消费者是否重启。
- 确认 Nginx / PHP-FPM / Supervisor 状态。
- 保留本次发布日志和版本号。
两条 SSH 信任链
知识库里的 SOP 明确指出,自动化部署要先打通两条 SSH 通道:Jenkins 到 GitLab 用于拉代码,Jenkins 到目标测试机用于 rsync 和远程命令。很多部署失败不是脚本问题,而是信任链没有分清。
Jenkins 拉 GitLab 应该用 GitLab Deploy Key,默认只读;Jenkins 到目标机可以使用独立 jenkins 用户,只授权具体项目目录。
- Jenkins -> GitLab:Deploy Key,只读。
- Jenkins -> 目标测试机:SSH 免密,最小目录权限。
- 不要给 /var/www 整体 777。
- 不要让 Jenkins 覆盖目标机 .env。
rsync 的排除列表很关键
rsync --delete 很强,也很危险。它能让目标目录与工作区保持一致,但如果排除列表没写好,可能覆盖 .env、删除日志、同步 vendor 或 node_modules,导致环境混乱。
知识库 SOP 建议排除 .git、.env、node_modules、vendor、storage/logs 等路径。依赖安装应该在目标机 Laradock workspace 容器中执行。
- 排除 .env,环境配置由目标机维护。
- 排除 vendor,在目标环境 composer install。
- 排除 storage/logs,保留运行日志。
- 排除 node_modules,避免无意义大文件同步。
composer install 为什么每次都跑
有些部署脚本会用 git diff HEAD~1 判断 composer.lock 是否变化,但知识库里不推荐依赖这种方式。Jenkins 可能是 shallow clone,合并提交和回滚提交也会让 diff 逻辑复杂。
更稳的做法是每次部署都执行 composer install。Composer 会根据 lock 文件判断实际安装内容,未变化时成本通常可接受。
- 生产部署使用 composer install,不使用 composer update。
- composer.lock 必须提交到仓库。
- 安装在 Laradock workspace 容器内执行。
- 失败时停止发布,不继续刷新缓存。
Jenkins Job 的最小验收
部署脚本跑完,只看 Jenkins 成功是不够的。至少要验证 rsync 是否成功、composer 是否成功、目标目录是否保留环境文件、站点或接口是否可访问。
这些检查可以先人工做,之后逐步脚本化,变成 Job 的后置健康检查。
- Console Output 中无 rsync 和 composer 错误。
- 目标项目目录没有被覆盖 .env。
- Laravel/Lumen 能启动或健康接口返回正常。
- 失败日志能定位到 Git、SSH、Docker、Composer 哪一层。