Python
responder
SENSYDay 11

responder on dockerしようとしたら、hello worldできなくて焦った話

pythonのフレームワーク経験があまりないので、せっかくだからモダンフレームワークから覚えてイケエンジニアになろうと思ってたら甘くはなかった....:sob:

結論から言うと、dockerでapi.runする際はapi.run(address="0.0.0.0")という話です。

理由が分かったひとは解散。


responderって...?

以下の記事を読むと楽しいです。

https://blog.ikedaosushi.com/entry/2018/12/01/195512


hello worldしようとするとserverからreplyが返らない。

すでにresponder先駆者の日本語記事があったので、以下の参考に実装させて頂いておりました。感謝:bow_tone1:

https://qiita.com/nskydiving/items/b98d5cea5a52459cb183


事象

しかし、dockerに載せると......replyを返してくれないだと....

curl http://127.0.0.1:5042/

curl: (52) Empty reply from server

原因を切り分けるためにコンテナに入って叩いてみると、ちゃんと返してくれる。なんぞ??

$ docker exec -it python_application bash                                                                                                                                         

root@6e256b0bdfc6:/usr/src/app# curl localhost:5042
hello, world!


解決に至るまでの格闘

事象でぐぐってみると、それっぽい記事が。

Dockerで、ホストからcurlでアクセスするとEmpty reply from serverがでてしまう | mokelab tech sheets


コンテナ内で起動しているサーバーがlocalhost指定でListenしている可能性があります。


サーバーがlocalhost指定でListenするなんてことがあるのですね。

そこでresponderのドキュメントを読んでみました。

https://python-responder.org/en/latest/quickstart.html#run-the-server


Note: you can pass port=5000 if you want to customize the port. The PORT environment variable for established web service providers (e.g. Heroku) will automatically be honored and will set the listening address to 0.0.0.0 automatically (also configurable through the address keyword argument).


怪しいので、さらにsourceの中身まで読んでみました。

https://python-responder.org/en/latest/_modules/responder/api.html#API.serve

        if address is None:

address = "127.0.0.1"
if port is None:
port = 5042

おお、127.0.0.1がめっちゃ怪しいですね。dockerのホストからのリクエストは、localhostとは別のIPのものと解釈されるらしいので、これが原因になることは有り得そう。


解決

address="0.0.0.0" を指定したら、hostからのアクセスでもreplyを返してくれました!

if __name__ == '__main__':

api.run(address="0.0.0.0")


補足

Flaskでも常識だったようですね。精進します:baby:

Flaskのサーバーはデフォルトだと公開されてない - Qiita