きっかけ
「WEBパフォーマンスチューニング ISUCON」という本を参考に、abコマンドを使ってlocalhost
にアクセスしようとしたところ、WSL(Windows Subsystem for Linux)環境内からアクセスした際に問題が発生しました。具体的には、アクセスログにリクエストが記録されず、意図した動作が得られませんでした。試行錯誤の結果、解決策を見つけたので、共有します。
1. curlでlocalhostを叩いてみる
まず、問題の再現と原因を特定するために、curl
を使ってlocalhost
にアクセスしてみました。
WSL内からのアクセス
以下のコマンドでWSL内からlocalhost
にアクセスした結果です。
curl -v localhost
出力は以下の通りです:
* Trying 127.0.0.1:80...
* Connected to localhost (127.0.0.1) port 80 (#0)
> GET / HTTP/1.1
> Host: localhost
> User-Agent: curl/7.81.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Tue, 13 Aug 2024 13:15:47 GMT
< Content-Type: text/html
< Content-Length: 612
< Last-Modified: Thu, 08 Aug 2024 05:17:10 GMT
< Connection: keep-alive
< ETag: "66b454d6-264"
< Accept-Ranges: bytes
<
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
この結果から、localhost
はWSL内で実行されているNginxサーバーのデフォルトページにアクセスしていることがわかります。
ホストのWindows側からのアクセス
次に、Windowsホスト側からlocalhost
にアクセスした結果です:
curl -v localhost
出力は以下の通りです:
詳細: GET http://localhost/ with 0-byte payload
詳細: received 33313-byte response of content type text/html;charset=utf-8
StatusCode : 200
StatusDescription : OK
Content : <!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Iscogram</title>
<link href="/css/style.css" media="screen" rel="stylesheet" type="text/css">
</head>
<body>
<div clas...
ここでは、Windows側で実行されているWebサーバー(ISUCONサイト)にアクセスできていることが確認できます。
2. 問題の特定と解決策
問題
WSL内からlocalhost
を叩くと、WSL内で実行されているサービスに接続されるため、Windowsホスト側で実行されているサービスにはアクセスできません。この違いは、WSLとWindowsホストが異なるネットワークスタックを持っているために発生します。
解決策
WSL内からWindowsホストで実行されているWebサーバーにアクセスするためには、localhost
ではなくhost.docker.internal
という特別なドメイン名を使用します。このドメインは、Windowsホストを指し示し、WSL2やDockerコンテナからホスト側のサービスにアクセスする際に利用できます。
具体的には、以下のコマンドを使用します:
curl -v http://host.docker.internal/
これにより、WSL内からWindowsホスト上で実行されているサービスにアクセスでき、ホスト側のWebサーバーの応答を得ることができます。
3. 原因
この問題は、WSLとWindowsホストが異なるネットワークスタックを使用していることに起因しています。WSL2では、WindowsホストとWSL2インスタンスがそれぞれ独自のIPアドレスを持つため、localhost
がWSL2インスタンス自身を指すようになり、ホスト側のサービスに直接アクセスできなくなります。
Microsoftが提供しているhost.docker.internal
は、この問題を解決するための手段であり、WSL2からホスト側のサービスにアクセスするためのシンプルな方法です。
4. まとめ
WSL内からWindowsホストで動作しているサービスにアクセスする際には、localhost
ではなくhost.docker.internal
を使用することで、ホスト側のサービスに正しくアクセスできます。これにより、WSL内での開発やテストがよりスムーズに行えるようになります。もし同様の問題に遭遇した場合、この手法を試してみてください。
記事を執筆するにあたり、生成AIを使用しました。