Docker容器日志按天切割核心思路分两类:一是用json-file驱动通过max-size和max-file参数实现近似按天轮转,轻量可靠;二是用宿主机logrotate配合容器内支持重载的服务(如Nginx)实现严格日期命名切割,需postrotate调用nginx -s reopen确保日志切换。

Docker 容器日志按天切割,核心思路分两类:用 Docker 自带的日志驱动轮转(推荐) 或 用宿主机 logrotate 配合容器内服务(如 Nginx)主动重载。两者适用场景不同,配置也不同。
用 Docker json-file 驱动实现按天自动切割
这不是真正“按天”,而是通过 大小+数量 控制,但配合合理参数可达到近似按天效果(比如日均日志 ≤10MB,设 max-size=10m + max-file=7,就相当于保留约一周)。这是最轻量、最可靠的方式,无需额外工具。
- 编辑 /etc/docker/daemon.json(若不存在则新建)
- 写入以下内容(注意 JSON 格式严格,末尾不能有多余逗号):
{"log-driver": "json-file","log-opts": {"max-size": "10m","max-file": "7"}}- 重启 Docker 生效:
sudo systemctl restart docker - 新启动的容器将自动启用该策略;已有容器需重建才生效
✅ 优点:零侵入、全容器统一管理、无额外进程、不依赖容器内 shell
❌ 局限:无法精确按日历日期切割(如 2026-07-29.log),只按文件大小触发轮转
用宿主机 logrotate 对接容器内服务(如 Nginx)
适用于需要严格按日期命名(如 access.log-20260729)、且容器中运行了支持日志重载的服务(Nginx、Apache、MongoDB 等)。关键在于:logrotate 切割后,必须通知服务“重新打开日志文件”,否则新日志仍写入旧文件。
- 确认宿主机已安装 logrotate:
logrotate --version - 在 /etc/logrotate.d/nginx 中写入(假设 Nginx 日志挂载在
/mnt/elements/log/nginx/access.log):
/mnt/elements/log/nginx/access.log {
daily
missingok
rotate 30
compress
delaycompress
dateext
create 0644 root root
sharedscripts
postrotate
docker exec elements_nginx_1 nginx -s reopen 2>/dev/null || true
endscript
}-
daily表示每天执行一次(实际由/etc/cron.daily/logrotate触发,默认凌晨 6:25) -
dateext启用日期后缀(如 .20260729) -
postrotate中的nginx -s reopen是关键——让 Nginx 关闭旧文件句柄、打开新文件 - 确保容器名
elements_nginx_1正确,且容器内有nginx命令可用
用 logrotate 处理纯 stdout/stderr 容器(无内置重载机制)
如果容器只是输出日志到 stdout(比如 Python Flask、Node.js 应用),它本身不响应 reopen 信号。这时不能靠 logrotate 切割容器日志文件(因为 Docker 的 *-json.log 是 Docker 进程独占写入,外部截断会丢失日志或损坏)。
- 正确做法:改用 Docker 的
json-file驱动 +max-size/max-file(第一种方案) - 或接入集中式日志系统(Fluentd / Filebeat → ELK),由采集端做时间切片
- 强行用 logrotate 切割
/var/lib/docker/containers/xxx/*.log属于高危操作,不建议
验证与调试技巧
- 查看某容器当前日志配置:
docker inspect myapp | grep -A 5 LogConfig - 手动触发 logrotate 测试(加
-d先看模拟结果):logrotate -d /etc/logrotate.d/nginx - 强制立即执行:
logrotate -f /etc/logrotate.d/nginx - 检查切割后是否生成新文件、旧文件是否带日期后缀、服务是否继续写新日志


















