Docker容器中Nginx日志轮转配置完全指南

Nginx Docker 日志切割配置指南

问题背景

在 Docker 容器中运行的 Nginx,其日志文件会随着时间推移无限增长。而 Docker 容器通常采用轻量化设计,内部并未包含 logrotate 等日志管理服务。

解决方案:利用宿主机的 logrotate 服务,对容器内的日志文件进行统一管理和切割。


为什么 Nginx 没有内置日志切割功能?

这是许多开发者的疑问。答案源于 Nginx 的设计哲学——遵循 Unix 哲学:专注做好一件事

设计理念

  • 职责分离:Nginx 专注于提供高性能的 Web 服务,日志管理则交由专业的系统工具处理
  • 避免重复造轮:Linux 生态已有成熟的日志管理工具(如 logrotate),无需在应用层重复实现
  • 保持核心轻量:不集成日志切割功能,使 Nginx 核心代码保持简洁高效

Nginx 提供的配合机制

Nginx 通过信号机制为外部日志切割工具提供支持:

1
nginx -s reopen   # 重新打开日志文件

该命令允许外部工具在完成日志切割后,通知 Nginx 重新打开日志文件,实现无缝衔接。


什么是 logrotate

logrotate 是 Linux 系统内置的日志管理工具,用于自动完成日志文件的切割、压缩和清理工作。

  • 配置目录:/etc/logrotate.d/
  • 工作机制:该目录下的每个文件都是独立的日志切割配置,系统定期读取并执行

配置步骤

1. 创建 logrotate 配置文件

在宿主机上创建 /etc/logrotate.d/nginx 文件,内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
/home/nginx/logs/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 644 root root
sharedscripts
postrotate
docker exec <容器名称> nginx -s reopen
endscript
}

重要提示:

  • <容器名称> 替换为实际的 Docker 容器名称(使用 docker ps 命令查看)
  • 使用 reopen 而非 reload:reopen 仅重新打开日志文件,而 reload 会重载整个 Nginx 配置

配置参数说明:

参数 说明
daily 每天执行一次日志轮转
rotate 30 保留最近 30 天的日志备份
compress 对旧日志文件进行 gzip 压缩
delaycompress 延迟一个周期后再压缩(保留最近一次切割的日志为未压缩状态)
missingok 如果日志文件不存在,不报错
notifempty 日志文件为空时不执行轮转
create 644 root root 创建新日志文件并设置权限
sharedscripts 所有日志文件轮转完成后,仅执行一次脚本
postrotate 日志轮转后执行的命令

2. 设置定时任务

通过 cron 定时任务确保 logrotate 定期执行:

1
2
3
4
5
# 编辑 root 用户的 crontab
sudo crontab -e

# 添加定时任务(每天 23:59 执行)
59 23 * * * /usr/sbin/logrotate -f /etc/logrotate.d/nginx >/dev/null 2>&1

3. 测试配置

在正式启用前,建议先测试配置的正确性:

1
2
3
4
5
# 调试模式:检查配置语法(不实际执行)
logrotate -d /etc/logrotate.d/nginx

# 强制执行一次(用于验证效果)
logrotate -f /etc/logrotate.d/nginx

实施效果

配置完成后,系统将自动实现以下功能:

  • ✅ 每天自动切割日志文件
  • ✅ 保留最近 30 天的历史日志
  • ✅ 自动压缩归档文件,节省磁盘空间
  • ✅ 自动清理过期日志

日志文件示例:

1
2
3
4
access.log              # 当前活跃日志
access.log-20250115 # 昨天的日志(未压缩)
access.log-20250114.gz # 前天的日志(已压缩)
access.log-20250113.gz # 更早的日志(已压缩)

总结

通过宿主机 logrotate + Docker exec 的组合方案,我们既保持了容器的轻量化特性,又实现了完善的日志管理功能。这种方案充分体现了 Unix 哲学中”组合小工具完成复杂任务”的设计思想。