localhostでDockerコンテナにどうしても繋がらない

Docker, Programming30 October 2020

Dockerコンテナで立ち上げた何らかのアプリケーションに、 localhost:port番号でどうしても繋がらない時に確認すべきことのメモです。

curl: (52) Empty reply from server

まずそもそもどんなエラーというと、curlしてみたら以下のエラー

curl: (52) Empty reply from server

ブラウザからアクセスしようとしたら、

このページは動作していません

のめっちゃムカつくやつでした。

コンテナ内のアプリケーション自身がlocalhostでのみListenしていた

僕の場合の原因は、コンテナ内で実際に動くアプリケーション自身が localhostでのListenをしていたことになります。

具体的にどのアプリケーションかというと、 本ブログで使用しているPelicanというPython製の静的サイトジェネレータです。

Pelicanは起動するときに、

$ pelican --listen

でOKなのですがこれはコンテナを使用しない場合です。 コンテナを使用して立ち上げたPelicanに対して、ホストのPCからアクセスするにはオプションが必要でした。

$ pelican --listen --bind=0.0.0.0

これは全てのIPからの接続をListenするということになります。

Pelicanに限った話ではなく、PythonではFlaskでもFastAPIでも同様に指定できるオプションがあり デフォルトではどれもlocalhostからの接続のみになっているので、オプションが必要です。

FastAPIの例

$ uvicorn main:app --host 0.0.0.0

なぜこのような挙動なのか

Dockerのネットワークとして、ホストPCから実際にはコンテナ1つ1つに振られたプライベートIPアドレスに対して DNATを行い接続をするという動きをしているようです。 こちらのサイトがわかりやすいです。

そのため、通常はコンテナから見るとリクエストはlocalhostに見えないため弾かれるということになります。

上記サイト様の情報を確認するとコンテナ起動時にDockerのネットワーク設定をbridgeではなく、 hostにすれば行けるかもしれません。(未確認です)