本文目录导读:

在 PHP 项目中实现 CI/CD(持续集成/持续部署),核心目标是自动化代码的构建、测试、部署流程,下面从工具选型、流程设计和具体配置示例三个方面来详细说明。
核心流程概述
一个典型的 PHP CI/CD 流水线包含以下阶段:
代码提交(Git Push)
→ 触发 CI
→ 环境准备(Composer install)
→ 代码质量检查(PHPStan, PHPCS)
→ 单元测试(PhpUnit)
→ 构建产物(可选, 如打包Docker镜像)
→ 部署到测试/预发/生产环境
工具选型
代码托管 & CI 平台
- GitHub Actions(最推荐,与GitHub深度集成,免费额度足够小团队)
- GitLab CI/CD(配合自建GitLab或GitLab SaaS)
- Jenkins(适合复杂、高度自定义的企业项目)
- Bitbucket Pipelines(如果代码托管在Bitbucket)
- Drone / CircleCI / Travis CI(其他选择)
测试与代码质量工具
- Composer:依赖管理
- PHPUnit:单元测试框架
- PHP_CodeSniffer:代码风格检查
- PHPStan / Psalm:静态分析(推荐必须使用)
- Deptrac:依赖检查(大型项目推荐)
部署方式
- 通过 SSH + rsync/scp:传统、直接
- 通过 Docker 镜像:更现代化、环境一致性好
- 使用 Envoy / Deployer:PHP 专用的部署工具
- 通过 K8s:容器化后的最佳选择
具体配置示例(两种主流方案)
GitHub Actions + Docker 部署(推荐)
项目根目录创建 .github/workflows/deploy.yml:
name: PHP CI/CD
on:
push:
branches: [ main, develop ]
pull_request:
branches: [ main ]
jobs:
test_and_lint:
runs-on: ubuntu-latest
services:
# 如果需要MySQL或Redis服务
mysql:
image: mysql:8.0
env:
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: test
ports:
- 3306:3306
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
steps:
- uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: mbstring, intl, pdo_mysql, redis
coverage: xdebug
- name: Validate composer.json
run: composer validate --strict
- name: Get Composer cache directory
id: composer-cache
run: echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
- name: Cache Composer dependencies
uses: actions/cache@v3
with:
path: ${{ steps.composer-cache.outputs.dir }}
key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
restore-keys: ${{ runner.os }}-composer-
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Copy .env
run: cp .env.example .env
- name: Generate key
run: php artisan key:generate
- name: Run PHPStan (静态分析)
run: vendor/bin/phpstan analyse --level=6 app/
- name: Run PHPCS (代码风格)
run: vendor/bin/phpcs --standard=PSR12 app/
- name: Run tests (单元测试)
run: vendor/bin/phpunit --coverage-text
- name: Run security check (安全扫描)
run: vendor/bin/security-checker security:check composer.lock
build_and_deploy:
needs: [test_and_lint] # 依赖测试阶段通过
if: github.ref == 'refs/heads/main' # 仅 main 分支执行部署
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Build Docker Image
run: |
docker build -t your-app:${{ github.sha }} .
docker tag your-app:${{ github.sha }} your-registry/your-app:latest
- name: Push to Container Registry
uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- run: docker push your-registry/your-app:latest
- name: Deploy to Production
run: |
# 假设你有一个部署脚本来更新K8s或服务器
ssh deployer@your-server "cd /var/www/app && git pull && docker-compose up -d"
GitLab CI/CD + Deployer 部署(适合 PHP 传统项目)
项目根目录创建 .gitlab-ci.yml:
stages:
- test
- deploy
variables:
COMPOSER_CACHE_DIR: '$CI_PROJECT_DIR/.composer-cache'
cache:
paths:
- vendor/
- .composer-cache/
before_script:
- apt-get update -qq && apt-get install -y -qq git unzip
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
- composer install --prefer-dist --no-ansi --no-interaction --no-progress
test:phpunit:
stage: test
script:
- cp .env.ci .env
- php artisan key:generate
- php artisan migrate --force
- ./vendor/bin/phpunit --coverage-text --colors=never
only:
- main
- develop
test:phpstan:
stage: test
script:
- ./vendor/bin/phpstan analyse app/ --level=6 --no-progress
only:
- main
- develop
deploy:staging:
stage: deploy
script:
- composer install --prefer-dist --no-dev --optimize-autoloader
- php artisan optimize
# 使用 Deployer 或其他部署工具
- php deployer.phar deploy staging
only:
- develop
environment:
name: staging
url: https://staging.your-site.com
deploy:production:
stage: deploy
script:
- composer install --prefer-dist --no-dev --optimize-autoloader
- php artisan optimize
- php deployer.phar deploy production
only:
- main
when: manual # 生产环境需要手动触发
environment:
name: production
url: https://your-site.com
配合 deployer 的 deploy.php 配置文件(示例):
<?php
namespace Deployer;
require 'recipe/laravel.php'; // 如果是Laravel项目
// 配置
set('repository', 'git@gitlab.com:your/project.git');
set('git_tty', true);
set('shared_files', ['.env']);
set('shared_dirs', ['storage']);
set('writable_dirs', ['storage', 'bootstrap/cache']);
// 服务器
host('production')
->hostname('your-server-ip')
->user('deploy')
->port(22)
->forwardAgent()
->multiplexing(true)
->addSshOption('UserKnownHostsFile', '/dev/null')
->set('deploy_path', '/var/www/app');
关键实践与注意事项
环境变量管理
- 永远不要在代码仓库中保留
.env文件(.gitignore 排除)。 - 在 CI/CD 平台(GitHub Secrets / GitLab Variable)中存储数据库密码、API Key 等敏感信息。
- 部署时通过脚本生成或下载
.env文件。
数据库迁移
- 在测试/部署阶段执行
php artisan migrate。 - 生产环境迁移必须谨慎,建议使用自动化回滚脚本,且最好在无流量时段执行。
- 考虑是否使用
--force参数,以及是否在 deploy 的不同步骤执行。
缓存与优化
- 在部署生产时执行:
php artisan optimize(Laravel),php artisan config:cache,route:cache,view:cache。 - 注意:配置缓存后,
.env修改不会生效,需重新执行。
零停机部署
- 方案一(传统):使用
deployer创建软链接,新版本部署在releases/目录下,完成后将current链接指向新版本。 - 方案二(容器化):使用 Docker + 负载均衡,先启动新容器,旧容器保留,待健康检查通过后移除旧容器。
- 方案三(K8s):
RollingUpdate策略,逐步替换 Pod。
回滚策略
- 在部署脚本中保留回滚能力(
deployer原生支持rollback)。 - CI/CD 流水线中为部署任务添加手动确认步骤(特别是生产环境)。
安全性
- 在 CI 中使用
security-checker或symfony的安全检查工具扫描依赖漏洞。 - 限制 CI/CD 触发条件(仅
main分支可部署生产)。 - 使用 SSH Keys / Deploy Tokens 而不是密码。
针对不同 PHP 框架的注意点
| 框架 | 额外 CI/CD 步骤 |
|---|---|
| Laravel | artisan migrate,artisan optimize,artisan passport:install(如果用到) |
| Symfony | cache:clear,assets:install,doctrine:migrations:migrate |
| ThinkPHP | 路由缓存,配置缓存 |
| WordPress | 通常不需要复杂CI/CD,重点在主题/插件测试 |
| 纯PHP | 关注静态分析 + 单元测试 |
进阶:蓝绿部署与金丝雀发布
如果项目规模较大,可以:
-
蓝绿部署:
- 准备两套完全相同的环境(蓝和绿)。
- 新版本部署到非活跃环境,测试通过后切换流量。
- 切换失败可快速切回。
-
金丝雀发布:
- 新版本先部署到少量实例(如1台服务器)。
- 监控几分钟,如果无异常再逐步全量部署。
- 需要配合负载均衡(如 Nginx + upstream)或 K8s Service。
最佳实践清单
- ✅ 统一开发、测试、生产环境(Docker 或 Vagrant)。
- ✅ 每次代码提交都自动触发测试。
- ✅ 代码质量检查(PHPStan级别≥5,代码规范PHPCS)。
- ✅ 单元测试覆盖核心业务逻辑。
- ✅ 生产部署使用“手动触发” + “回滚按钮”。
- ✅ 敏感信息用 CI/CD 的 Secrets 功能。
- ✅ 日志与监控(部署后自动检查 200 状态码、日志错误率)。
快速上手建议
小型项目:GitHub Actions + 直接 SSH 部署。 中型项目:GitLab CI + Docker Compose + 多环境。 大型/企业级:K8s + GitOps (ArgoCD/Flux) + 蓝绿/金丝雀。
选择方案时,平衡“自动化程度”与“团队维护成本”,先跑通简版再逐步完善。