07-PHP服务配置详解
本文档详细介绍PHP服务的配置,采用双容器架构(nginx:alpine + php:8.2-fpm-alpine),实现静态文件服务和动态PHP处理分离。
双容器架构说明
PHP服务由两个容器组成:
┌─────────────────────────────────────────────────────────┐ │ PHP服务 (双容器) │ ├─────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────┐ ┌─────────────────────────┐ │ │ │ php (nginx:alpine)│ │ php-fpm (php:8.2-fpm) │ │ │ │ 172.20.2.11 │ │ 172.20.2.21 │ │ │ │ │ │ │ │ │ │ 监听: 80 │◄───│ fastcgi_pass │ │ │ │ │ │ 监听: 9000 │ │ │ │ 静态文件 │ │ PHP解析 │ │ │ └─────────────────────┘ └─────────────────────────┘ │ │ │ │ shared volume: web-data │ │ (/usr/share/nginx/html = /var/www/html) │ └─────────────────────────────────────────────────────────┘
容器职责
| 容器 | 镜像 | IP | 职责 |
|---|---|---|---|
| php | nginx:alpine | 172.20.2.11 | 静态文件服务、接收请求、转发PHP到fastcgi |
| php-fpm | php:8.2-fpm-alpine | 172.20.2.21 | 解析PHP代码、执行逻辑 |
通信流程
客户端请求 → nginx-lb → php(172.20.2.11:80) │ ▼ fastcgi_pass php-fpm(172.20.2.21:9000) │ ▼ 读取/写入 共享卷 web-data
nginx配置(php-node*.conf)
php-node1.conf
user nginx; worker_processes auto; error_log /var/log/nginx/error.log warn; pid /var/run/nginx.pid; events { worker_connections 1024; use epoll; multi_accept on; } http { include /etc/nginx/mime.types; default_type application/octet-stream; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for" ' 'request_time: $request_time'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; client_max_body_size 100M; gzip on; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml; server { listen 80; server_name localhost; root /usr/share/nginx/html; index index.php index.html index.htm; location / { try_files $uri $uri/ /index.php?$query_string; } location ~ \.php$ { fastcgi_pass 172.20.2.21:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name; include fastcgi_params; } location /health { access_log off; return 200 "php-healthy\n"; add_header Content-Type text/plain; } error_page 404 /404.html; error_page 500 502 503 504 /50x.html; } }节点配置差异
| 节点 | 配置文件 | fastcgi_pass | root |
|---|---|---|---|
| Node1 | php-node1.conf | 172.20.2.21:9000 | /usr/share/nginx/html |
| Node2 | php-node2.conf | 172.20.2.22:9000 | /usr/share/nginx/html |
| Node3 | php-node3.conf | 172.20.2.23:9000 | /usr/share/nginx/html |
关键配置项详解
1. fastcgi_pass
location ~ \.php$ { fastcgi_pass 172.20.2.21:9000; # 指向本节点的php-fpm容器 ... }重要:
不能使用
127.0.0.1:9000或localhost:9000必须使用php-fpm的外部IP(macvlan分配的IP)
每个节点的php.conf中IP不同
2. root路径
root /usr/share/nginx/html; # nginx容器内路径
注意:
nginx容器使用
/usr/share/nginx/htmlphp-fpm容器使用
/var/www/html通过共享卷
web-data保持一致
3. SCRIPT_FILENAME
fastcgi_param SCRIPT_FILENAME /var/www/html$fastcgi_script_name;
说明:
必须是nginx容器内的完整路径
与root配置保持一致
php.ini配置
[PHP] upload_max_filesize = 50M post_max_size = 50M max_execution_time = 60 memory_limit = 256M display_errors = Off log_errors = On error_log = /var/log/php/error.log date.timezone = Asia/Shanghai [Session] session.save_handler = redis session.save_path = "tcp://172.20.3.11:6379?auth=YourStr0ng!Pass" [opcache] opcache.enable = 1 opcache.memory_consumption = 128 opcache.interned_strings_buffer = 8 opcache.max_accelerated_files = 4000
配置项说明
| 配置 | 说明 |
|---|---|
upload_max_filesize | 上传文件最大大小 |
post_max_size | POST数据最大大小 |
max_execution_time | 脚本最大执行时间 |
memory_limit | 脚本最大内存 |
session.save_handler | Session存储方式 |
session.save_path | Redis服务器地址 |
opcache.* | OPcache加速配置 |
Docker Compose配置
Node1示例
php: image: nginx:alpine container_name: php networks: backend-net: ipv4_address: 172.20.2.11 volumes: - ./config/php/php-node1.conf:/etc/nginx/nginx.conf:ro - web-data:/usr/share/nginx/html restart: unless-stopped healthcheck: test: ["CMD-SHELL", "curl -f http://localhost/index.php > /dev/null 2>&1 || exit 1"] interval: 10s timeout: 5s retries: 3 php-fpm: build: ./config/php-fpm # 基于php:8.2-fpm-alpine安装pdo_mysql container_name: php-fpm networks: backend-net: ipv4_address: 172.20.2.21 volumes: - ./config/php/php.ini:/usr/local/etc/php/conf.d/custom.ini:ro - web-data:/var/www/html restart: unless-stopped healthcheck: test: ["CMD", "php-fpm", "-t"] interval: 10s timeout: 5s retries: 3 volumes: web-data:
服务IP分配
| 节点 | php | php-fpm |
|---|---|---|
| Node1 | 172.20.2.11 | 172.20.2.21 |
| Node2 | 172.20.2.12 | 172.20.2.22 |
| Node3 | 172.20.2.13 | 172.20.2.23 |
部署注意事项
1. 配置文件必须先创建
# 确保配置文件存在 touch /opt/cluster-deploy/config/php/php-node1.conf touch /opt/cluster-deploy/config/php/php-node2.conf touch /opt/cluster-deploy/config/php/php-node3.conf touch /opt/cluster-deploy/config/php/php.ini
2. 正确配置fastcgi_pass
Node1:
fastcgi_pass 172.20.2.21:9000;Node2:
fastcgi_pass 172.20.2.22:9000;Node3:
fastcgi_pass 172.20.2.23:9000;
3. 共享卷一致性
nginx容器挂载:
web-data:/usr/share/nginx/htmlphp-fpm容器挂载:
web-data:/var/www/html确保两边路径对应正确
4. 健康检查端点
每个php容器提供/health端点:
# 测试健康状态 curl http://172.20.2.11/health curl http://172.20.2.12/health curl http://172.20.2.13/health
创建测试页面
# 创建测试页面 cat > /opt/cluster-deploy/index.php << 'EOF' <?php echo "<h1>PHP Service Test</h1>"; echo "<p>Server: " . gethostname() . "</p>"; echo "<p>PHP Version: " . phpversion() . "</p>"; echo "<p>Time: " . date('Y-m-d H:i:s') . "</p>"; echo "<p>REMOTE_ADDR: " . $_SERVER['REMOTE_ADDR'] . "</p>"; # 测试Redis连接 try { $redis = new Redis(); $redis->connect('172.20.3.11', 6379); $redis->auth('YourStr0ng!Pass'); echo "<p>Redis: Connected</p>"; } catch (Exception $e) { echo "<p>Redis: Error - " . $e->getMessage() . "</p>"; } # 测试Session session_start(); $_SESSION['test'] = 'Hello from PHP!'; echo "<p>Session ID: " . session_id() . "</p>"; echo "<p>Session Data: " . ($_SESSION['test'] ?? 'Not set') . "</p>"; ?> EOF # 复制到共享卷 docker run --rm -v web-data:/data -v $(pwd)/index.php:/index.php alpine cp /index.php /data/常见问题
Q1: 502 Bad Gateway
检查php-fpm是否运行:
docker ps | grep php-fpm检查fastcgi_pass地址是否正确
检查网络连通性:
ping 172.20.2.21
Q2: PHP代码不执行
检查SCRIPT_FILENAME路径
确认root路径与挂载路径一致
Q3: Session无法写入Redis
检查Redis连接:
telnet 172.20.3.11 6379验证密码认证
检查php.ini中的session配置
验证命令
# 查看PHP容器 docker ps | grep -E "php|php-fpm" # 测试PHP服务 curl http://172.20.2.11/index.php curl http://172.20.2.12/index.php curl http://172.20.2.13/index.php # 测试健康检查 curl http://172.20.2.11/health curl http://172.20.2.12/health curl http://172.20.2.13/health # 查看PHP-FPM日志 docker logs php-fpm # 查看PHP版本 docker exec php-fpm php -v
下一步
08-Redis配置详解.md - 了解Redis集群配置
12-验证测试.md - 验证PHP服务