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/html -
php-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/html -
php-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服务