PHP 部署运维实战:Nginx、PHP-FPM、Docker 与 CI/CD

系统覆盖 PHP 生产部署:Nginx + PHP-FPM 配置与调优、Docker 化多阶段构建、环境变量管理、CI/CD 流水线、上线灰度与回滚、监控告警与常见故障排查。

引言

写代码只占一半,把 PHP 应用稳、快、可回滚地跑在生产是另一半。本文主线是 Nginx + PHP-FPM 的经典架构(全球 PHP 网站的事实标准),再给 Docker 化与 CI/CD 流水线,最后落到灰度、回滚、监控与高频故障排查——让你部署不再靠「改了试试」。

前置:/php-performance-tuning/(FPM 调参)、/php-security-hardening/(加固)。Docker 深入见 [[docker]]。


目录


1. Nginx + PHP-FPM 架构

为什么是这套:Nginx 处理静态与并发连接,PHP-FPM 独立进程池执行 PHP——两者解耦、各干所长。

用户 → [Nginx] ──静态资源──→ 直接返回
            └──PHP 请求──→ [PHP-FPM] → PHP 代码
                                  → MySQL / Redis / ...

请求流转:Nginx 收到 /index.php → 按 location 匹配 → 用 fastcgi_pass 转发到 FPM 的 socket → FPM 在空闲 worker 上执行 → 返回。

组件职责特点
Nginx静态、反向代理、限流、TLS高并发事件驱动
PHP-FPM执行 PHP进程池 + 按请求创建

理解点:PHP 每请求一个 worker 执行——没有常驻状态,这是 FPM 模型(常驻见 /php-swoole-async/)。


2. Nginx 配置实战:站点与静态资源

最小站点配置:

server {
    listen 80;
    server_name example.com;
    root /var/www/app/public;
    index index.php;

    # 静态资源:Nginx 直接服务,不经过 PHP
    location ~* \.(js|css|png|jpg|woff2)$ {
        expires 30d;
        add_header Cache-Control "public, immutable";
    }

    # PHP 请求转发到 FPM
    location ~ \.php$ {
        try_files $uri =404;
        fastcgi_pass unix:/var/run/php-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
        # 安全头
        add_header X-Content-Type-Options "nosniff" always;
        add_header X-Frame-Options "SAMEORIGIN" always;
    }

    # 前端路由(SPA / Laravel fallback)
    location / {
        try_files $uri $uri/ /index.php?$query_string;
    }
}

关键点:

配置作用
try_files $uri =404防 PHP 文件不存在 500
SCRIPT_FILENAME传 PHP 文件路径(防任意文件执行)
静态资源直接返回不给 FPM 加压
安全头XSS 基础防护

反模式:把所有请求都扔给 PHP(连 .js 也过 FPM)——静态资源必须 Nginx 直出。


3. PHP-FPM 调优:进程池与参数

www.conf 核心参数:

[www]
pm = dynamic                    # dynamic / static / ondemand
pm.max_children = 40            # 最大进程数(核心)
pm.start_servers = 10
pm.min_spare_servers = 5
pm.max_spare_servers = 15
pm.max_requests = 500           # 进程处理 500 请求后重启(防内存泄漏累积)

进程数怎么定(经验公式):

每进程约 20–40MB 内存
max_children ≈ 可用内存 / 每进程内存
例:4GB 内存机器 → 4GB / 40MB ≈ 100,留余量取 60–80

运行模式对比:

模式行为适用
dynamic按需增减流量波动
static固定常驻流量稳定(最稳)
ondemand有请求才起低流量/省内存

opcache 相关(配合 /php-performance-tuning/):

opcache.enable = 1
opcache.memory_consumption = 256
opcache.max_accelerated_files = 20000

4. Docker 化:多阶段构建

多阶段构建:构建阶段装 Composer 依赖,运行阶段只留运行时。

# 阶段 1:依赖构建
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --no-scripts --prefer-dist --no-progress

# 阶段 2:运行时
FROM php:8.3-fpm-alpine
RUN docker-php-ext-install pdo_mysql opcache
COPY --from=vendor /app/vendor /var/www/vendor
COPY . /var/www
WORKDIR /var/www

# FPM 默认启动
EXPOSE 9000
CMD ["php-fpm"]

docker-compose 编排:

services:
  app:
    build: .
    environment:
      APP_ENV: production
      DB_HOST: mysql
    depends_on: [mysql]
  nginx:
    image: nginx:1.27-alpine
    ports: ["80:80"]
    volumes:
      - ./nginx.conf:/etc/nginx/conf.d/default.conf:ro
    depends_on: [app]
  mysql:
    image: mysql:8.4
    environment:
      MYSQL_DATABASE: app

多阶段要点:锁版本(composer.lock)、非 root 运行、.dockerignore(排除 .git/node_modules)。


5. 环境变量与配置管理

配置不进镜像:镜像一套,环境变量区分环境。

// 读取环境变量(Laravel 已内置)
$dbHost = getenv('DB_HOST');
// 生产必须覆盖:APP_ENV、APP_DEBUG、DB_*、REDIS_*

环境管理规范:

配置处理
密钥/密码环境变量/密钥管理(K8s Secret)
环境区分APP_ENV + 对应 env 文件
调试开关生产强制 APP_DEBUG=false
默认值只在开发默认,生产显式注入

安全铁律:APP_DEBUG=true + 线上异常 = 源码/环境泄露——生产必须 false(见 /php-security-hardening/)。


6. CI/CD 流水线

GitHub Actions 完整流水线:

name: Deploy
on:
  push:
    branches: [main]

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: shivammathur/setup-php@v2
        with: { php-version: '8.3', extensions: pdo_mysql, coverage: xdebug }
      - run: composer install --no-interaction
      - run: cp .env.ci .env
      - run: php artisan key:generate
      - run: php artisan test          # 测试
      - run: vendor/bin/phpstan analyse  # 静态分析
      - run: vendor/bin/ecs check     # 代码规范

  deploy:
    needs: test
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - run: docker build -t ${{ vars.IMAGE }} .
      - run: docker push ${{ vars.IMAGE }}
      - run: ssh ${{ secrets.SSH }} 'docker pull && docker compose up -d'

CI 阶段:lint → 静态分析 → 单测 → 集成测试 → 构建 → 部署——测试挂了不部署。


7. 上线策略:灰度与回滚

灰度发布:新版本先给部分流量,验证后再全量。

# Nginx 按比例分流(示意:90% 老版,10% 新版)
# 或用负载均衡权重、开关/Feature Flag
# docker-compose 多版本并存(简化示意)
services:
  app-v2:
    image: app:v2
    environment: { CANARY: "true" }

Feature Flag(更细粒度):

// 功能开关:按用户/百分比放量
if (feature_flag('new_checkout', $user)) {
    $this->handleNewCheckout($order);
} else {
    $this->handleOldCheckout($order);
}

回滚策略:

策略做法
镜像回滚保留上一 tag,docker compose 指回
数据库迁移前滚兼容(迁移可回退),先迁移后代码
快速回滚路由/开关层一键切旧

铁律:数据库迁移要「前向兼容」——先跑迁移再上代码,回滚不拖库。


8. 监控与告警

必监控指标(PHP 应用):

指标告警阈值(参考)
FPM 活跃进程接近 max_children
FPM 队列(backlog)> 0 持续
请求 95 分位延迟超 SLA
5xx 比例> 1%
内存使用> 80%
MySQL 慢查询持续增多
磁盘/CPU常规

落地工具:

指标:Prometheus + php-fpm-exporter + node_exporter
日志:Laravel 结构化日志 → 采集 → 检索
追踪:traceId 贯穿(见 [[observability]])
告警:Alertmanager → 飞书/钉钉/邮件

健康检查:

// /health 端点:探活 + 依赖状态
Route::get('/health', function () {
    try { DB::select('SELECT 1'); } catch (Throwable) {
        return response()->json(['status' => 'degraded'], 503);
    }
    return response()->json(['status' => 'ok']);
});

9. 高频故障排查

故障 → 排查路径:

故障先看什么
502 Bad GatewayFPM 挂了/未启动、socket 路径不匹配
504 Gateway TimeoutFPM max_execution_time/Nginx proxy_read_timeout
500 内部错误应用日志(Laravel log / stderr)
页面空白PHP 错误被屏蔽 → display_errors 临时开(生产关)
静态 404Nginx root 路径/try_files
慢请求FPM slow log + MySQL 慢查询
内存爆pm.max_requests 没设 → 泄漏累积

常用排查命令:

# FPM 状态
curl localhost/status            # pm.status_path 暴露的指标
php-fpm -t                       # 语法检查

# Nginx
nginx -t
tail -f /var/log/nginx/error.log

# 进程与连接
ps aux | grep php-fpm
ss -lntp | grep 9000

记忆:502 是「FPM 连不上」,504 是「FPM 太慢」,500 看应用日志——先定层再深挖。


10. 速查表

需求做法
PHP 部署架构Nginx + PHP-FPM
静态资源Nginx 直出 + 缓存头
FPM 进程数内存估算,dynamic 起步
容器化多阶段 Docker + compose
配置管理环境变量注入
上线灰度/Feature Flag + 可回滚
迁移前向兼容,先迁移后代码
监控5xx/延迟/FPM 队列 + 告警
排查502→FPM、504→超时、500→日志

一句话记忆:Nginx 管静态与转发、FPM 管执行;Docker 多阶段、环境变量管配置;灰度放量、镜像回滚、迁移前向兼容;502 查 FPM、504 查超时、500 看日志。


延伸阅读

  • /php-performance-tuning/ — FPM/OPcache 深度调优
  • /php-security-hardening/ — 生产加固与环境配置
  • /php-microservices-message-queue/ — 部署后服务间的通信
  • [[docker]] — 容器化与编排深入
  • [[devops]] — CI/CD 与监控运维

继续阅读

探索更多技术文章

浏览归档,发现更多关于系统设计、工具链和工程实践的内容。

全部文章 返回首页

「php」更多文章

  1. PHP 面向对象与设计模式:SOLID、常用模式与 Laravel 实践
  2. PHP 静态分析与代码质量:PHPStan、Psalm、Rector 与 CI 门禁
  3. PHP 缓存与 Redis 实战:缓存模式、数据结构与一致性