我有以下Dockerfile:
FROM ubuntu:16.04
RUN apt-get update
VOLUME ["/LOGS"]
COPY ./testServer .
ENTRYPOINT ./testServer 8600
"testServer"具有正在写入的日志文件。它们位于目录"LOGS"中。每次启动"testServer"时,都会创建一个新日志。我想做的是将目录中的最新日志文件"尾部"到 stdout/stderr。
我尝试添加:
CMD ["/bin/sh", "-c", "tail $( ls -Art /LOGS | tail -n 1 ) > out_server.log 2>&1"]
到 Dockerfile(并随后重建映像),但它不起作用。
如何做到这一点?
蒂亚
相反,您可以使用 tail,您可以将日志文件符号链接到容器进程的 stdout。为此,您需要将可执行文件包装在单独的脚本中,以便它作为独立于容器主进程的进程启动。
要执行的脚本:
#!/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"]
这里有两个问题。
-
您定义了
ENTRYPOINT
,并且正在尝试使用CMD
运行命令。Docker 使用单个进程启动容器,当您定义这两个进程时,CMD
将作为附加 cli 参数附加到ENTRYPOINT
。容器作为 pid 1 运行的是:/bin/sh -c './testServer 8600 /bin/sh -c "tail $( ls -Art /LOGS | tail -n 1 ) > out_server.log 2>&1"'
除非testServer运行额外的args,否则它们永远不会被使用。
-
如果您正在运行的命令确实有效,它将所有内容输出到容器内的/out_server.log,而不是 stdout,并且一旦到达输入末尾就会停止。如果这是您的 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,以便通过信号。
将您的 Dockerfile 更新为:
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
行的原因的更多详细信息,请参阅此处的博客文章。
我发现以下内容很有用。
#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
。
源
如果这是一个要求,我会重新配置 ubuntu 用于输出的系统日志。一个例子在这里