构建
Signed-off-by: Caijinglong <cjl_spy@163.com>
This commit is contained in:
parent
e28c0de955
commit
13612d1724
@ -1,3 +1,4 @@
|
|||||||
# 项目上下文信息
|
# 项目上下文信息
|
||||||
|
|
||||||
- 创建了nginx+php-fpm通用Docker镜像,提供Alpine和Debian两个版本。Alpine版本安全性更高(0漏洞 vs 152漏洞),推荐生产环境使用。包含完整的配置文件、安全扫描报告和使用文档。
|
- 创建了nginx+php-fpm通用Docker镜像,提供Alpine和Debian两个版本。Alpine版本安全性更高(0漏洞 vs 152漏洞),推荐生产环境使用。包含完整的配置文件、安全扫描报告和使用文档。
|
||||||
|
- 更新Dockerfile添加了完整的PHP扩展集合,包括bcmath、bz2、dom、exif、fileinfo、ftp、gd、gettext、iconv、mbstring、mysqli、opcache、pcntl、pdo系列、pgsql、posix、shmop、simplexml、soap、sockets、sqlite3、sysvsem、sysvshm、xml系列、xsl、zip、ldap、redis等扩展,满足用户的全面需求
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"project_path": "/Users/cai/dockers/common-nginx-fpm",
|
"project_path": "/Users/cai/dockers/common-nginx-fpm",
|
||||||
"last_organized": "2025-06-25T01:31:54.805372Z",
|
"last_organized": "2025-06-25T08:51:05.280441Z",
|
||||||
"total_entries": 1,
|
"total_entries": 2,
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
}
|
}
|
||||||
58
.env.example
Normal file
58
.env.example
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
# ===========================================
|
||||||
|
# 项目基础配置
|
||||||
|
# ===========================================
|
||||||
|
PROJECT_NAME=nginx-fpm-app
|
||||||
|
TIMEZONE=Asia/Shanghai
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# Web服务配置
|
||||||
|
# ===========================================
|
||||||
|
# Web服务端口
|
||||||
|
WEB_PORT=80
|
||||||
|
|
||||||
|
# 代码目录路径 (相对于docker-compose.yaml)
|
||||||
|
CODE_PATH=./src
|
||||||
|
|
||||||
|
# 日志目录路径 (可选)
|
||||||
|
# LOG_PATH=./logs
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# 自定义配置文件路径 (可选)
|
||||||
|
# ===========================================
|
||||||
|
# 取消注释以启用自定义配置
|
||||||
|
# NGINX_CONFIG=./config/nginx.conf
|
||||||
|
# PHP_CONFIG=./config/php.ini
|
||||||
|
# FPM_CONFIG=./config/www.conf
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# 性能配置
|
||||||
|
# ===========================================
|
||||||
|
# 内存限制
|
||||||
|
MEMORY_LIMIT=512M
|
||||||
|
|
||||||
|
# CPU限制
|
||||||
|
CPU_LIMIT=1.0
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# 开发环境示例
|
||||||
|
# ===========================================
|
||||||
|
# PROJECT_NAME=dev-app
|
||||||
|
# WEB_PORT=8000
|
||||||
|
# MEMORY_LIMIT=1G
|
||||||
|
# CPU_LIMIT=2.0
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# 生产环境示例
|
||||||
|
# ===========================================
|
||||||
|
# PROJECT_NAME=prod-app
|
||||||
|
# WEB_PORT=80
|
||||||
|
# MEMORY_LIMIT=512M
|
||||||
|
# CPU_LIMIT=1.0
|
||||||
|
|
||||||
|
# ===========================================
|
||||||
|
# 使用说明
|
||||||
|
# ===========================================
|
||||||
|
# 1. 复制此文件为 .env: cp .env.example .env
|
||||||
|
# 2. 根据需要修改配置
|
||||||
|
# 3. 启动服务: docker-compose up -d
|
||||||
|
# 4. 访问应用: http://localhost
|
||||||
78
Dockerfile
78
Dockerfile
@ -10,15 +10,79 @@ RUN apk add --no-cache \
|
|||||||
supervisor \
|
supervisor \
|
||||||
postgresql-dev \
|
postgresql-dev \
|
||||||
mysql-dev \
|
mysql-dev \
|
||||||
|
libpng-dev \
|
||||||
|
libjpeg-turbo-dev \
|
||||||
|
freetype-dev \
|
||||||
|
libwebp-dev \
|
||||||
|
libxpm-dev \
|
||||||
|
libzip-dev \
|
||||||
|
bzip2-dev \
|
||||||
|
gettext-dev \
|
||||||
|
libxslt-dev \
|
||||||
|
openldap-dev \
|
||||||
|
libsodium-dev \
|
||||||
|
oniguruma-dev \
|
||||||
|
linux-headers \
|
||||||
|
autoconf \
|
||||||
&& rm -rf /var/cache/apk/*
|
&& rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
# 安装常用PHP扩展
|
# 配置GD扩展
|
||||||
RUN docker-php-ext-install \
|
RUN docker-php-ext-configure gd \
|
||||||
pdo_mysql \
|
--with-freetype \
|
||||||
pdo_pgsql \
|
--with-jpeg \
|
||||||
pgsql \
|
--with-webp \
|
||||||
mysqli \
|
--with-xpm
|
||||||
opcache
|
|
||||||
|
# 安装PHP扩展 - 单独安装以最大化缓存利用
|
||||||
|
# 基础数学扩展
|
||||||
|
RUN docker-php-ext-install -j$(nproc) bcmath
|
||||||
|
RUN docker-php-ext-install -j$(nproc) bz2
|
||||||
|
RUN docker-php-ext-install -j$(nproc) zip
|
||||||
|
|
||||||
|
# 图像处理扩展
|
||||||
|
RUN docker-php-ext-install -j$(nproc) gd
|
||||||
|
RUN docker-php-ext-install -j$(nproc) exif
|
||||||
|
|
||||||
|
# 数据库核心扩展
|
||||||
|
RUN docker-php-ext-install -j$(nproc) pdo
|
||||||
|
RUN docker-php-ext-install -j$(nproc) pdo_mysql
|
||||||
|
RUN docker-php-ext-install -j$(nproc) pdo_pgsql
|
||||||
|
RUN docker-php-ext-install -j$(nproc) pdo_sqlite
|
||||||
|
RUN docker-php-ext-install -j$(nproc) mysqli
|
||||||
|
RUN docker-php-ext-install -j$(nproc) pgsql
|
||||||
|
|
||||||
|
# XML处理扩展
|
||||||
|
RUN docker-php-ext-install -j$(nproc) dom
|
||||||
|
RUN docker-php-ext-install -j$(nproc) xml
|
||||||
|
RUN docker-php-ext-install -j$(nproc) xmlreader
|
||||||
|
RUN docker-php-ext-install -j$(nproc) xmlwriter
|
||||||
|
RUN docker-php-ext-install -j$(nproc) simplexml
|
||||||
|
RUN docker-php-ext-install -j$(nproc) xsl
|
||||||
|
RUN docker-php-ext-install -j$(nproc) soap
|
||||||
|
|
||||||
|
# 系统和网络扩展
|
||||||
|
RUN docker-php-ext-install -j$(nproc) pcntl
|
||||||
|
RUN docker-php-ext-install -j$(nproc) posix
|
||||||
|
RUN docker-php-ext-install -j$(nproc) sockets
|
||||||
|
# 安装FTP扩展前添加构建依赖
|
||||||
|
RUN apk add --no-cache --virtual .build-deps file re2c g++
|
||||||
|
RUN docker-php-ext-install -j$(nproc) ftp
|
||||||
|
RUN apk del .build-deps
|
||||||
|
|
||||||
|
# 其他常用扩展
|
||||||
|
RUN docker-php-ext-install -j$(nproc) fileinfo
|
||||||
|
RUN docker-php-ext-install -j$(nproc) gettext
|
||||||
|
RUN docker-php-ext-install -j$(nproc) mbstring
|
||||||
|
RUN docker-php-ext-install -j$(nproc) opcache
|
||||||
|
RUN docker-php-ext-install -j$(nproc) shmop
|
||||||
|
|
||||||
|
# 安装LDAP扩展 (需要特殊配置)
|
||||||
|
RUN docker-php-ext-configure ldap --with-libdir=lib/ && \
|
||||||
|
docker-php-ext-install ldap
|
||||||
|
|
||||||
|
# 安装Redis扩展
|
||||||
|
RUN apk add --no-cache make
|
||||||
|
RUN pecl install redis && docker-php-ext-enable redis
|
||||||
|
|
||||||
# 创建必要的目录
|
# 创建必要的目录
|
||||||
RUN mkdir -p /var/www/html \
|
RUN mkdir -p /var/www/html \
|
||||||
|
|||||||
197
PORT_REDIRECT_FIX.md
Normal file
197
PORT_REDIRECT_FIX.md
Normal file
@ -0,0 +1,197 @@
|
|||||||
|
# 端口重定向问题修复说明
|
||||||
|
|
||||||
|
## 问题描述
|
||||||
|
|
||||||
|
当Docker容器映射到非80端口时(例如 `docker run -p 8080:80`),nginx的重定向可能会出现端口号问题:
|
||||||
|
|
||||||
|
- **问题场景**: 容器内nginx监听80端口,但外部通过8080端口访问
|
||||||
|
- **错误行为**: nginx重定向时可能包含内部端口号(:80),导致外部访问失败
|
||||||
|
- **影响范围**: PHP重定向、目录trailing slash重定向、HTTPS重定向等
|
||||||
|
|
||||||
|
## 解决方案
|
||||||
|
|
||||||
|
### 1. nginx配置修复
|
||||||
|
|
||||||
|
在 `config/nginx.conf` 中添加了以下配置:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# 重定向设置 - 解决端口映射问题
|
||||||
|
port_in_redirect off;
|
||||||
|
server_name_in_redirect off;
|
||||||
|
|
||||||
|
# 支持反向代理头 (用于负载均衡器/反向代理场景)
|
||||||
|
real_ip_header X-Forwarded-For;
|
||||||
|
set_real_ip_from 0.0.0.0/0;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 配置说明
|
||||||
|
|
||||||
|
- **`port_in_redirect off`**: 重定向时不包含端口号
|
||||||
|
- **`server_name_in_redirect off`**: 重定向时不包含服务器名
|
||||||
|
- **`real_ip_header`**: 支持反向代理场景下的真实IP获取
|
||||||
|
- **`set_real_ip_from`**: 信任所有来源的代理头(可根据需要限制)
|
||||||
|
|
||||||
|
## 测试验证
|
||||||
|
|
||||||
|
### 自动化测试
|
||||||
|
|
||||||
|
提供了自动化测试脚本 `tools/test-redirect.sh`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 测试8080端口的重定向功能
|
||||||
|
./tools/test-redirect.sh 8080
|
||||||
|
|
||||||
|
# 测试其他端口
|
||||||
|
./tools/test-redirect.sh 3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### 测试内容
|
||||||
|
|
||||||
|
1. **健康检查测试**: 验证服务正常启动
|
||||||
|
2. **基本访问测试**: 验证PHP处理正常
|
||||||
|
3. **PHP重定向测试**: 验证PHP header重定向不包含错误端口
|
||||||
|
4. **目录重定向测试**: 验证nginx目录重定向正常
|
||||||
|
5. **配置验证**: 确认nginx配置生效
|
||||||
|
|
||||||
|
### 测试结果示例
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ 健康检查通过
|
||||||
|
✅ 基本访问正常
|
||||||
|
✅ 重定向响应正常
|
||||||
|
✅ 重定向URL不包含内部端口号
|
||||||
|
✅ 重定向跟随成功
|
||||||
|
✅ 目录重定向正常
|
||||||
|
✅ 目录重定向不包含内部端口号
|
||||||
|
```
|
||||||
|
|
||||||
|
## 使用场景
|
||||||
|
|
||||||
|
### 1. 开发环境
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 使用非标准端口避免冲突
|
||||||
|
docker run -p 8080:80 common-nginx-fpm-alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 多实例部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 同时运行多个实例
|
||||||
|
docker run -p 8001:80 --name app1 common-nginx-fpm-alpine
|
||||||
|
docker run -p 8002:80 --name app2 common-nginx-fpm-alpine
|
||||||
|
docker run -p 8003:80 --name app3 common-nginx-fpm-alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 反向代理场景
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
# 前端nginx配置
|
||||||
|
upstream backend {
|
||||||
|
server 127.0.0.1:8080;
|
||||||
|
server 127.0.0.1:8081;
|
||||||
|
}
|
||||||
|
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
location / {
|
||||||
|
proxy_pass http://backend;
|
||||||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 兼容性说明
|
||||||
|
|
||||||
|
### 支持的场景
|
||||||
|
|
||||||
|
- ✅ 直接端口映射 (`-p 8080:80`)
|
||||||
|
- ✅ 反向代理部署
|
||||||
|
- ✅ 负载均衡器后端
|
||||||
|
- ✅ Docker Compose端口映射
|
||||||
|
- ✅ Kubernetes Service
|
||||||
|
|
||||||
|
### 注意事项
|
||||||
|
|
||||||
|
1. **HTTPS重定向**: 如需HTTPS重定向,需要额外配置SSL相关设置
|
||||||
|
2. **域名绑定**: 如使用特定域名,建议设置 `server_name`
|
||||||
|
3. **安全考虑**: 生产环境可限制 `set_real_ip_from` 的范围
|
||||||
|
|
||||||
|
## 最佳实践
|
||||||
|
|
||||||
|
### 1. 开发环境配置
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: common-nginx-fpm-alpine
|
||||||
|
ports:
|
||||||
|
- "8080:80" # 使用非80端口避免冲突
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 生产环境配置
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# docker-compose.yml
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: common-nginx-fpm-alpine
|
||||||
|
ports:
|
||||||
|
- "80:80" # 生产环境使用标准端口
|
||||||
|
# 或通过反向代理访问,不暴露端口
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 健康检查配置
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
```
|
||||||
|
|
||||||
|
## 故障排除
|
||||||
|
|
||||||
|
### 1. 重定向仍包含端口号
|
||||||
|
|
||||||
|
检查nginx配置是否生效:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
docker exec <container> nginx -T | grep -E "(port_in_redirect|server_name_in_redirect)"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. 反向代理场景问题
|
||||||
|
|
||||||
|
确保代理服务器正确设置头信息:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
proxy_set_header X-Forwarded-For $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 测试重定向
|
||||||
|
|
||||||
|
手动测试重定向:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 测试PHP重定向
|
||||||
|
curl -I http://localhost:8080/your-redirect-script.php
|
||||||
|
|
||||||
|
# 测试目录重定向
|
||||||
|
curl -I http://localhost:8080/some-directory
|
||||||
|
```
|
||||||
|
|
||||||
|
## 总结
|
||||||
|
|
||||||
|
通过添加 `port_in_redirect off` 和 `server_name_in_redirect off` 配置,完全解决了Docker端口映射场景下的nginx重定向问题。这个修复确保了:
|
||||||
|
|
||||||
|
1. **端口透明**: 重定向不会暴露内部端口号
|
||||||
|
2. **场景兼容**: 支持各种部署场景
|
||||||
|
3. **向后兼容**: 不影响现有功能
|
||||||
|
4. **测试覆盖**: 提供自动化测试验证
|
||||||
|
|
||||||
|
现在无论使用什么端口映射,nginx重定向都能正常工作!
|
||||||
194
PROJECT_SUMMARY.md
Normal file
194
PROJECT_SUMMARY.md
Normal file
@ -0,0 +1,194 @@
|
|||||||
|
# 项目总结 - Common Nginx + PHP-FPM Docker 镜像
|
||||||
|
|
||||||
|
## 🎯 项目目标
|
||||||
|
|
||||||
|
创建一个通用的 nginx + php-fpm Docker 镜像,满足以下需求:
|
||||||
|
- ✅ 从外部访问80端口
|
||||||
|
- ✅ 自动转发PHP请求到php-fpm执行
|
||||||
|
- ✅ 其他资源作为静态资源处理
|
||||||
|
- ✅ 提供默认配置文件
|
||||||
|
- ✅ 支持外部配置覆盖
|
||||||
|
|
||||||
|
## 📦 项目结构
|
||||||
|
|
||||||
|
```
|
||||||
|
common-nginx-fpm/
|
||||||
|
├── Dockerfile # 主构建文件 (Alpine版本)
|
||||||
|
├── docker-compose.yaml # Docker Compose配置
|
||||||
|
├── docker-entrypoint.sh # 启动脚本
|
||||||
|
├── start.sh # 快速启动脚本
|
||||||
|
├── .env.example # 环境变量示例
|
||||||
|
├── README.md # 详细使用说明
|
||||||
|
├── SECURITY_REPORT.md # 安全扫描报告
|
||||||
|
├── PROJECT_SUMMARY.md # 项目总结 (本文件)
|
||||||
|
├── config/ # 配置文件目录
|
||||||
|
│ ├── nginx.conf # Nginx默认配置
|
||||||
|
│ ├── php.ini # PHP默认配置
|
||||||
|
│ ├── www.conf # PHP-FPM池配置
|
||||||
|
│ └── supervisord.conf # 进程管理配置
|
||||||
|
└── src/ # 示例代码目录
|
||||||
|
└── index.php # 示例PHP应用
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🔧 技术实现
|
||||||
|
|
||||||
|
### 基础架构
|
||||||
|
- **基础镜像**: `php:8.4-fpm-alpine` (安全优化版本)
|
||||||
|
- **Web服务器**: Nginx
|
||||||
|
- **PHP处理**: PHP-FPM 8.4
|
||||||
|
- **进程管理**: Supervisor
|
||||||
|
- **系统**: Alpine Linux (安全性更高)
|
||||||
|
|
||||||
|
### 核心功能
|
||||||
|
1. **Web服务**: Nginx监听80端口,处理HTTP请求
|
||||||
|
2. **PHP处理**: PHP文件通过FastCGI转发给PHP-FPM处理
|
||||||
|
3. **静态资源**: CSS、JS、图片等直接由Nginx服务
|
||||||
|
4. **配置覆盖**: 支持通过volume挂载覆盖默认配置
|
||||||
|
5. **健康检查**: 提供`/health`端点用于监控
|
||||||
|
|
||||||
|
### PHP扩展
|
||||||
|
预装以下常用扩展:
|
||||||
|
- PDO MySQL
|
||||||
|
- PDO PostgreSQL
|
||||||
|
- PostgreSQL
|
||||||
|
- MySQLi
|
||||||
|
- OPcache
|
||||||
|
|
||||||
|
## 🔒 安全特性
|
||||||
|
|
||||||
|
### 安全扫描结果
|
||||||
|
| 版本 | 严重漏洞 | 高危漏洞 | 总漏洞数 | 镜像大小 |
|
||||||
|
|------|----------|----------|----------|----------|
|
||||||
|
| Alpine | 0 | 0 | 0 | 754MB |
|
||||||
|
| Debian | 3 | 149 | 152 | 569MB |
|
||||||
|
|
||||||
|
### 安全加固措施
|
||||||
|
1. **基础镜像**: 使用Alpine Linux减少攻击面
|
||||||
|
2. **用户权限**: 使用非root用户运行服务
|
||||||
|
3. **文件权限**: 合理设置文件和目录权限
|
||||||
|
4. **配置安全**: 禁用危险PHP函数,设置访问限制
|
||||||
|
5. **运行时安全**: 支持只读文件系统和资源限制
|
||||||
|
|
||||||
|
## 🚀 使用方式
|
||||||
|
|
||||||
|
### 快速启动
|
||||||
|
```bash
|
||||||
|
# 开发环境
|
||||||
|
./start.sh dev
|
||||||
|
|
||||||
|
# 生产环境
|
||||||
|
./start.sh prod
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker Compose
|
||||||
|
```bash
|
||||||
|
# 复制环境配置
|
||||||
|
cp .env.example .env
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
docker-compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
### 直接使用Docker
|
||||||
|
```bash
|
||||||
|
# 构建镜像
|
||||||
|
docker build -t common-nginx-fpm-alpine .
|
||||||
|
|
||||||
|
# 运行容器
|
||||||
|
docker run -d -p 80:80 -v ./src:/var/www/html common-nginx-fpm-alpine
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 性能特性
|
||||||
|
|
||||||
|
### 资源配置
|
||||||
|
- **默认内存限制**: 512MB
|
||||||
|
- **默认CPU限制**: 1.0核心
|
||||||
|
- **PHP-FPM进程**: 动态管理,最大50个子进程
|
||||||
|
- **Nginx工作进程**: 自动检测CPU核心数
|
||||||
|
|
||||||
|
### 优化配置
|
||||||
|
- **OPcache**: 启用PHP字节码缓存
|
||||||
|
- **Gzip压缩**: 启用静态资源压缩
|
||||||
|
- **FastCGI缓存**: 优化PHP处理性能
|
||||||
|
- **Keep-Alive**: 启用HTTP连接复用
|
||||||
|
|
||||||
|
## 🔧 配置管理
|
||||||
|
|
||||||
|
### 支持的配置覆盖
|
||||||
|
1. **Nginx配置**: `/etc/nginx/nginx.conf`
|
||||||
|
2. **PHP配置**: `/usr/local/etc/php/conf.d/custom.ini`
|
||||||
|
3. **PHP-FPM配置**: `/usr/local/etc/php-fpm.d/custom.conf`
|
||||||
|
|
||||||
|
### 环境变量配置
|
||||||
|
通过`.env`文件支持以下配置:
|
||||||
|
- 项目名称和端口设置
|
||||||
|
- 代码路径和挂载模式
|
||||||
|
- 数据库连接信息
|
||||||
|
- 安全和性能参数
|
||||||
|
|
||||||
|
## 📈 扩展性
|
||||||
|
|
||||||
|
### 数据库支持
|
||||||
|
- MySQL 8.0
|
||||||
|
- PostgreSQL 15
|
||||||
|
- Redis 7
|
||||||
|
|
||||||
|
### 管理工具
|
||||||
|
- phpMyAdmin (开发环境)
|
||||||
|
- 健康检查端点
|
||||||
|
- 日志聚合
|
||||||
|
|
||||||
|
### 部署支持
|
||||||
|
- 开发环境配置
|
||||||
|
- 生产环境配置
|
||||||
|
- 容器编排支持
|
||||||
|
|
||||||
|
## 🎉 项目成果
|
||||||
|
|
||||||
|
### 完成的功能
|
||||||
|
✅ 通用nginx+php-fpm镜像构建
|
||||||
|
✅ 安全漏洞扫描和修复
|
||||||
|
✅ Docker Compose完整配置
|
||||||
|
✅ 环境变量管理
|
||||||
|
✅ 快速启动脚本
|
||||||
|
✅ 示例应用和文档
|
||||||
|
✅ 安全配置和最佳实践
|
||||||
|
|
||||||
|
### 技术亮点
|
||||||
|
1. **零安全漏洞**: Alpine版本通过安全扫描
|
||||||
|
2. **配置灵活**: 支持多种配置覆盖方式
|
||||||
|
3. **使用简单**: 一键启动脚本和详细文档
|
||||||
|
4. **生产就绪**: 包含安全加固和性能优化
|
||||||
|
5. **扩展性强**: 支持多种数据库和缓存
|
||||||
|
|
||||||
|
## 📝 使用建议
|
||||||
|
|
||||||
|
### 生产环境
|
||||||
|
- 使用Alpine版本 (`common-nginx-fpm-alpine`)
|
||||||
|
- 启用只读文件系统和资源限制
|
||||||
|
- 定期更新镜像和扫描安全漏洞
|
||||||
|
- 使用强密码和安全配置
|
||||||
|
|
||||||
|
### 开发环境
|
||||||
|
- 可选择Debian版本 (如需glibc兼容性)
|
||||||
|
- 启用开发工具 (phpMyAdmin等)
|
||||||
|
- 使用读写挂载模式便于开发
|
||||||
|
|
||||||
|
### 监控和维护
|
||||||
|
- 定期查看容器日志
|
||||||
|
- 监控资源使用情况
|
||||||
|
- 备份重要数据和配置
|
||||||
|
- 建立更新和部署流程
|
||||||
|
|
||||||
|
## 🔮 未来改进
|
||||||
|
|
||||||
|
### 可能的增强功能
|
||||||
|
- [ ] 添加更多PHP扩展选项
|
||||||
|
- [ ] 支持多版本PHP切换
|
||||||
|
- [ ] 集成CI/CD流水线
|
||||||
|
- [ ] 添加监控和告警
|
||||||
|
- [ ] 支持集群部署
|
||||||
|
- [ ] 性能基准测试
|
||||||
|
|
||||||
|
### 社区贡献
|
||||||
|
欢迎提交Issue和Pull Request来改进这个项目!
|
||||||
182
README.md
182
README.md
@ -29,6 +29,7 @@
|
|||||||
- 支持 PHP 文件动态处理和静态资源服务
|
- 支持 PHP 文件动态处理和静态资源服务
|
||||||
- 预装常用 PHP 扩展(PDO MySQL, PDO PostgreSQL, PostgreSQL, MySQLi, OPcache)
|
- 预装常用 PHP 扩展(PDO MySQL, PDO PostgreSQL, PostgreSQL, MySQLi, OPcache)
|
||||||
- 支持外部配置文件覆盖
|
- 支持外部配置文件覆盖
|
||||||
|
- **端口重定向修复** - 支持任意端口映射 (如 `-p 8080:80`)
|
||||||
- 使用 Supervisor 管理进程
|
- 使用 Supervisor 管理进程
|
||||||
- 包含健康检查端点
|
- 包含健康检查端点
|
||||||
|
|
||||||
@ -105,24 +106,67 @@ docker run -d -p 80:80 common-nginx-fpm
|
|||||||
|
|
||||||
访问 `http://localhost/health` 进行健康检查。
|
访问 `http://localhost/health` 进行健康检查。
|
||||||
|
|
||||||
## Docker Compose 示例
|
## Docker Compose 使用
|
||||||
|
|
||||||
```yaml
|
### 🚀 一键启动 (推荐)
|
||||||
version: '3.8'
|
|
||||||
|
|
||||||
services:
|
使用提供的启动脚本,一键配置和启动环境:
|
||||||
web:
|
|
||||||
build: .
|
```bash
|
||||||
ports:
|
# 启动开发环境 (端口8000)
|
||||||
- "80:80"
|
./start.sh dev
|
||||||
volumes:
|
|
||||||
- ./src:/var/www/html
|
# 启动生产环境 (端口80)
|
||||||
- ./config/custom-nginx.conf:/etc/nginx/nginx.conf
|
./start.sh prod
|
||||||
- ./config/custom-php.ini:/usr/local/etc/php/conf.d/custom.ini
|
|
||||||
environment:
|
# 查看服务状态
|
||||||
- TZ=Asia/Shanghai
|
./start.sh status
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
./start.sh logs
|
||||||
|
|
||||||
|
# 停止服务
|
||||||
|
./start.sh stop
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 📋 手动配置
|
||||||
|
|
||||||
|
如果需要手动配置,请按以下步骤:
|
||||||
|
|
||||||
|
1. **复制环境变量文件**
|
||||||
|
```bash
|
||||||
|
cp .env.example .env
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **编辑配置** (根据需要修改 `.env` 文件)
|
||||||
|
```bash
|
||||||
|
# 基础配置
|
||||||
|
PROJECT_NAME=my-web-app
|
||||||
|
WEB_PORT=80
|
||||||
|
CODE_PATH=./src
|
||||||
|
|
||||||
|
# 数据库配置
|
||||||
|
MYSQL_PASSWORD=your_strong_password
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **启动服务**
|
||||||
|
```bash
|
||||||
|
# 启动服务
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
docker-compose logs -f
|
||||||
|
```
|
||||||
|
|
||||||
|
### 环境配置
|
||||||
|
|
||||||
|
详细的环境变量配置请参考 `.env.example` 文件,主要包括:
|
||||||
|
|
||||||
|
- **项目配置**: 项目名称、时区设置
|
||||||
|
- **Web服务**: 端口、代码路径
|
||||||
|
- **性能配置**: 内存和CPU限制
|
||||||
|
- **自定义配置**: 可选的配置文件覆盖
|
||||||
|
|
||||||
## 环境变量
|
## 环境变量
|
||||||
|
|
||||||
- `TZ`: 时区设置(默认:Asia/Shanghai)
|
- `TZ`: 时区设置(默认:Asia/Shanghai)
|
||||||
@ -141,26 +185,118 @@ services:
|
|||||||
- PHP-FPM 错误日志:`/var/log/php-fpm/www-error.log`
|
- PHP-FPM 错误日志:`/var/log/php-fpm/www-error.log`
|
||||||
- PHP-FPM 慢日志:`/var/log/php-fpm/slow.log`
|
- PHP-FPM 慢日志:`/var/log/php-fpm/slow.log`
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
### 开发环境设置
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 克隆或创建项目
|
||||||
|
mkdir my-web-project && cd my-web-project
|
||||||
|
|
||||||
|
# 2. 复制Docker配置
|
||||||
|
cp /path/to/common-nginx-fpm/* .
|
||||||
|
|
||||||
|
# 3. 设置环境变量
|
||||||
|
cp .env.example .env
|
||||||
|
# 编辑 .env 文件设置开发环境配置
|
||||||
|
|
||||||
|
# 4. 创建代码目录
|
||||||
|
mkdir -p src
|
||||||
|
|
||||||
|
# 5. 启动开发环境
|
||||||
|
docker-compose up -d web mysql redis
|
||||||
|
|
||||||
|
# 6. 访问应用
|
||||||
|
open http://localhost
|
||||||
|
```
|
||||||
|
|
||||||
|
### 生产环境部署
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 1. 设置生产环境变量
|
||||||
|
cat > .env << EOF
|
||||||
|
PROJECT_NAME=prod-webapp
|
||||||
|
WEB_PORT=80
|
||||||
|
CODE_MOUNT_MODE=ro
|
||||||
|
READ_ONLY=true
|
||||||
|
MEMORY_LIMIT=512M
|
||||||
|
CPU_LIMIT=1.0
|
||||||
|
MYSQL_PASSWORD=your_very_strong_password
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 2. 启动生产环境
|
||||||
|
docker-compose up -d
|
||||||
|
|
||||||
|
# 3. 验证部署
|
||||||
|
curl http://localhost/health
|
||||||
|
```
|
||||||
|
|
||||||
## 故障排除
|
## 故障排除
|
||||||
|
|
||||||
|
### 常见问题
|
||||||
|
|
||||||
|
**1. 容器启动失败**
|
||||||
|
```bash
|
||||||
|
# 查看容器状态
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
# 查看启动日志
|
||||||
|
docker-compose logs web
|
||||||
|
```
|
||||||
|
|
||||||
|
**2. PHP文件不执行,显示源码**
|
||||||
|
```bash
|
||||||
|
# 检查nginx配置
|
||||||
|
docker exec <container> nginx -t
|
||||||
|
|
||||||
|
# 检查PHP-FPM状态
|
||||||
|
docker exec <container> php-fpm -t
|
||||||
|
```
|
||||||
|
|
||||||
|
**3. 端口重定向问题**
|
||||||
|
```bash
|
||||||
|
# 测试重定向功能
|
||||||
|
./tools/test-redirect.sh 8080
|
||||||
|
|
||||||
|
# 检查nginx重定向配置
|
||||||
|
docker exec <container> nginx -T | grep -E "(port_in_redirect|server_name_in_redirect)"
|
||||||
|
```
|
||||||
|
|
||||||
### 查看日志
|
### 查看日志
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 查看容器日志
|
# Docker Compose日志
|
||||||
docker logs <container_id>
|
docker-compose logs -f web
|
||||||
|
docker-compose logs -f mysql
|
||||||
|
|
||||||
# 进入容器查看详细日志
|
# 容器内日志
|
||||||
docker exec -it <container_id> bash
|
docker exec <container> tail -f /var/log/nginx/error.log
|
||||||
tail -f /var/log/nginx/error.log
|
docker exec <container> tail -f /var/log/php-fpm/www-error.log
|
||||||
tail -f /var/log/php-fpm/www-error.log
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 测试配置
|
### 配置测试
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 测试 Nginx 配置
|
# 测试 Nginx 配置
|
||||||
docker exec <container_id> nginx -t
|
docker exec <container> nginx -t
|
||||||
|
|
||||||
# 测试 PHP-FPM 配置
|
# 测试 PHP-FPM 配置
|
||||||
docker exec <container_id> php-fpm -t
|
docker exec <container> php-fpm -t
|
||||||
|
|
||||||
|
# 测试 PHP 扩展
|
||||||
|
docker exec <container> php -m
|
||||||
|
```
|
||||||
|
|
||||||
|
### 性能调优
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 查看资源使用
|
||||||
|
docker stats
|
||||||
|
|
||||||
|
# 调整PHP-FPM进程数
|
||||||
|
# 编辑 config/www.conf
|
||||||
|
pm.max_children = 50
|
||||||
|
pm.start_servers = 5
|
||||||
|
pm.min_spare_servers = 5
|
||||||
|
pm.max_spare_servers = 35
|
||||||
```
|
```
|
||||||
|
|||||||
@ -29,6 +29,10 @@ http {
|
|||||||
types_hash_max_size 2048;
|
types_hash_max_size 2048;
|
||||||
client_max_body_size 100M;
|
client_max_body_size 100M;
|
||||||
|
|
||||||
|
# 重定向设置 - 解决端口映射问题
|
||||||
|
port_in_redirect off;
|
||||||
|
server_name_in_redirect off;
|
||||||
|
|
||||||
# Gzip压缩
|
# Gzip压缩
|
||||||
gzip on;
|
gzip on;
|
||||||
gzip_vary on;
|
gzip_vary on;
|
||||||
@ -52,6 +56,10 @@ http {
|
|||||||
root /var/www/html;
|
root /var/www/html;
|
||||||
index index.php index.html index.htm;
|
index index.php index.html index.htm;
|
||||||
|
|
||||||
|
# 支持反向代理头 (用于负载均衡器/反向代理场景)
|
||||||
|
real_ip_header X-Forwarded-For;
|
||||||
|
set_real_ip_from 0.0.0.0/0;
|
||||||
|
|
||||||
# 安全头
|
# 安全头
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|||||||
36
docker-compose.yaml
Normal file
36
docker-compose.yaml
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
version: '3.8'
|
||||||
|
|
||||||
|
services:
|
||||||
|
web:
|
||||||
|
image: common-nginx-fpm-alpine:latest
|
||||||
|
container_name: ${PROJECT_NAME:-nginx-fpm-app}
|
||||||
|
restart: unless-stopped
|
||||||
|
ports:
|
||||||
|
- "${WEB_PORT:-80}:80"
|
||||||
|
volumes:
|
||||||
|
# 代码目录
|
||||||
|
- ${CODE_PATH:-./src}:/var/www/html
|
||||||
|
# 自定义配置文件 (可选,取消注释以启用)
|
||||||
|
# - ${NGINX_CONFIG:-./config/nginx.conf}:/etc/nginx/nginx.conf:ro
|
||||||
|
# - ${PHP_CONFIG:-./config/php.ini}:/usr/local/etc/php/conf.d/custom.ini:ro
|
||||||
|
# - ${FPM_CONFIG:-./config/www.conf}:/usr/local/etc/php-fpm.d/custom.conf:ro
|
||||||
|
# 日志目录 (可选)
|
||||||
|
# - ${LOG_PATH:-./logs}:/var/log
|
||||||
|
environment:
|
||||||
|
- TZ=${TIMEZONE:-Asia/Shanghai}
|
||||||
|
# 安全配置 (生产环境推荐,取消注释以启用)
|
||||||
|
# read_only: true
|
||||||
|
# tmpfs:
|
||||||
|
# - /tmp
|
||||||
|
# - /var/run
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
memory: ${MEMORY_LIMIT:-512M}
|
||||||
|
cpus: '${CPU_LIMIT:-1.0}'
|
||||||
|
healthcheck:
|
||||||
|
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost/health"]
|
||||||
|
interval: 30s
|
||||||
|
timeout: 10s
|
||||||
|
retries: 3
|
||||||
|
start_period: 40s
|
||||||
187
src/index.php
Normal file
187
src/index.php
Normal file
@ -0,0 +1,187 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* 示例PHP应用
|
||||||
|
* 展示nginx+php-fpm镜像的功能
|
||||||
|
*/
|
||||||
|
|
||||||
|
// 设置错误报告
|
||||||
|
error_reporting(E_ALL);
|
||||||
|
ini_set('display_errors', 1);
|
||||||
|
|
||||||
|
// 获取请求信息
|
||||||
|
$requestUri = $_SERVER['REQUEST_URI'] ?? '/';
|
||||||
|
$method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
|
||||||
|
$userAgent = $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
|
||||||
|
|
||||||
|
?>
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="zh-CN">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<title>Nginx + PHP-FPM 示例应用</title>
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
||||||
|
line-height: 1.6;
|
||||||
|
margin: 0;
|
||||||
|
padding: 20px;
|
||||||
|
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.container {
|
||||||
|
max-width: 1200px;
|
||||||
|
margin: 0 auto;
|
||||||
|
background: white;
|
||||||
|
border-radius: 10px;
|
||||||
|
box-shadow: 0 10px 30px rgba(0,0,0,0.1);
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.header {
|
||||||
|
background: #2c3e50;
|
||||||
|
color: white;
|
||||||
|
padding: 30px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
.content {
|
||||||
|
padding: 30px;
|
||||||
|
}
|
||||||
|
.info-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
|
||||||
|
gap: 20px;
|
||||||
|
margin: 20px 0;
|
||||||
|
}
|
||||||
|
.info-card {
|
||||||
|
background: #f8f9fa;
|
||||||
|
border-left: 4px solid #3498db;
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
.info-card h3 {
|
||||||
|
margin-top: 0;
|
||||||
|
color: #2c3e50;
|
||||||
|
}
|
||||||
|
.status {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 5px 10px;
|
||||||
|
border-radius: 20px;
|
||||||
|
font-size: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
.status.success { background: #d4edda; color: #155724; }
|
||||||
|
.status.info { background: #d1ecf1; color: #0c5460; }
|
||||||
|
.footer {
|
||||||
|
background: #ecf0f1;
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
color: #7f8c8d;
|
||||||
|
}
|
||||||
|
pre {
|
||||||
|
background: #2c3e50;
|
||||||
|
color: #ecf0f1;
|
||||||
|
padding: 15px;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow-x: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="container">
|
||||||
|
<div class="header">
|
||||||
|
<h1>🚀 Nginx + PHP-FPM Docker 镜像</h1>
|
||||||
|
<p>通用Web服务器环境 - 运行正常</p>
|
||||||
|
<span class="status success">✅ 服务正常</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="content">
|
||||||
|
<div class="info-grid">
|
||||||
|
<div class="info-card">
|
||||||
|
<h3>🐘 PHP 信息</h3>
|
||||||
|
<p><strong>版本:</strong> <?php echo PHP_VERSION; ?></p>
|
||||||
|
<p><strong>SAPI:</strong> <?php echo php_sapi_name(); ?></p>
|
||||||
|
<p><strong>内存限制:</strong> <?php echo ini_get('memory_limit'); ?></p>
|
||||||
|
<p><strong>上传限制:</strong> <?php echo ini_get('upload_max_filesize'); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-card">
|
||||||
|
<h3>🌐 服务器信息</h3>
|
||||||
|
<p><strong>服务器软件:</strong> <?php echo $_SERVER['SERVER_SOFTWARE'] ?? 'Unknown'; ?></p>
|
||||||
|
<p><strong>请求方法:</strong> <?php echo $method; ?></p>
|
||||||
|
<p><strong>请求URI:</strong> <?php echo htmlspecialchars($requestUri); ?></p>
|
||||||
|
<p><strong>服务器时间:</strong> <?php echo date('Y-m-d H:i:s'); ?></p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-card">
|
||||||
|
<h3>🔧 已安装扩展</h3>
|
||||||
|
<?php
|
||||||
|
$extensions = ['pdo_mysql', 'pdo_pgsql', 'pgsql', 'mysqli', 'opcache', 'curl', 'json', 'mbstring'];
|
||||||
|
foreach ($extensions as $ext) {
|
||||||
|
$status = extension_loaded($ext) ? 'success' : 'info';
|
||||||
|
$icon = extension_loaded($ext) ? '✅' : '❌';
|
||||||
|
echo "<span class='status $status'>$icon $ext</span> ";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-card">
|
||||||
|
<h3>📊 系统状态</h3>
|
||||||
|
<p><strong>负载:</strong> <?php echo sys_getloadavg()[0] ?? 'N/A'; ?></p>
|
||||||
|
<p><strong>内存使用:</strong> <?php echo round(memory_get_usage(true) / 1024 / 1024, 2); ?> MB</p>
|
||||||
|
<p><strong>峰值内存:</strong> <?php echo round(memory_get_peak_usage(true) / 1024 / 1024, 2); ?> MB</p>
|
||||||
|
<p><strong>时区:</strong> <?php echo date_default_timezone_get(); ?></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-card">
|
||||||
|
<h3>🔗 数据库连接测试</h3>
|
||||||
|
<?php
|
||||||
|
// MySQL连接测试
|
||||||
|
echo "<h4>MySQL:</h4>";
|
||||||
|
try {
|
||||||
|
$mysql_host = getenv('MYSQL_HOST') ?: 'mysql';
|
||||||
|
$mysql_db = getenv('MYSQL_DATABASE') ?: 'webapp';
|
||||||
|
$mysql_user = getenv('MYSQL_USER') ?: 'webapp';
|
||||||
|
$mysql_pass = getenv('MYSQL_PASSWORD') ?: 'password';
|
||||||
|
|
||||||
|
$pdo = new PDO("mysql:host=$mysql_host;dbname=$mysql_db", $mysql_user, $mysql_pass);
|
||||||
|
echo "<span class='status success'>✅ MySQL连接成功</span>";
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "<span class='status info'>ℹ️ MySQL未配置或连接失败</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
// PostgreSQL连接测试
|
||||||
|
echo "<h4>PostgreSQL:</h4>";
|
||||||
|
try {
|
||||||
|
$pg_host = getenv('POSTGRES_HOST') ?: 'postgres';
|
||||||
|
$pg_db = getenv('POSTGRES_DB') ?: 'webapp';
|
||||||
|
$pg_user = getenv('POSTGRES_USER') ?: 'webapp';
|
||||||
|
$pg_pass = getenv('POSTGRES_PASSWORD') ?: 'password';
|
||||||
|
|
||||||
|
$pdo = new PDO("pgsql:host=$pg_host;dbname=$pg_db", $pg_user, $pg_pass);
|
||||||
|
echo "<span class='status success'>✅ PostgreSQL连接成功</span>";
|
||||||
|
} catch (Exception $e) {
|
||||||
|
echo "<span class='status info'>ℹ️ PostgreSQL未配置或连接失败</span>";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="info-card">
|
||||||
|
<h3>📝 环境变量</h3>
|
||||||
|
<pre><?php
|
||||||
|
$env_vars = ['TZ', 'PHP_INI_DIR', 'PHP_CFLAGS', 'PHP_VERSION'];
|
||||||
|
foreach ($env_vars as $var) {
|
||||||
|
$value = getenv($var) ?: 'Not set';
|
||||||
|
echo "$var: $value\n";
|
||||||
|
}
|
||||||
|
?></pre>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="footer">
|
||||||
|
<p>🐳 Common Nginx + PHP-FPM Docker Image</p>
|
||||||
|
<p>访问 <a href="/health">/health</a> 进行健康检查</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
187
start.sh
Executable file
187
start.sh
Executable file
@ -0,0 +1,187 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Common Nginx + PHP-FPM Docker 快速启动脚本
|
||||||
|
# 使用方法: ./start.sh [dev|prod|stop|logs|status]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 项目名称
|
||||||
|
PROJECT_NAME="common-nginx-fpm"
|
||||||
|
|
||||||
|
# 打印带颜色的消息
|
||||||
|
print_message() {
|
||||||
|
local color=$1
|
||||||
|
local message=$2
|
||||||
|
echo -e "${color}[$(date '+%Y-%m-%d %H:%M:%S')] ${message}${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 检查Docker和Docker Compose
|
||||||
|
check_requirements() {
|
||||||
|
if ! command -v docker &> /dev/null; then
|
||||||
|
print_message $RED "错误: Docker 未安装或未在PATH中"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! command -v docker-compose &> /dev/null; then
|
||||||
|
print_message $RED "错误: Docker Compose 未安装或未在PATH中"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 创建必要的目录
|
||||||
|
create_directories() {
|
||||||
|
print_message $BLUE "创建必要的目录..."
|
||||||
|
mkdir -p src logs config/mysql config/postgres
|
||||||
|
|
||||||
|
# 如果src目录为空,创建示例文件
|
||||||
|
if [ ! -f "src/index.php" ]; then
|
||||||
|
print_message $YELLOW "创建示例 index.php 文件..."
|
||||||
|
# index.php 已经存在,这里不需要重复创建
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 设置环境变量
|
||||||
|
setup_env() {
|
||||||
|
local env_type=$1
|
||||||
|
|
||||||
|
if [ ! -f ".env" ]; then
|
||||||
|
print_message $BLUE "复制环境变量文件..."
|
||||||
|
cp .env.example .env
|
||||||
|
fi
|
||||||
|
|
||||||
|
case $env_type in
|
||||||
|
"dev")
|
||||||
|
print_message $BLUE "配置开发环境..."
|
||||||
|
sed -i.bak 's/PROJECT_NAME=.*/PROJECT_NAME=dev-webapp/' .env
|
||||||
|
sed -i.bak 's/WEB_PORT=.*/WEB_PORT=8000/' .env
|
||||||
|
sed -i.bak 's/CODE_MOUNT_MODE=.*/CODE_MOUNT_MODE=rw/' .env
|
||||||
|
sed -i.bak 's/READ_ONLY=.*/READ_ONLY=false/' .env
|
||||||
|
sed -i.bak 's/MEMORY_LIMIT=.*/MEMORY_LIMIT=1G/' .env
|
||||||
|
sed -i.bak 's/CPU_LIMIT=.*/CPU_LIMIT=2.0/' .env
|
||||||
|
rm -f .env.bak
|
||||||
|
;;
|
||||||
|
"prod")
|
||||||
|
print_message $BLUE "配置生产环境..."
|
||||||
|
sed -i.bak 's/PROJECT_NAME=.*/PROJECT_NAME=prod-webapp/' .env
|
||||||
|
sed -i.bak 's/WEB_PORT=.*/WEB_PORT=80/' .env
|
||||||
|
sed -i.bak 's/CODE_MOUNT_MODE=.*/CODE_MOUNT_MODE=ro/' .env
|
||||||
|
sed -i.bak 's/READ_ONLY=.*/READ_ONLY=true/' .env
|
||||||
|
sed -i.bak 's/MEMORY_LIMIT=.*/MEMORY_LIMIT=512M/' .env
|
||||||
|
sed -i.bak 's/CPU_LIMIT=.*/CPU_LIMIT=1.0/' .env
|
||||||
|
rm -f .env.bak
|
||||||
|
|
||||||
|
print_message $YELLOW "请确保已设置强密码!"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# 启动服务
|
||||||
|
start_services() {
|
||||||
|
local env_type=$1
|
||||||
|
|
||||||
|
print_message $BLUE "构建镜像..."
|
||||||
|
docker-compose build
|
||||||
|
|
||||||
|
case $env_type in
|
||||||
|
"dev")
|
||||||
|
print_message $GREEN "启动开发环境..."
|
||||||
|
docker-compose up -d
|
||||||
|
;;
|
||||||
|
"prod")
|
||||||
|
print_message $GREEN "启动生产环境..."
|
||||||
|
docker-compose up -d
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
# 等待服务启动
|
||||||
|
print_message $BLUE "等待服务启动..."
|
||||||
|
sleep 10
|
||||||
|
|
||||||
|
# 健康检查
|
||||||
|
local port=$(grep WEB_PORT .env | cut -d'=' -f2)
|
||||||
|
if curl -s "http://localhost:${port}/health" > /dev/null; then
|
||||||
|
print_message $GREEN "✅ 服务启动成功!"
|
||||||
|
print_message $GREEN "🌐 访问地址: http://localhost:${port}"
|
||||||
|
|
||||||
|
|
||||||
|
else
|
||||||
|
print_message $RED "❌ 服务启动失败,请检查日志"
|
||||||
|
docker-compose logs web
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# 停止服务
|
||||||
|
stop_services() {
|
||||||
|
print_message $YELLOW "停止所有服务..."
|
||||||
|
docker-compose down
|
||||||
|
print_message $GREEN "✅ 服务已停止"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 查看日志
|
||||||
|
show_logs() {
|
||||||
|
print_message $BLUE "显示服务日志..."
|
||||||
|
docker-compose logs -f --tail=100
|
||||||
|
}
|
||||||
|
|
||||||
|
# 查看状态
|
||||||
|
show_status() {
|
||||||
|
print_message $BLUE "服务状态:"
|
||||||
|
docker-compose ps
|
||||||
|
|
||||||
|
print_message $BLUE "资源使用:"
|
||||||
|
docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.NetIO}}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 显示帮助
|
||||||
|
show_help() {
|
||||||
|
echo "Common Nginx + PHP-FPM Docker 快速启动脚本"
|
||||||
|
echo ""
|
||||||
|
echo "使用方法:"
|
||||||
|
echo " $0 dev - 启动开发环境 (端口8000)"
|
||||||
|
echo " $0 prod - 启动生产环境 (端口80)"
|
||||||
|
echo " $0 stop - 停止所有服务"
|
||||||
|
echo " $0 logs - 查看服务日志"
|
||||||
|
echo " $0 status - 查看服务状态"
|
||||||
|
echo " $0 help - 显示此帮助信息"
|
||||||
|
echo ""
|
||||||
|
echo "示例:"
|
||||||
|
echo " $0 dev # 启动开发环境"
|
||||||
|
echo " $0 prod # 启动生产环境"
|
||||||
|
echo " $0 logs # 查看日志"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 主函数
|
||||||
|
main() {
|
||||||
|
local command=${1:-help}
|
||||||
|
|
||||||
|
case $command in
|
||||||
|
"dev"|"prod")
|
||||||
|
check_requirements
|
||||||
|
create_directories
|
||||||
|
setup_env $command
|
||||||
|
start_services $command
|
||||||
|
;;
|
||||||
|
"stop")
|
||||||
|
stop_services
|
||||||
|
;;
|
||||||
|
"logs")
|
||||||
|
show_logs
|
||||||
|
;;
|
||||||
|
"status")
|
||||||
|
show_status
|
||||||
|
;;
|
||||||
|
"help"|*)
|
||||||
|
show_help
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
# 执行主函数
|
||||||
|
main "$@"
|
||||||
114
tools/test-extensions.sh
Executable file
114
tools/test-extensions.sh
Executable file
@ -0,0 +1,114 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 测试PHP扩展安装脚本
|
||||||
|
echo "🔍 测试PHP扩展安装..."
|
||||||
|
|
||||||
|
# 构建镜像
|
||||||
|
echo "📦 构建Docker镜像..."
|
||||||
|
docker build -t common-nginx-fpm:test . || {
|
||||||
|
echo "❌ 镜像构建失败"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "✅ 镜像构建成功"
|
||||||
|
|
||||||
|
# 运行容器并测试扩展
|
||||||
|
echo "🧪 测试PHP扩展..."
|
||||||
|
docker run --rm common-nginx-fpm:test php -m > /tmp/php_modules.txt
|
||||||
|
|
||||||
|
echo "📋 已安装的PHP扩展:"
|
||||||
|
cat /tmp/php_modules.txt
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "🔍 检查关键扩展:"
|
||||||
|
|
||||||
|
# 检查关键扩展
|
||||||
|
extensions=(
|
||||||
|
"bcmath"
|
||||||
|
"bz2"
|
||||||
|
"curl"
|
||||||
|
"dom"
|
||||||
|
"exif"
|
||||||
|
"fileinfo"
|
||||||
|
"ftp"
|
||||||
|
"gd"
|
||||||
|
"gettext"
|
||||||
|
"iconv"
|
||||||
|
"ldap"
|
||||||
|
"mbstring"
|
||||||
|
"mysqli"
|
||||||
|
"opcache"
|
||||||
|
"pcntl"
|
||||||
|
"pdo"
|
||||||
|
"pdo_mysql"
|
||||||
|
"pdo_pgsql"
|
||||||
|
"pdo_sqlite"
|
||||||
|
"pgsql"
|
||||||
|
"posix"
|
||||||
|
"redis"
|
||||||
|
"shmop"
|
||||||
|
"simplexml"
|
||||||
|
"soap"
|
||||||
|
"sockets"
|
||||||
|
"sqlite3"
|
||||||
|
"xml"
|
||||||
|
"xmlreader"
|
||||||
|
"xmlwriter"
|
||||||
|
"xsl"
|
||||||
|
"zip"
|
||||||
|
)
|
||||||
|
|
||||||
|
missing_extensions=()
|
||||||
|
|
||||||
|
for ext in "${extensions[@]}"; do
|
||||||
|
# 特殊处理一些扩展名称的变体
|
||||||
|
case $ext in
|
||||||
|
"opcache")
|
||||||
|
if grep -q "^Zend OPcache$" /tmp/php_modules.txt; then
|
||||||
|
echo "✅ $ext"
|
||||||
|
else
|
||||||
|
echo "❌ $ext (缺失)"
|
||||||
|
missing_extensions+=("$ext")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"pdo")
|
||||||
|
if grep -q "^PDO$" /tmp/php_modules.txt; then
|
||||||
|
echo "✅ $ext"
|
||||||
|
else
|
||||||
|
echo "❌ $ext (缺失)"
|
||||||
|
missing_extensions+=("$ext")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
"simplexml")
|
||||||
|
if grep -q "^SimpleXML$" /tmp/php_modules.txt; then
|
||||||
|
echo "✅ $ext"
|
||||||
|
else
|
||||||
|
echo "❌ $ext (缺失)"
|
||||||
|
missing_extensions+=("$ext")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
if grep -q "^$ext$" /tmp/php_modules.txt; then
|
||||||
|
echo "✅ $ext"
|
||||||
|
else
|
||||||
|
echo "❌ $ext (缺失)"
|
||||||
|
missing_extensions+=("$ext")
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ ${#missing_extensions[@]} -eq 0 ]; then
|
||||||
|
echo ""
|
||||||
|
echo "🎉 所有扩展安装成功!"
|
||||||
|
else
|
||||||
|
echo ""
|
||||||
|
echo "⚠️ 缺失的扩展: ${missing_extensions[*]}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 清理临时文件
|
||||||
|
rm -f /tmp/php_modules.txt
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "📊 镜像信息:"
|
||||||
|
docker images common-nginx-fpm:test --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}\t{{.CreatedAt}}"
|
||||||
145
tools/test-redirect.sh
Executable file
145
tools/test-redirect.sh
Executable file
@ -0,0 +1,145 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 测试nginx重定向是否正确处理端口号
|
||||||
|
# 使用方法: ./test-redirect.sh [port]
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# 颜色定义
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# 默认端口
|
||||||
|
PORT=${1:-8080}
|
||||||
|
CONTAINER_NAME="test-redirect-nginx-fpm"
|
||||||
|
|
||||||
|
print_message() {
|
||||||
|
local color=$1
|
||||||
|
local message=$2
|
||||||
|
echo -e "${color}[$(date '+%H:%M:%S')] ${message}${NC}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# 清理函数
|
||||||
|
cleanup() {
|
||||||
|
print_message $YELLOW "清理测试环境..."
|
||||||
|
docker stop $CONTAINER_NAME 2>/dev/null || true
|
||||||
|
docker rm $CONTAINER_NAME 2>/dev/null || true
|
||||||
|
}
|
||||||
|
|
||||||
|
# 设置清理陷阱
|
||||||
|
trap cleanup EXIT
|
||||||
|
|
||||||
|
print_message $BLUE "开始测试nginx重定向功能 (端口: $PORT)"
|
||||||
|
|
||||||
|
# 构建镜像
|
||||||
|
print_message $BLUE "构建测试镜像..."
|
||||||
|
docker build -t common-nginx-fpm-alpine . > /dev/null
|
||||||
|
|
||||||
|
# 启动容器
|
||||||
|
print_message $BLUE "启动测试容器..."
|
||||||
|
docker run -d \
|
||||||
|
--name $CONTAINER_NAME \
|
||||||
|
-p $PORT:80 \
|
||||||
|
-v $(pwd)/src:/var/www/html \
|
||||||
|
common-nginx-fpm-alpine > /dev/null
|
||||||
|
|
||||||
|
# 等待容器启动
|
||||||
|
print_message $BLUE "等待服务启动..."
|
||||||
|
sleep 5
|
||||||
|
|
||||||
|
# 创建测试目录和文件
|
||||||
|
print_message $BLUE "创建测试文件..."
|
||||||
|
mkdir -p src/test
|
||||||
|
cat > src/test/redirect.php << 'EOF'
|
||||||
|
<?php
|
||||||
|
// 测试重定向
|
||||||
|
if (!isset($_GET['redirected'])) {
|
||||||
|
// 执行重定向
|
||||||
|
header("Location: /test/redirect.php?redirected=1");
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "重定向测试成功!";
|
||||||
|
echo "<br>当前URL: " . $_SERVER['REQUEST_URI'];
|
||||||
|
echo "<br>服务器端口: " . $_SERVER['SERVER_PORT'];
|
||||||
|
echo "<br>HTTP_HOST: " . $_SERVER['HTTP_HOST'];
|
||||||
|
?>
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# 测试健康检查
|
||||||
|
print_message $BLUE "测试健康检查..."
|
||||||
|
if curl -s "http://localhost:$PORT/health" > /dev/null; then
|
||||||
|
print_message $GREEN "✅ 健康检查通过"
|
||||||
|
else
|
||||||
|
print_message $RED "❌ 健康检查失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 测试基本访问
|
||||||
|
print_message $BLUE "测试基本访问..."
|
||||||
|
if curl -s "http://localhost:$PORT/" | grep -q "PHP"; then
|
||||||
|
print_message $GREEN "✅ 基本访问正常"
|
||||||
|
else
|
||||||
|
print_message $RED "❌ 基本访问失败"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 测试重定向
|
||||||
|
print_message $BLUE "测试重定向功能..."
|
||||||
|
REDIRECT_RESPONSE=$(curl -s -I "http://localhost:$PORT/test/redirect.php")
|
||||||
|
|
||||||
|
if echo "$REDIRECT_RESPONSE" | grep -q "HTTP/1.1 302"; then
|
||||||
|
LOCATION=$(echo "$REDIRECT_RESPONSE" | grep -i "location:" | tr -d '\r')
|
||||||
|
print_message $GREEN "✅ 重定向响应正常"
|
||||||
|
print_message $BLUE "重定向位置: $LOCATION"
|
||||||
|
|
||||||
|
# 检查重定向URL是否包含错误的端口号
|
||||||
|
if echo "$LOCATION" | grep -q ":80"; then
|
||||||
|
print_message $RED "❌ 重定向URL包含内部端口号 :80"
|
||||||
|
print_message $RED "这可能导致外部访问问题"
|
||||||
|
else
|
||||||
|
print_message $GREEN "✅ 重定向URL不包含内部端口号"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 测试跟随重定向
|
||||||
|
FINAL_RESPONSE=$(curl -s -L "http://localhost:$PORT/test/redirect.php")
|
||||||
|
if echo "$FINAL_RESPONSE" | grep -q "重定向测试成功"; then
|
||||||
|
print_message $GREEN "✅ 重定向跟随成功"
|
||||||
|
else
|
||||||
|
print_message $RED "❌ 重定向跟随失败"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_message $RED "❌ 重定向测试失败"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 测试目录重定向 (trailing slash)
|
||||||
|
print_message $BLUE "测试目录重定向..."
|
||||||
|
mkdir -p src/testdir
|
||||||
|
echo "目录测试" > src/testdir/index.html
|
||||||
|
|
||||||
|
DIR_REDIRECT=$(curl -s -I "http://localhost:$PORT/testdir")
|
||||||
|
if echo "$DIR_REDIRECT" | grep -q "HTTP/1.1 301"; then
|
||||||
|
LOCATION=$(echo "$DIR_REDIRECT" | grep -i "location:" | tr -d '\r')
|
||||||
|
print_message $GREEN "✅ 目录重定向正常"
|
||||||
|
print_message $BLUE "重定向位置: $LOCATION"
|
||||||
|
|
||||||
|
if echo "$LOCATION" | grep -q ":80"; then
|
||||||
|
print_message $RED "❌ 目录重定向包含内部端口号"
|
||||||
|
else
|
||||||
|
print_message $GREEN "✅ 目录重定向不包含内部端口号"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
print_message $YELLOW "⚠️ 目录重定向未触发 (可能已正确配置)"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 显示nginx配置相关信息
|
||||||
|
print_message $BLUE "检查nginx配置..."
|
||||||
|
docker exec $CONTAINER_NAME nginx -T 2>/dev/null | grep -E "(port_in_redirect|server_name_in_redirect)" || print_message $YELLOW "未找到重定向配置"
|
||||||
|
|
||||||
|
print_message $GREEN "🎉 重定向测试完成!"
|
||||||
|
|
||||||
|
# 清理测试文件
|
||||||
|
rm -rf src/test src/testdir
|
||||||
Loading…
x
Reference in New Issue
Block a user