使用logrotate进行容器化的nginx日志旋转

时间:2017-05-02 19:33:07

标签: nginx logging docker logrotate

Nginx没有本机日志轮换,因此需要外部工具,例如logrotate。 Nginx提出了一个挑战,即日志必须在轮换后重新打开。如果pid在/ var / run中可用,您可以向其发送USR1信号。

但是当在docker容器中运行时,/ var / run中缺少pid文件(并且pid实际上属于主机,因为它在技术上是一个主机进程)。

如果您不重新打开日志,nginx根本不会记录任何内容,但它会继续作为Web服务器,反向代理等运行。

2 个答案:

答案 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 等,以便它们在轮换后创建并记录到新的日志文件。

总结:

  • 将所有日志放在一个共享卷上
  • 将 docker socket 导出到 logrotate 容器
  • 使用 logrotate、cron、curl 和 jq 构建 logrotate 图像
  • 使用 docker exec API 使用 postrotate 调用构建 logrotate.conf,详情如下
  • 在容器中使用 cron 调度 logrotate

难点:

为了让 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 来实际运行命令。

我确信它会发展(比如错误处理),但这应该是一个很好的起点。