Nginx没有本机日志轮换,因此需要外部工具,例如logrotate。 Nginx提出了一个挑战,即日志必须在轮换后重新打开。如果pid在/ var / run中可用,您可以向其发送USR1信号。
但是当在docker容器中运行时,/ var / run中缺少pid文件(并且pid实际上属于主机,因为它在技术上是一个主机进程)。
如果您不重新打开日志,nginx根本不会记录任何内容,但它会继续作为Web服务器,反向代理等运行。
答案 0 :(得分:3)
您可以使用docker inspect从Pid属性获取进程ID,并使用kill -USR1 {pid}让nginx重新打开日志。
这是我创建的/etc/logrotate.d/nginx文件:
/var/log/nginx/access.log
{
size 2M
rotate 10
missingok
notifempty
compress
delaycompress
postrotate
docker inspect -f '{{ .State.Pid }}' nginx | xargs kill -USR1
endscript
}
答案 1 :(得分:0)
如果您想在专用容器中运行 logrotate(例如,同时轮换 nginx 日志和 Rails 的文件日志)而不是在主机上运行,那么我是这样做的。迄今为止最棘手的部分是如上所述,将重新加载信号发送到 nginx、Rails 等,以便它们在轮换后创建并记录到新的日志文件。
为了让 nginx (/etcetera) 重新加载从而连接到新的日志文件,我通过套接字使用 Docker's API 将 exec 命令发送到其他容器。它需要一个带有 JSON 格式命令的 POST,它用一个 exec 实例 ID 响应。然后您需要显式运行该实例。
来自我的 logrotate.conf 文件的示例 postrotate 部分:
postrotate
exec_id=`curl -X POST --unix-socket /var/run/docker.sock \
-H "Content-Type: application/json" \
-d '{"cmd": ["nginx", "-s", "reopen"]}' \
http:/v1.41/containers/hofg_nginx_1/exec \
| jq -r '.Id'`
curl -X POST --unix-socket /var/run/docker.sock \
-H "Content-Type: application/json" \
-d '{"Detach": true}' \
http:/v1.41/exec/"$exec_id"/start
endscript
exec_id=`curl -X POST --unix-socket /var/run/docker.sock \
这是两次调用 curl 中的第一次,将结果保存到变量中以供第二次使用。另外不要忘记(不安全地)将套接字安装到容器中,'/var/run/docker.sock:/var/run/docker.sock'
-H "Content-Type: application/json" \
-d '{"cmd": ["nginx", "-s", "reopen"]}' \
Docker 的 API 文档说命令可以是字符串或字符串数组,但它只对我作为字符串数组有效。我使用了 nginx 命令行工具,但类似 'kill -SIGUSR1 $(cat /var/run/nginx.pid)
' 之类的东西也可能会起作用。
http:/v1.41/containers/hofg_nginx_1/exec \
我对容器名称进行了硬编码,如果您正在处理更复杂的事情,您可能也在使用更高级的日志服务
| jq -r '.Id'`
响应为 JSON 格式,我使用 jq 提取 ID(对不起,'Id')以供下一步使用。
curl -X POST --unix-socket /var/run/docker.sock \
-H "Content-Type: application/json" \
-d '{"Detach": true}' \
Detach: true 可能不是必需的,只是调试时方便的 POST 数据的占位符
http:/v1.41/exec/"$exec_id"/start
利用第一个 curl 返回的 exec 实例 ID 来实际运行命令。
我确信它会发展(比如错误处理),但这应该是一个很好的起点。