Logrotate - nginx 日志不在 docker 容器内旋转

问题描述 投票:0回答:4

我有一个运行 nginx 的 docker 容器,它正在将日志写入

/var/log/nginx
Logrotate 安装在 docker 容器中,并且 nginx 的 logrotate 配置文件已正确设置。尽管如此,logrotate 仍不会自动旋转日志。通过
logrotate -f /path/to/conf-file
手动强制日志旋转以按预期旋转日志。

我的结论是,有些东西没有触发 cron ,但我找不到原因。

这是运行 nginx 的 docker 容器的 Dockerfile

FROM nginx:1.11

# Remove sym links from nginx image
RUN rm /var/log/nginx/access.log
RUN rm /var/log/nginx/error.log

# Install logrotate
RUN apt-get update && apt-get -y install logrotate

# Copy MyApp nginx config
COPY config/nginx.conf /etc/nginx/nginx.conf

#Copy logrotate nginx configuration
COPY config/logrotate.d/nginx /etc/logrotate.d/

还有 docker-compose 文件:

version: '2'
services:
  nginx:
    build: ./build
    restart: always
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./auth:/etc/nginx/auth
      - ./certs:/etc/nginx/certs
      - ./conf:/etc/nginx/conf
      - ./sites-enabled:/etc/nginx/sites-enabled
      - ./web:/etc/nginx/web
      - nginx_logs:/var/log/nginx
    logging:
      driver: "json-file"
      options:
        max-size: "100m"
        max-file: "1"

volumes:
  nginx_logs:

networks:
  default:
    external:
      name: my-network

以下内容:/etc/logrotate.d/nginx

/var/log/nginx/*.log {
        daily
        dateext
        missingok
        rotate 30
        compress
        delaycompress
        notifempty
        create 0640 www-data adm
        sharedscripts
        prerotate
                if [ -d /etc/logrotate.d/httpd-prerotate ]; then \
                        run-parts /etc/logrotate.d/httpd-prerotate; \
                fi \
        endscript
        postrotate
                [ -s /run/nginx.pid ] && kill -USR1 `cat /run/nginx.pid`
        endscript
}

/etc/cron.daily/logrotate的内容

#!/bin/sh

test -x /usr/sbin/logrotate || exit 0
/usr/sbin/logrotate /etc/logrotate.conf

/etc/logrotate.conf的内容

# see "man logrotate" for details
# rotate log files weekly
weekly

# keep 4 weeks worth of backlogs
rotate 4

# create new (empty) log files after rotating old ones
create

# uncomment this if you want your log files compressed
#compress

# packages drop log rotation information into this directory
include /etc/logrotate.d

# no packages own wtmp, or btmp -- we'll rotate them here
/var/log/wtmp {
    missingok
    monthly
    create 0664 root utmp
    rotate 1
}

/var/log/btmp {
    missingok
    monthly
    create 0660 root utmp
    rotate 1
}

# system-specific logs may be configured here

有人可以指出我为什么 nginx 日志没有被 logrotate 自动轮转的正确方向吗?

编辑

我可以追溯到这个问题的根本原因是 cron 服务没有在容器上运行。一个可能的解决方案是想办法让容器同时运行 nginx 和 cron 服务。

docker nginx docker-compose dockerfile logrotate
4个回答
21
投票

正如我问题的编辑所述,问题是来自

CMD
nginx:1.11
仅开始
nginx
过程。解决方法是将以下命令放在我的 Dockerfile 上

CMD service cron start && nginx -g 'daemon off;'

这将在

nginx:1.11
启动 nginx 时启动 nginx,并启动 cron 服务。

Dockerfile 看起来像这样:

FROM nginx:1.11

# Remove sym links from nginx image
RUN rm /var/log/nginx/access.log
RUN rm /var/log/nginx/error.log

# Install logrotate
RUN apt-get update && apt-get -y install logrotate

# Copy MyApp nginx config
COPY config/nginx.conf /etc/nginx/nginx.conf

#Copy logrotate nginx configuration
COPY config/logrotate.d/nginx /etc/logrotate.d/

# Start nginx and cron as a service
CMD service cron start && nginx -g 'daemon off;'

16
投票

我从这个链接找到了一个方法,其核心思想是在外面使用

logrotate
,conf如下:

$ sudo vi /etc/logrotate.d/test
/home/test/logs/*log {
    rotate 90
    missingok
    ifempty
    sharedscripts
    compress
    postrotate
        /usr/bin/docker exec nginx-test /bin/sh -c '/usr/sbin/nginx -s reopen > /dev/null 2>/dev/null'
    endscript
}

0
投票

我的答案接近@touchstone,但我想添加一个连贯的答案和一些解释,因为在没有这些知识的情况下调试问题将花费很多时间。

因此,此配置将起作用:

$ sudo vi /etc/logrotate.d/test
/home/test/logs/*log {
    rotate 90
    missingok
    ifempty
    sharedscripts
    compress
    postrotate
        /usr/bin/docker exec nginx bash -c 'kill -USR1 $(cat /var/run/nginx.pid)'
    endscript
}

您需要注意的事项:

  • 所有路径始终使用绝对路径。这适用于脚本、可执行文件和脚本内的路径等。
    • bash
      不需要绝对路径,因为这是引用 docker 容器内而不是主机上的
      bash
      命令。
  • 请勿将
    -it
    参数用于
    docker exec

如果上述任何一点错误,您可以体验到手动运行

logrotate
(
sudo logrotate --force /etc/logrotate.d/nginx
) 将通过并按预期工作。然而,cron 任务将会默默地失败。具体来说,您将看到日志文件已轮换,但未压缩。 NGINX 也不会写入日志文件。 由于
logrotate
默认情况下在运行 cron 任务时不会记录自己的操作,因此您无法查看问题所在。

  • 命令
    docker exec nginx bash -c 'kill -USR1 $(cat /var/run/nginx.pid)'
    基于官方NGINX文档。 NGINX 需要 USR1 信号来指示日志文件已轮转并且应该再次开始写入日志文件。此外,您还需要进程的 PID,可以在
    /var/run/nginx.pid
    中找到。

我希望这对某人有用,因为我使用绝对路径并使用

-it
参数来实现
docker exec
,并且在手动运行
logrotate
时有效,但不是自动运行。


-4
投票
docker exec --user root `docker container ls --filter "name=nginx" --format "{{.Names}}"` nginx -s reopen
© www.soinside.com 2019 - 2024. All rights reserved.