重定向 docker 中的命令输出

Redirecting command output in docker

我想为我的服务器做一些简单的日志记录,这是一个小型 Flask 应用 运行在 Docker 容器中。

这是Docker文件

# Dockerfile
FROM dreen/flask
MAINTAINER dreen
WORKDIR /srv

# Get source
RUN mkdir -p /srv
COPY perfektimprezy.tar.gz /srv/perfektimprezy.tar.gz
RUN tar x -f perfektimprezy.tar.gz
RUN rm perfektimprezy.tar.gz

# Run server
EXPOSE 80
CMD ["python", "index.py", "1>server.log", "2>server.log"]

正如您在最后一行看到的,我将 stderr 和 stdout 重定向到一个文件。现在我 运行 这个容器 shell 放进去

docker run -d -p 80:80 perfektimprezy
docker exec -it "... id of container ..." bash

并观察以下事项:

服务器运行正在运行,网站正在运行

没有/srv/server.log

ps aux | grep python 产量:

root         1  1.6  3.2  54172 16240 ?        Ss   13:43   0:00 python index.py 1>server.log 2>server.log
root        12  1.9  3.3 130388 16740 ?        Sl   13:43   0:00 /usr/bin/python index.py 1>server.log 2>server.log
root        32  0.0  0.0   8860   388 ?        R+   13:43   0:00 grep --color=auto python

但是没有日志...但是,如果我 docker attach 到容器,我可以在控制台中看到应用生成输出。

如何在使用 Docker 时正确地将 stdout/err 重定向到文件?

当你在Dockerfile中指定一个JSON列表为CMD时,它不会在shell中执行,所以通常的shell stdout 和 stderr 重定向等功能将不起作用。

来自documentation:

The exec form is parsed as a JSON array, which means that you must use double-quotes (") around words not single-quotes (').

Unlike the shell form, the exec form does not invoke a command shell. This means that normal shell processing does not happen. For example, CMD [ "echo", "$HOME" ] will not do variable substitution on $HOME. If you want shell processing then either use the shell form or execute a shell directly, for example: CMD [ "sh", "-c", "echo", "$HOME" ].

你的命令实际上做的是执行你的index.py脚本并将字符串"1>server.log""2>server.log"作为command-line参数传递给那个python脚本.

改用以下方法之一(两者都应该有效):

  1. CMD "python index.py > server.log 2>&1"
  2. CMD ["/bin/sh", "-c", "python index.py > server.log 2>&1"]

补充一下,在使用docker-compose时,你也可以试试:

command: bash -c "script_or_command > /path/to/log/command.log 2>&1"

要在 shell 管道或 shell 重定向下使用 docker run,使 run 接受 stdin 并适当地输出到 stdout 和 stderr,请使用此咒语:

docker run -i --log-driver=none -a stdin -a stdout -a stderr ...

例如运行 alpine 映像并在包含的环境中执行 UNIX 命令 cat:

echo "This was piped into docker" |
  docker run -i --log-driver=none -a stdin -a stdout -a stderr \
    alpine cat - |
  xargs echo This is coming out of docker: 

发出:

This is coming out of docker: This was piped into docker

我个人使用:

ENTRYPOINT ["python3"]
CMD ["-u", "-m", "swagger_server"]

“-u”是关键:)