【问题标题】:Redirecting command output in docker在docker中重定向命令输出
【发布时间】:2016-04-10 12:48:19
【问题描述】:

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

这里是 Dockerfile

# 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 重定向到一个文件。现在我在其中运行这个容器和外壳

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 重定向到文件?

【问题讨论】:

    标签: linux bash logging docker output


    【解决方案1】:

    当您在 Dockerfile 中将 JSON 列表指定为 CMD 时,它将不会在 shell 中执行,因此通常的 shell 函数(如 stdout 和 stderr 重定向)将不起作用。

    来自documentation

    exec 表单被解析为 JSON 数组,这意味着您必须在单词周围使用双引号 (") 而不是单引号 (')。

    与 shell 形式不同,exec 形式不调用命令 shell。这意味着不会发生正常的外壳处理。例如,CMD [ "echo", "$HOME" ] 不会对 $HOME 进行变量替换。如果你想要 shell 处理,那么要么使用 shell 形式,要么直接执行 shell,例如:CMD [ "sh", "-c", "echo", "$HOME" ]

    您的命令实际上是执行您的index.py 脚本并将字符串"1>server.log""2>server.log" 作为命令行参数传递给该python 脚本

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

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

    【讨论】:

    • documentation 建议使用内置的exec shell,以使容器尊重操作系统信号和docker stop。所以第一个命令变成:CMD exec python index.py > server.log 2>&1
    【解决方案2】:

    要在 shell 管道或 shell 重定向下使用 docker run,使 run 接受标准输入并适当地输出到标准输出和标准错误,请使用以下咒语:

    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
    

    【讨论】:

    • -d 和 -a 不能一起使用
    【解决方案3】:

    只是一个补充,在使用docker-compose的时候,你也可以试试:

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

    【讨论】:

    • 你试过了吗?这对我来说很有意义,但不起作用!到目前为止,在使用 docker-compose command 指令时,我完全没有成功将 stderr 重定向到 stdout。标准输出很好。
    • 啊,我的问题原来是我需要设置PYTHONUNBUFFERED 环境变量或使用-u 标志运行python,如下所示:stackoverflow.com/a/24183941/562883
    • 我必须将我的 postgres 容器的 pg_dump 放到主机上的一个文件中。这是我所做的:docker run -ti -v /usr/local/jay/words_data:/mnt/data --rm --link mypostgres:pghost postgres bash -c "pg_dump -h pghost -U app_user myschema >> /mnt/data/export.sql"(旁注:我本可以将更简单的选项 -f 与 pg_dump 一起使用,但当时我没有想到。无论如何,这个答案对我有帮助。)
    【解决方案4】:

    我个人使用:

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

    “-u”是关键:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-05-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-04-07
      • 1970-01-01
      相关资源
      最近更新 更多