web-dev-qa-db-ja.com

dockerでのコマンド出力のリダイレクト

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

そして、次のことを守ってください。

サーバーが稼働しており、Webサイトが機能している

/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をファイルに適切にリダイレクトするにはどうすればよいですか?

44
Dreen

JSONリストをCMDDockerfileとして指定すると、シェルで実行されないため、stdoutやstderrリダイレクトなどの通常のシェル関数は機能しません。

ドキュメント から:

ExecフォームはJSON配列として解析されます。つまり、単一引用符(")ではなく、単語の周りに二重引用符(')を使用する必要があります。

シェルフォームとは異なり、execフォームはコマンドシェルを呼び出しません。これは、通常のシェル処理が行われないことを意味します。たとえば、CMD [ "echo", "$HOME" ]$HOMEの変数置換を行いません。シェル処理が必要な場合は、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"]
44
helmbert

docker-composeを使用する場合の補足として、次のようにすることもできます。

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

8
Jing Li

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
7