本文目录导读:

- 使用Docker Volumes(推荐方案)
- 使用Bind Mounts(直接挂载宿主机目录)
- PHP代码层面配置
- 配置Nginx访问日志持久化
- 日志收集方案(ELK Stack)
- 日志轮转配置
- 最佳实践建议
- 监控和告警
在PHP项目的Docker容器中实现日志持久化,主要有以下几种方案:
使用Docker Volumes(推荐方案)
Docker Compose配置
version: '3.8'
services:
php-app:
image: your-php-app:latest
volumes:
- php-logs:/var/www/html/logs
environment:
- LOG_DIR=/var/www/html/logs
volumes:
php-logs:
driver: local
driver_opts:
type: none
o: bind
device: /path/on/host/logs # 宿主机存储路径
Docker命令方式
# 创建卷 docker volume create php-logs # 运行容器时挂载 docker run -d \ --name php-app \ -v php-logs:/var/www/html/logs \ your-php-app:latest
使用Bind Mounts(直接挂载宿主机目录)
version: '3.8'
services:
php-app:
image: your-php-app:latest
volumes:
- /data/logs/php:/var/www/html/logs:rw
# 或相对路径
# - ./logs:/var/www/html/logs
PHP代码层面配置
修改PHP日志配置
// config.php
define('LOG_PATH', '/var/www/html/logs/app.log');
// 确保目录存在
if (!is_dir('/var/www/html/logs')) {
mkdir('/var/www/html/logs', 0777, true);
}
// 日志写入函数
function writeLog($message, $level = 'INFO') {
$logFile = LOG_PATH . '/' . date('Y-m-d') . '.log';
$content = sprintf(
"[%s] [%s] %s%s",
date('Y-m-d H:i:s'),
$level,
$message,
PHP_EOL
);
file_put_contents($logFile, $content, FILE_APPEND | LOCK_EX);
}
使用Monolog(推荐)
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
use Monolog\Handler\RotatingFileHandler;
// 创建日志器
$log = new Logger('app');
// 按天轮转,保留30天
$log->pushHandler(
new RotatingFileHandler('/var/www/html/logs/app.log', 30, Logger::DEBUG)
);
// 使用
$log->info('User login', ['user_id' => 123]);
$log->error('Database connection failed', ['error' => $e->getMessage()]);
配置Nginx访问日志持久化
version: '3.8'
services:
nginx:
image: nginx:alpine
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d
- nginx-logs:/var/log/nginx
depends_on:
- php-app
php-app:
image: your-php-app:latest
volumes:
- php-logs:/var/www/html/logs
volumes:
php-logs:
nginx-logs:
Nginx配置示例
server {
listen 80;
server_name example.com;
access_log /var/log/nginx/access.log main buffer=32k flush=5s;
error_log /var/log/nginx/error.log warn;
location ~ \.php$ {
fastcgi_pass php-app:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
日志收集方案(ELK Stack)
version: '3.8'
services:
php-app:
image: your-php-app:latest
volumes:
- php-logs:/var/www/html/logs
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
filebeat:
image: elastic/filebeat:7.15.0
volumes:
- php-logs:/var/www/html/logs:ro
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
depends_on:
- elasticsearch
elasticsearch:
image: elasticsearch:7.15.0
environment:
- discovery.type=single-node
volumes:
- es-data:/usr/share/elasticsearch/data
kibana:
image: kibana:7.15.0
ports:
- "5601:5601"
depends_on:
- elasticsearch
volumes:
php-logs:
es-data:
日志轮转配置
Docker Compose中配置
version: '3.8'
services:
php-app:
image: your-php-app:latest
volumes:
- php-logs:/var/www/html/logs
logging:
driver: "local"
options:
max-size: "10m" # 单个日志文件最大10MB
max-file: "5" # 保留5个日志文件
compress: "true" # 压缩旧日志
Docker运行命令
docker run -d \ --log-opt max-size=10m \ --log-opt max-file=5 \ --log-opt compress=true \ --name php-app \ your-php-app:latest
最佳实践建议
Dockerfile示例
FROM php:8.1-fpm
# 创建日志目录并设置权限
RUN mkdir -p /var/log/php && \
chown -R www-data:www-data /var/log/php
# 复制PHP配置
COPY php.ini /usr/local/etc/php/
COPY www.conf /usr/local/etc/php-fpm.d/
# 应用代码
COPY . /var/www/html
# 创建挂载点
VOLUME ["/var/www/html/logs", "/var/log/php"]
# 启动脚本
COPY docker-entrypoint.sh /usr/local/bin/
ENTRYPOINT ["docker-entrypoint.sh"]
CMD ["php-fpm"]
权限处理
# docker-entrypoint.sh
#!/bin/bash
set -e
# 确保日志目录存在且权限正确
LOG_DIR="/var/www/html/logs"
if [ ! -d "$LOG_DIR" ]; then
mkdir -p "$LOG_DIR"
fi
chown -R www-data:www-data "$LOG_DIR"
# 执行主命令
exec "$@"
监控和告警
# promtail.yml (Loki日志收集)
scrape_configs:
- job_name: php-logs
static_configs:
- targets: ['localhost']
labels:
job: php-app
__path__: /var/log/php/*.log
pipeline_stages:
- regex:
expression: '^(?P<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) \[(?P<level>\w+)\] (?P<message>.*)$'
- labels:
level:
选择建议:
- 开发环境:使用Bind Mounts简单方便
- 生产环境:使用Docker Volumes + 日志收集系统(ELK/Loki)
- 小型项目:使用RotatingFileHandler + Docker Volumes
- 大型项目:考虑集中式日志管理(ELK Stack或Grafana Loki)