将在 docker 容器中创建的日志文件重定向到 stdout / stderr

redirect log files created in a docker container to stdout / stderr

我有以下 Dockerfile:

FROM ubuntu:16.04
RUN apt-get update
VOLUME ["/LOGS"]
COPY ./testServer .
ENTRYPOINT ./testServer 8600

"testServer" 有正在写入的日志文件。它们位于目录 "LOGS" 中。每次启动 "testServer" 时,都会创建一个新日志。我想做的是 "tail" 目录中的最新日志文件到 stdout / stderr.

我尝试添加:

CMD ["/bin/sh", "-c", "tail $( ls -Art /LOGS | tail -n 1 ) > out_server.log 2>&1"]

添加到 Dockerfile(然后重建镜像),但它没有用。

如何做到这一点?

TIA

如果这是一个要求,我会重新配置 ubuntu 用于输出的系统日志。一个例子是 here

这里有两个问题。

  1. 您定义了一个 ENTRYPOINT,并且您正在尝试 运行 一个带有 CMD 的命令。 Docker 使用单个进程启动容器,当您同时定义这两个进程时,CMD 将作为附加的 cli args 附加到 ENTRYPOINT。作为 pid 1 的容器 运行ning 是什么:

    /bin/sh -c './testServer 8600 /bin/sh -c "tail $( ls -Art /LOGS | tail -n 1 ) > out_server.log 2>&1"'

    除非 testServer 运行 有额外的参数,否则它们永远不会被使用。

  2. 如果您 运行ning 的命令确实有效,它会将所有内容输出到容器内的 /out_server.log,而不是标准输出,它会尽快停止它到达了输入的末尾。如果那是你的 pid 1,容器也会在那个时候退出。

要解决此问题,您可以创建一个 entrypoint.sh 类似于:

#!/bin/sh

./testServer 8600 &
sleep 2 # give testServer time to create the newest log
exec tail -f $( ls -Art /LOGS | tail -n 1 )

该入口点在后台启动 testServer,然后 运行 使用 exec 执行尾部。 exec 替换 pid 1 以便信号通过。

将您的 Docker 文件更新为:

FROM ubuntu:16.04

# This apt-get line shouldn't be needed unless something else 
# needs the possibly outdated package repo list
# RUN apt-get update

# Removing this volume, you can create it from a docker-compose.yml
# VOLUME ["/LOGS"]

COPY entrypoint.sh testServer /
RUN chmod 755 /entrypoint.sh /testServer
ENTRYPOINT [ "/entrypoint.sh" ]

有关我删除 VOLUME 行的原因的更多详细信息,请参阅 my blog post here

您可以将日志文件符号链接到容器进程的标准输出,而不是使用 tail。为此,您需要将可执行文件包装在一个单独的脚本中,以便它作为一个独立于容器主进程的进程启动。

要执行的脚本:

#!/bin/bash

# The application log will be redirected to the main docker container process's stdout, so # that it will show up in the container logs
touch /my/app/application.log
ln -sf /proc/1/fd/1 /my/app/application.log

# Execute my app
./testServer 8600

然后在 docker 文件中复制并执行脚本

COPY start_server.sh /the/above/script/start_server.sh
CMD ["/bin/bash", "/the/above/script/start_server.sh"]

我发现以下内容很有用。

#forward request and error logs to docker log collector
RUN ln -sf /dev/stdout /var/log/nginx/access.log \
    && ln -sf /dev/stderr /var/log/nginx/error.log

作为上述行的结果,写入access.logerror.log的内容将分别写入stdoutstderr

Source