2020年11月16日月曜日

flask + python の print が docker logs で表示されない場合の対処方法

概要

どうやら python の print はデフォルトだとバッファリングしているようで、そのままだと docker logs の標準出力に出ないようです
簡単な対象方法を紹介します

環境

  • macOS 10.15.7
  • Python 3.8.5
  • docker 19.03.13

アプリ作成

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    print('hello')
    return 'Hello'

ターミナル上で確認

  • FLASK_APP=app.py pipenv run flask run
  • curl localhost:5000

=> hello が表示される

Dockerfile

FROM python:3.8-buster

ADD . /app
WORKDIR /app

RUN pip install pipenv
RUN pipenv install
ENV FLASK_APP app.py

EXPOSE 5000

CMD ["pipenv", "run", "flask", "run", "--host", "0.0.0.0"]

docker 上で確認

  • docker build -t test_app .
  • docker run -p 5000:5000 --name test_app test_app
  • docker logs test_app

=> 表示されない

対処方法1: flush=True

print 時に flush=True を指定します

from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    print('hello', flush=True)
    return 'Hello'

対象方法2: PYTHONUNBUFFERED を指定する

すべての print に flush=True を入れるのは大変なので PYTHONUNBUFFERED で制御します

  • docker run -e PYTHONUNBUFFERED=1 --name test_app -p 5000:5000 test_app

もしくは Dockerfile を書き換えても OK です

FROM python:3.8-buster

ADD . /app
WORKDIR /app

RUN pip install pipenv
RUN pipenv install
ENV FLASK_APP app.py
ENV PYTHONUNBUFFERED 1

EXPOSE 5000

CMD ["pipenv", "run", "flask", "run", "--host", "0.0.0.0"]

app.logger の場合は

特に何もせずに docker logs に出力されました
素直に app.logger を使い回すのが docker との相性は良さそうです

import logging
from flask import Flask

app = Flask(__name__)

@app.route('/')
def hello():
    app.logger.setLevel(logging.INFO)
    app.logger.info('hello')
    return 'Hello'

最後に

flask で print を使った際にバッファリングさせない方法を紹介しました
python の print はデフォルトだとバッファリングするので flask には関係なく今回の現象は発生すると思います

flask を使っている場合は素直に app.logger を使うことをおすすめします

参考サイト

0 件のコメント:

コメントを投稿