Dockerでデタッチして実行すると、Pythonアプリは何も印刷しません


160

私のdockerfileで開始されたPython(2.7)アプリがあります。

CMD ["python","main.py"]

main.pyは、起動時にいくつかの文字列を出力し、その後ループに入ります。

print "App started"
while True:
    time.sleep(1)

コンテナーを-itフラグで開始する限り、すべてが期待どおりに機能します。

$ docker run --name=myapp -it myappimage
> App started

そして、後でログを介して同じ出力を見ることができます:

$ docker logs myapp
> App started

-dフラグを使用して同じコンテナーを実行しようとすると、コンテナーは正常に起動するように見えますが、出力が表示されません。

$ docker run --name=myapp -d myappimage
> b82db1120fee5f92c80000f30f6bdc84e068bafa32738ab7adb47e641b19b4d1
$ docker logs myapp
$ (empty)

しかし、コンテナーはまだ実行されているようです。

$ docker ps
Container Status ...
myapp     up 4 minutes ... 

アタッチしても何も表示されません。

$ docker attach --sig-proxy=false myapp
(working, no output)

どんなアイデアがうまくいかないのですか?バックグラウンドで実行した場合、「印刷」の動作は異なりますか?

Dockerバージョン:

Client version: 1.5.0
Client API version: 1.17
Go version (client): go1.4.2
Git commit (client): a8a31ef
OS/Arch (client): linux/arm
Server version: 1.5.0
Server API version: 1.17
Go version (server): go1.4.2
Git commit (server): a8a31ef

回答:


266

最後に、GitHubの @ahmetalpbalkanのおかげで、Dockerでデーモン化されたときにPython出力を表示するソリューションを見つけました。さらに参照するためにここで自分で答えます:

でのバッファなし出力の使用

CMD ["python","-u","main.py"]

の代わりに

CMD ["python","main.py"]

問題を解決します。あなたはを介して出力(両方、stderrとstdout)を見ることができます

docker logs myapp

今!


2
-uは私にとってはうまくいくようですが、実際に何が行われるかを説明したドキュメントがどこかにありますか?
リトルオタク、

7
他の回答で示唆さENV PYTHONUNBUFFERED=0れているように、-uフラグが機能しない場合は、環境変数を設定してみてください。
Farshid T 2017

1
これも私の問題でした。詳細については、stackoverflow.com
Jonathan Stray

いくつかのよりおよそ-uこちら:stackoverflow.com/questions/107705/disable-output-buffering
カルダモン

1
PYTHONUNBUFFERED = 0を設定しても役に立たなかった一方で、python3での夢のように機能します。
レッヒミグダル2018

71

私の場合、Pythonを実行して-uも何も変わりませんでした。ただし、トリックはPYTHONUNBUFFERED=0環境変数として設定することでした。

docker run --name=myapp -e PYTHONUNBUFFERED=0 -d myappimage

6
私の場合、追加-e PYTHONUNBUFFERED=0すると役立ちます。
David Ng

1
ありがとうございました!私は何時間も頭を壁から叩いていたが、でもログを機能させることができなかった-u。あなたのソリューションは、Docker for MacでDjangoを使用して私のために修正しました
Someguy123

2
私はこれがより良い解決策だと思います、出力を見るために
Docker

2
これは大きな感謝です。これは、ドキュメントPYTHONUNBUFFERED
A Star

docker-composeインターフェースで動作しました。
想像もつか

24

私にとってそれはバグではなく機能です。疑似TTYがなければ、標準化するものは何もありません。したがって、簡単な解決策は、実行中のコンテナに疑似TTYを割り当てることです。

$ docker run -t ...

これは質問に対する答えを提供しません。批評したり、著者に説明を要求するには、投稿の下にコメントを残してください。
James K. Polk大統領、2015年

@JamesKPolk、それは今より良いですか?
Peter Senna、

dockerでは、stdoutとstderrに疑似ttyを割り当てる必要はありません
Matt

3
tty: true作曲地で
deepelement '20年

15

動作の詳細な理由を説明するこの記事を参照してください。

バッファリングには通常3つのモードがあります。

  • ファイル記述子がバッファリングされていない場合、バッファリングは一切発生せず、データの読み取りまたは書き込みを行う関数呼び出しがすぐに発生します(ブロックされます)。
  • ファイル記述子が完全にバッファリングされている場合、固定サイズのバッファが使用され、読み取りまたは書き込みの呼び出しは、単にバッファから読み取りまたは書き込みを行います。バッファは、いっぱいになるまでフラッシュされません。
  • ファイル記述子が行バッファリングされている場合、バッファリングは改行文字が見つかるまで待機します。したがって、データはバッファリングされ、\ nが表示されるまでバッファリングされます。その後、バッファリングされたすべてのデータがその時点でフラッシュされます。実際には、通常、バッファには最大サイズがあります(完全にバッファリングされた場合と同様)。このルールは、実際には、「改行文字が見つかるか、4096バイトのデータが検出されるまで、どちらか早い方のバッファ」のようなものです。

そして、GNU libc(glibc)は、バッファリングに以下のルールを使用します。

Stream               Type          Behavior
stdin                input         line-buffered
stdout (TTY)         output        line-buffered
stdout (not a TTY)   output        fully-buffered
stderr               output        unbuffered

したがって、docker document-tからを使用すると、疑似ttyが割り当てられ、になるため、1行の出力が表示されます。stdoutline-buffereddocker run --name=myapp -it myappimage

ちょうど使用している場合や、-d、何のttyが割り当てられていなかった、そして、stdoutあるfully-buffered1行App startedのバッファをフラッシュする確かにできません。

次に、使用-dtするmake stdout line bufferedか、追加-uのpythonでは、flush the bufferそれを修正する方法です。



6

に変更printすると、切り離されたイメージのログを表示できますlogging

main.py:

import time
import logging
print "App started"
logging.warning("Log app started")
while True:
    time.sleep(1)

Dockerfile:

FROM python:2.7-stretch
ADD . /app
WORKDIR /app
CMD ["python","main.py"]

1
いいね。ヒント:Python 3を使用してください
adhg

質問はPython 2(括弧なしのprintステートメント)にあるため、ここでは2を使用しています。Python3.6でもまったく同じ動作ですが、ヒントをありがとう;)
Hog

6

私はまだこの答えを見ていませんので:

印刷後にstdoutをフラッシュすることもできます。

import time

if __name__ == '__main__':
    while True:
        print('cleaner is up', flush=True)
        time.sleep(5)

1
これは私にとっては完全に機能しましたが、これが必要であるという愚かさはありましたが、今はうまく機能しています。
jamescampbell


3

簡単な修正として、これを試してください:

from __future__ import print_function
# some code
print("App started", file=sys.stderr)

これは、同じ問題が発生した場合に役立ちます。しかし、正直なところ、このエラーが発生する理由はわかりません。


先端をありがとう!すべてのプリントをお使いのバージョンで置き換えようとしましたが、残念ながら私には機能しませんでしたが、Dockerログから出力を取得できません(sys.stderr / sys.stdoutを変更しても、目に見える結果はありません)。これはドッカーのバグですか?
jpdus 2015

私の答えをください、その理由は:stderrがバッファーされていないので、ソリューションで修正することができます。
atline


0

通常、特定のファイルにリダイレクトします(ホストからボリュームをマウントして、そのファイルに書き込むことにより)。

-tを使用してttyを追加することもできます。あなたはそれをドッカーのログで拾う必要があります。

大量のログ出力を使用して、すべてをDockerログに入れずにバッファーを保存することには問題がありませんでした。


-1

使用docker-composeしておらず、通常のdocker場合はDockerfile、フラスコアプリをホストしているにこれを追加できます

ARG FLASK_ENV="production"
ENV FLASK_ENV="${FLASK_ENV}" \
    PYTHONUNBUFFERED="true"

CMD [ "flask", "run" ]
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.