Docker:如何正确清除Docker容器的日志?

我使用docker logs [container-name]来查看特定容器的日志。

有什么优雅的方法来清除这些日志吗?

545395 次浏览

首先是糟糕的答案。在这个问题中有一个你可以运行的一行程序:

echo "" > $(docker inspect --format='\{\{.LogPath}}' <container_name_or_id>)

代替echo的是更简单的:

: > $(docker inspect --format='\{\{.LogPath}}' <container_name_or_id>)

或者还有truncate命令:

truncate -s 0 $(docker inspect --format='\{\{.LogPath}}' <container_name_or_id>)

我对这两种都不太喜欢,因为它们直接修改Docker的文件。外部日志删除可能发生在docker将json格式的数据写入文件时,导致部分行,并破坏从docker logs cli读取任何日志的能力。有关这种情况的例子,请参见以下是对duketwo回答的评论:

清空日志文件后,我得到这个错误:error from daemon in stream: Error grabbing logs: invalid character '\x00' looking for beginning of value

相反,您可以让Docker自动旋转日志。如果你使用默认的JSON日志驱动程序,这是通过dockerd的附加标志来完成的:

dockerd ... --log-opt max-size=10m --log-opt max-file=3

你也可以将它设置为你的daemon.json文件的一部分,而不是修改你的启动脚本:

{
"log-driver": "json-file",
"log-opts": {"max-size": "10m", "max-file": "3"}
}

这些选项需要配置为具有root访问权限。确保在更改此文件后运行systemctl reload docker以应用设置。这个设置将是所有新创建的容器的默认设置。注意,需要删除并重新创建现有容器以接收新的日志限制。


可以将类似的日志选项传递给各个容器以覆盖这些默认值,从而允许您在各个容器上保存更多或更少的日志。从docker run来看,如下所示:

docker run --log-driver json-file --log-opt max-size=10m --log-opt max-file=3 ...

或者在一个合成文件中:

version: '3.7'
services:
app:
image: ...
logging:
options:
max-size: "10m"
max-file: "3"

为了节省额外的空间,你可以从json日志驱动切换到&;local&;日志的司机。它采用相同的max-size和max-file选项,但它使用更快更小的二进制语法,而不是存储在json中。这允许您在相同大小的文件中存储更多的日志。这个守护进程。Json条目看起来像这样:

{
"log-driver": "local",
"log-opts": {"max-size": "10m", "max-file": "3"}
}

本地驱动程序的缺点是依赖于直接访问json日志的外部日志解析器/转发器将不再工作。因此,如果你使用filebeat之类的工具向Elastic或Splunk的通用转发器发送信息,我会避免使用“;司机。

我在我的窍门和技巧演示中有更多关于这一点的内容。

你不能通过Docker命令直接做到这一点。

您可以限制日志的大小,或者使用脚本删除与容器相关的日志。你可以在这里找到脚本示例(从底部阅读):功能:能够清除日志历史#1083

查看docker-compose文件引用的日志部分,在那里你可以为一些日志驱动程序指定选项(比如日志旋转和日志大小限制)。

使用:

truncate -s 0 /var/lib/docker/containers/**/*-json.log

你可能需要sudo

sudo sh -c "truncate -s 0 /var/lib/docker/containers/**/*-json.log"

参考。杰夫S. Docker:如何正确清除Docker容器的日志?

参考:当文件's被使用时截断它(Linux)

通过设置日志清除功能,可以定期清除日志。

“/etc/logrotate.d/docker-logs”文件示例

/var/lib/docker/containers/*/*.log {
rotate 7
daily
compress
size=50M
missingok
delaycompress
copytruncate
}
sudo sh -c "truncate -s 0 /var/lib/docker/containers/*/*-json.log"

Docker为Mac用户,这里是解决方案:

    <李> < ol >
  • 查找日志文件路径

    $ docker inspect | grep log < / p >

  • 李< / ol > < / > <李> < ol开始= " 2 " >
  • SSH进入docker机器(假设名称为default,如果不是,运行docker-machine ls来查找):

    $ docker-machine ssh default < / p >

  • 李< / ol > < / > <李> < ol开始= " 3 " >
  • 修改为root用户(参考):

    $ sudo -i < / p >

  • 李< / ol > < / > <李> < ol开始= " 4 " >
  • 删除日志文件内容:

    $ echo "" > log_file_path_from_step1 < / p >

  • 李< / ol > < / >

作为用户,尝试运行以下命令:

>  /var/lib/docker/containers/*/*-json.log

cat /dev/null > /var/lib/docker/containers/*/*-json.log

echo "" > /var/lib/docker/containers/*/*-json.log

Docker4Mac, 2018年解决方案:

LOGPATH=$(docker inspect --format='\{\{.LogPath}}' <container_name_or_id>)
docker run -it --rm --privileged --pid=host alpine:latest nsenter -t 1 -m -u -n -i -- truncate -s0 $LOGPATH

第一行获取日志文件路径,类似于接受的答案。

第二行使用nsenter,它允许你在xhyve虚拟机中运行命令,该虚拟机作为Docker4Mac下所有docker容器的主机。我们运行的命令是非mac答案中熟悉的truncate -s0 $LOGPATH

如果你使用docker-compose,第一行变成:

local LOGPATH=$(docker inspect --format='\{\{.LogPath}}' $(docker-compose ps -q <service>))

<service>是你的docker-compose.yml文件中的服务名。

感谢https://github.com/justincormack/nsenter1nsenter技巧。

在Docker for Windows和Mac上,也可能在其他平台上,可以使用tail选项。例如:

docker logs -f --tail 100

这样,只显示最后100行,你不需要首先滚动1M行……

(因此,删除日志可能是不必要的)

在我的Ubuntu服务器上,即使是sudo,我也会得到Cannot open ‘/var/lib/docker/containers/*/*-json.log’ for writing: No such file or directory

但是结合docker检查和截断答案是有效的:

sudo truncate -s 0 `docker inspect --format='\{\{.LogPath}}' <container>`

我更喜欢这个(从上面的解决方案):

truncate -s 0 /var/lib/docker/containers/*/*-json.log

然而,我正在运行几个系统(Ubuntu 18。x Bionic为例),该路径不能正常工作。Docker是通过Snap安装的,所以到容器的路径更像:

truncate -s 0 /var/snap/docker/common/var-lib-docker/containers/*/*-json.log

你也可以在docker run命令行上提供log-opts参数,如下所示:

docker run --log-opt max-size=10m --log-opt max-file=5 my-app:latest

或者是码头式的。Yml是这样的

my-app:
image: my-app:latest
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"

credit: https://medium.com/@Quigley_Ja/ roting-docker -logs- keeping-your-overlay-folader -small-40cfa2155412 (James Quigley)

不确定这是否对您有帮助,但删除容器总是有帮助的。

因此,如果你使用docker-compose进行设置,你可以简单地使用docker-compose down && docker-compose up -d而不是docker-compose restart。通过适当的设置(确保对持久数据使用卷挂载),您不会以这种方式丢失任何数据。

当然,这比任务要求的要多。但是在各种情况下,其他答案都不起作用(如果使用远程docker服务器或在Windows机器上工作,访问底层文件系统是私有的,而且很困难)

我需要一些可以作为一个命令运行的东西,而不是必须编写docker ps并复制每个容器ID并多次运行该命令。我已经改编了BMitch的回答,我想我会分享,以防其他人发现这个有用。

混合xargs似乎实现了我在这里需要的:

docker ps --format='\{\{.ID}}' | \
xargs -I {} sh -c 'echo > $(docker inspect --format="\{\{.LogPath}}" {})'

这将获取由docker ps (会删除列表上所有容器的日志!)列出的每个容器ID,将其管道到xargs中,然后回显一个空白字符串来替换容器的日志路径。

下面是一个清除docker容器日志的跨平台解决方案:

docker run --rm -v /var/lib/docker:/var/lib/docker alpine sh -c "echo '' > $(docker inspect --format='\{\{.LogPath}}' CONTAINER_NAME)"

将此粘贴到您的终端,并将CONTAINER_NAME更改为所需的容器名称或id。

要移除/清除docker容器日志,我们可以使用下面的命令

$(docker inspect container_id|grep " logpath;|cut -d "f4) 或 $(docker inspect container_name|grep "LogPath"|cut -d "f4) < / p >

这将删除所有容器的日志文件:

sudo find /var/lib/docker/containers/ -type f -name "*.log" -delete

Ubuntu Linux /:

如果您有多个容器,而您只想删除一个日志,而不想删除其他日志。

  • (如果您遇到“许可被拒绝”等问题;sudo su)
  • 列出所有容器:docker ps -a
  • 寻找你想要的容器并复制CONTAINER ID。例子:E1X2A3M4P5L6
  • 容器、文件夹和真实名称比E1X2A3M4P5L6长,但前12个字符是由docker ps -a生成的。
  • 删除日志: > /var/lib/docker/containers/E1X2A3M4P5L6*/E1X2A3M4P5L6*-json.log(替换E1X2A3M4P5L6为你的结果!!)李< / >

正如你所看到的,在/containers里面是容器,logs有相同的名称,但在结尾有-json.log。你只需要知道前12个字符,因为*意味着“任何东西”。

感谢回复@BMitch,我刚刚写了一个shell脚本来清理所有容器的日志:

#!/bin/bash
ids=$(docker ps -a --format='\{\{.ID}}')
for id in $ids
do
echo $(docker ps -a --format='\{\{.ID}} ### \{\{.Names}} ### \{\{.Image}}' | fgrep $id)
truncate -s 0 $(docker inspect --format='\{\{.LogPath}}' $id)
ls -llh $(docker inspect --format='\{\{.LogPath}}' $id)
done

如果你需要在删除之前存储日志文件的备份,我已经为指定的容器创建了一个执行以下操作的脚本(你必须使用sudo运行它):

  1. 创建一个文件夹以存储作为备份的压缩日志文件。
  2. 查找正在运行的容器的id(由容器名指定)。
  3. 使用随机名称将容器的日志文件复制到一个新位置(步骤1中的文件夹)。
  4. 压缩之前的日志文件(以节省空间)。
  5. 按您可以定义的特定大小截断容器的日志文件。

注:

  • 它使用shuf命令。确保您的linux发行版拥有它,或者将其更改为另一个bash支持的随机生成器。
  • 在使用之前,更改变量CONTAINER_NAME以匹配正在运行的容器;它可以是一个部分名称(不必是完全匹配的名称)。
  • 默认情况下,它将日志文件截断为10M(10兆字节),但你可以通过修改变量SIZE_TO_TRUNCATE来改变这个大小。
  • 它在路径:/ opt / your-container-name /日志中创建了一个文件夹,如果你想将压缩日志存储在其他地方,只需更改变量LOG_FOLDER
  • 在生产环境中运行之前运行一些测试。
#!/bin/bash
set -ex


############################# Main Variables Definition:
CONTAINER_NAME="your-container-name"
SIZE_TO_TRUNCATE="10M"


############################# Other Variables Definition:
CURRENT_DATE=$(date "+%d-%b-%Y-%H-%M-%S")
RANDOM_VALUE=$(shuf -i 1-1000000 -n 1)
LOG_FOLDER="/opt/${CONTAINER_NAME}/logs"
CN=$(docker ps --no-trunc -f name=${CONTAINER_NAME} | awk '{print $1}' | tail -n +2)
LOG_DOCKER_FILE="$(docker inspect --format='\{\{.LogPath}}' ${CN})"
LOG_FILE_NAME="${CURRENT_DATE}-${RANDOM_VALUE}"


############################# Procedure:
mkdir -p "${LOG_FOLDER}"
cp ${LOG_DOCKER_FILE} "${LOG_FOLDER}/${LOG_FILE_NAME}.log"
cd ${LOG_FOLDER}
tar -cvzf "${LOG_FILE_NAME}.tar.gz" "${LOG_FILE_NAME}.log"
rm -rf "${LOG_FILE_NAME}.log"
truncate -s ${SIZE_TO_TRUNCATE} ${LOG_DOCKER_FILE}

您可以创建一个cronjob来每月运行前面的脚本。第一次运行:

sudo crontab -e

在键盘上输入一个进入编辑模式。然后添加如下一行:

0 0 1 * * /your-script-path/script.sh

逃避键退出编辑模式。通过输入: wq并按回车键保存文件。确保script.sh文件具有执行权限。

< p > docker system prune < br > 在命令提示符

下执行此命令