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にすれば行けるかもしれません。(未確認です)