将在 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
这里有两个问题。
您定义了一个 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 运行 有额外的参数,否则它们永远不会被使用。
如果您 运行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.log
和error.log
的内容将分别写入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
这里有两个问题。
您定义了一个
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 运行 有额外的参数,否则它们永远不会被使用。
如果您 运行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.log
和error.log
的内容将分别写入stdout
和stderr
。