- [2015-01-24 05:00] @5t111111 さんのコメントに基づき、Rack 1.6 のデフォルト挙動について追記
Rack 1.6.0 を使用した Sinatra アプリケーションを Docker 上で起動したところ、コンテナ外からの接続ができませんでした。EXPOSE 9292
して -p 9292:9292
しているにも関わらず、です。
とりあえずの対処法を書いておきます。
アプリケーション構成例
最小構成の Sinatra アプリケーションを Docker 上で動かすためのファイル例を Gist に上げました。
はじめに言っておくと、Ruby のバージョンを変えること(2.1.5 にするとか)は解決になりませんでした。Ruby 2.2.0 のせいとかではない。
あと Docker のバージョンは (2015-01-21 最新の)1.4.1 です。
対処法1: Rack 1.5.2 を使う
一つ前のバージョンである Rack 1.5.2 であればこの問題は発生しません。Gemfile でバージョン指定しましょう。
gem "rack", "~> 1.5.2" # or "= 1.5.2"
対処法2: rackup
に -o 0.0.0.0
オプションをつける
rackup --help
より、
-o
は ListenAddress を設定するためのオプションです。
-o, --host HOST listen on HOST (default: 0.0.0.0)
というように 0.0.0.0
がデフォルトで設定されるよ、と書いてありますが明示的に指定してあげます。Dockerfile だと最後の CMD
がこういう感じになります。
CMD ["bundle", "exec", "rackup", "-p", "9292", "-E", "production", "-o", "0.0.0.0"]
--- 2015-01-24 05:00 追記 ---
Rack 1.6 からは、明示的に指定しない限り localhost のみを listen するような変更が加わったとのことです。公衆 Wi-Fi につないでるような場合に、他の端末からアクセスされないようにするためです。
プルリクは rack/rack#514
該当コミットは 28b0144
ということで上のヘルプメッセージは変更に追随できてないのですが、これもコミット 076711a で修正が入りました。
次のリリースでは直っているはず!
教えてくださった @5t111111 さん、ありがとうございました。
--- 追記ここまで ---
ちなみに、localhost からアクセスした時のログですが
-o 0.0.0.0
なしの場合、以下のようにリクエスト元 IP が IPv6 に、
::1 - - [21/Jan/2015:15:35:31 +0900] "GET / HTTP/1.1" 200 8056 2.2458
-o 0.0.0.0
ありの場合、以下のようにリクエスト元 IP が IPv4 になっています。Rack 1.5.2 でも同様のログが得られます。
127.0.0.1 - - [21/Jan/2015:15:37:11 +0900] "GET / HTTP/1.1" 200 8056 2.0355
詳しくはまだ追えていないのですが、多分 Docker のネットワーク部で IPv6 と IPv4 の対応か何かができてないのが理由かな…と思っています。
デフォルト値をそのまま指定しているのに、挙動が変わる Rack もなんか不自然ですが…
--- 2015-01-24 05:00 追記 ---
上に追記しましたが、Rack 1.6 からはデフォルトで localhost のみを listen するようになりました。この状態では、コンテナ外からアクセス出来ないのは当然ですね…。
(ヘルプに書かれた)デフォルト値をそのまま指定して挙動が変わるの、ヘルプが間違っているのですからこれまた当然です…。
Docker の挙動の問題ではありませんでした。
--- 追記ここまで ---
おわりに
Rack 1.6 な Sinatra アプリケーションに Docker コンテナ外からアクセスするための対処法を紹介しました。Sinatra アプリケーションを bundle update
する際は注意してください。
ここに上げた方法は、その場しのぎの対応である感じが否めません。Docker のネットワーク周り確認したり、Rack のソースコード読まないといけませんね(1.5.2 -> 1.6.0 の ChangeLog が無いの厳しい…)。