Edited at

DockerコンテナでFlaskを起動し, JSONデータのPOSTとGET

More than 1 year has passed since last update.


仕様

ターミナルからcurlコマンドでjsonデータを送ると,

文字列が成型されて, 同じくjson形式でデータが返ってくる.


環境

Mac OS X 10.12

Docker for Mac 17.03

多分Linuxでも同様にできます.



1. Flask起動スクリプトの用意

Pythonの軽量WebフレームワークであるFlaskをつかって作成します.

@app.route()で指定されたディレクトリにアクセスすると,

defで定義したメソッドが起動し, returnで結果を返す, という流れです.


reply.py

from flask import Flask, jsonify, request

import json
app = Flask(__name__)

@app.route("/", methods=['GET'])
def hello():
return "Hello World!"

@app.route('/reply', methods=['POST'])
def reply():
data = json.loads(request.data)
answer = "Yes, it is %s!\n" % data["keyword"]
result = {
"Content-Type": "application/json",
"Answer":{"Text": answer}
}
# return answer
return jsonify(result)

if __name__ == "__main__":
app.run(host='0.0.0.0',port=5000,debug=True)


Flaskは, デフォルトではlocalhostからの要求しか受けませんが,

app.runメソッドでhost='0.0.0.0'を渡すと, 全てのアドレスからの要求を受け付けます.

外部公開するときなどは, この設定を行います.

アプリのルートディレクトリ(reply.pyの置いてあるディレクトリ)で

GET要求を受けると, hello()メソッドが実行され, "Hello World!"を返します.

また, /reply ディレクトリでPOST要求を受けjsonデータを受けとると,

reply()メソッドが起動して, データを編集して返します.


2. DockerImageの用意

FlaskをDockerコンテナで動かすために, Pythonの公式イメージを利用します.

DockerFileは以下の通り.


Dockerfile

FROM python:3.6

ARG project_dir=/app/

# ADD requirements.txt $project_dir
ADD reply.py $project_dir

WORKDIR $project_dir

RUN pip install flask
# RUN pip install -r requirements.txt

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


追加で必要なモジュールがあれば, requirements.txtに記述し, ADDで追加します.

最終行のCMDにより, コンテナ起動と同時にアプリが立ち上がるように指定しています.

Dockerfileを用意したら, reply.pyと同じディレクトリに置き, 次のコマンドでビルドします.

# docker build -t flask_docker .

末尾の"."はタイプミスではなく, カレントディレクトリのDockerfileを参照するという合図です.(定番)


3. コンテナの起動

先ほど作成したImageファイル"flask_docker"を元に, コンテナを起動します.

# docker run -p 5000:5000 -it flask_docker

コンテナ内部ではflaskが使用する5000番ポートを解放し, さらにホストマシンの5000番ポートからアクセスできるよう宣言しています.

今回は, コンテナ起動と同時にflaskが起動するように設定しましたが, コンテナの中に入って作業をしたい場合は,

# docker run -p 5000:5000 -it flask_docker /bin/bash

とすれば, Dockerfile最終行のCMDが実行される代わりにbashが起動し, コンテナ内に入ることができます.


4. 動作確認

まずは,ブラウザから"localhost:5000"にアクセスします.

するとhello()メソッドが実行され, "Hello, World!"とブラウザに表示されます.

次に, いよいよJSON形式のデータをPOSTしてみます.

$ curl http://localhost:5000/reply -X POST -H "Content-Type: application/json" -d '{"keyword": "Keffia"}'

読みづらいですが, 以下のような結果が返ってきます.

{

"Answer": {
"Text": "Yes, it is Keffia!"
},
"Content-Type": "application/json"
}

今回はjsonで返しましたが, テキストで返したいときは,

reply()の返り値を"return answer"とすれば良いです.

以上です.