ポートとlocalhostがわかればネットワークの半分は読める
Docker記事の-p 8080:80やWSL記事のlocalhostを、意味が分からないまま「おまじない」として通り過ぎていないでしょうか。AIが生成する設定ファイルには当たり前のようにIPアドレス・ポート番号・localhostが登場しますが、この3つの役割分担さえ分かれば、ネットワーク関連のエラーの大半は読めるようになります。
IPアドレスとポート番号は「住所」と「部屋番号」
「IPアドレスさえ分かれば通信できる」と思ってしまいがちですが、実際には1台のPCの中でWebサーバー・データベース・SSHなど複数のサービスが同時に動いています。IPアドレスだけでは、そのうちのどのサービス宛てなのかを区別できません。そこで使われるのがポート番号です。
http://192.168.1.10:8080/api/users
^^^^^^^^^^^^ ^^^^
IPアドレス ポート番号
(どの機器か) (機器の中のどのサービスか)
ハクスラゲームのギルド街でたとえると、IPアドレスは「ギルド街のどの建物か」という住所、ポート番号は「その建物の何号室(武器屋なのか宿屋なのか)」にあたります。住所だけ知っていても目的の窓口にはたどり着けず、部屋番号(ポート)まで揃って初めて正しいサービスに接続できます。ポート番号は0〜65535の範囲で、0〜1023番はIANAという組織が用途を決めているwell-knownポート(80番はHTTP、443番はHTTPSなど)です。
localhostと127.0.0.1は「自分の机の中への手紙」
localhostという言葉を見ると、どこか外部のサーバーに問い合わせていると考えてしまいがちですが、実際には正反対です。localhostは127.0.0.1という特別なIPアドレス(ループバックアドレス)を指す名前で、この名前解決はDNS(ドメイン名をIPアドレスに変換する、インターネット上の住所録のような仕組み)のサーバーに問い合わせず、自分のPCの中にあるhostsファイルだけで完結します。
# localhost宛てのリクエストは外部に一切出ていかない(実行して試せる)
curl http://localhost:8080/
# Windowsのhostsファイル(C:\Windows\System32\drivers\etc\hosts)を見ると、
# 127.0.0.1という対応表が書かれているだけだと確認できる
type C:\Windows\System32\drivers\etc\hosts
# → 127.0.0.1 localhost
localhost宛ての通信は、郵便局(実際のネットワーク回線)を一切経由せず、自分の机の引き出し(PC内部のループバック)にそのまま手紙を入れるようなものです。だからこそWi-Fiを切っていてもlocalhostへの接続は普通に動きます。この仕組みを知っていれば、「localhostに繋がらない」というエラーが出たとき、ネットワーク回線ではなく自分のPCの中(ポートが開いているか等)を疑うべきだと判断できます。
ポートが衝突するとどうなるか:Dockerのポートマッピングを読み解く
Docker記事で見た-p 8080:80を、AIに勧められるまま何となく使っていないでしょうか。これは「ホスト側の8080番の部屋」と「コンテナ側の80番の部屋」を対応づける設定で、同じホスト側ポートを2つのコンテナが同時に使おうとすると衝突が起きます。
# 1つ目のコンテナがホストの8080番を使う
docker run -p 8080:80 nginx
# 同じ8080番を指定すると衝突してエラーになる
docker run -p 8080:80 another-app
# → Error: port is already allocated
同じ部屋番号(ポート)を2つのパーティ(コンテナやプロセス)が同時に予約しようとしている状態だと考えると、エラーの意味が直感的に分かります。AIに「ポートが使用中というエラーが出た」と伝えると、空いている別のポート番号(例: 8081)への変更を提案してくることが多いですが、それはこの部屋番号の重複を避けているだけだと分かれば、提案の意図まで理解できます。
よくあるはまりポイント:コンテナの中でlocalhostにバインドして繋がらない
Docker初心者が高確率で踏む地雷が、コンテナの中のアプリが127.0.0.1(localhost)だけを待ち受けるように設定されているケースです。ホスト側で-p 8080:80と正しくポートマッピングしていても、コンテナ内部から見ると「外から来た通信」は127.0.0.1(自分自身)宛てとは扱われないため、接続を拒否されてしまいます。
# NG: コンテナ内で127.0.0.1だけを待ち受けている
# → ホストからの-pマッピング経由の通信を「外から来た」ものとして拒否してしまう
app.listen(3000, "127.0.0.1")
# OK: 0.0.0.0(すべてのネットワークインターフェース)で待ち受ける
# → コンテナ外(ホスト経由)からの接続も受け付けられる
app.listen(3000, "0.0.0.0")
127.0.0.1での待ち受けは「自分の部屋の内線電話にしか出ない」状態、0.0.0.0での待ち受けは「建物のどの入口から来た配達員(通信)にも対応する」状態だと考えてください。Dockerのポートマッピングはホストの外にある建物の入口を、コンテナという別の建物につなぐ配達ルートを作るだけなので、コンテナ側の受付(アプリ)が内線(127.0.0.1)にしか出ないままだと、いくら配達ルートを整備しても荷物は届きません。設定ファイル自体は正しいのに繋がらないときは、まずこの待ち受けアドレスを疑うと解決が早くなります。
- DNS
- ドメイン名(example.comなど)をIPアドレスに変換する仕組み。localhostはDNSを使わずhostsファイルだけで解決される点が例外
- 0.0.0.0
- 「すべてのネットワークインターフェースで待ち受ける」ことを表す特別なアドレス。127.0.0.1(自分専用)との違いが接続トラブルの分かれ目になる
「繋がらない」というエラーに出会ったら、いきなり設定ファイル全体を疑うのではなく、①IPアドレスは合っているか②ポート番号は合っているか③サーバー側は127.0.0.1ではなく0.0.0.0で待ち受けているか、の3点を順番に確認してみてください。Dockerの記事やWSLの記事で見た設定も、この3点に分解して読み直すと、AIが生成した設定ファイルの意図がぐっと読み取りやすくなります。
IP・ポート・localhostの基本が分かったら、Dockerの記事で実際のポートマッピング設定を、Linux基礎コマンドの記事でコマンドラインからの動作確認の視点を確認してみてください。