curl「(7) Failed to connect」の原因と直し方
curl: (7) Failed to connect は、名前は引けたがそのホストとポートで待ち受けるサーバーが無いと出る。
サーバーの起動とポート番号、待ち受けるアドレス、コンテナの中の localhost の意味を順に確かめれば直る。
公開:
要約
curl: (7) Failed to connect は、ホスト名の解決までは済んだが、そのアドレスとポートへの TCP 接続を相手に拒まれたときに出る。
curl 8.23.0 で何も待ち受けていないポートを指すと、次の表示になり終了コード 7 で終わった。
curl: (7) Failed to connect to localhost:8000 after 0 ms: Could not connect to servercurl 8.14.1 では localhost port 8000 のように書き方が少し違ったが、番号の 7 と意味は同じである。そのホストとポートで待ち受けているプロセスが無いので、curl の設定より先にサーバー側を確かめる。
解決策
1. 待ち受けているプロセスとポートを確かめる
-v を付けると、どのアドレスへの接続が拒まれたかが行ごとに出る。
* connect to ::1 port 8080 from ::1 port 42604 failed: Connection refused
* connect to 127.0.0.1 port 8080 from 127.0.0.1 port 35616 failed: Connection refused
curl: (7) Failed to connect to localhost port 8080 after 0 ms: Could not connect to serverIPv6 と IPv4 の両方で Connection refused なら、そのポートでは何も待ち受けていない。
サーバーのログで実際に待ち受けているポートを確かめ、URL を合わせる。
2. 待ち受けるアドレスを 0.0.0.0 にする
外から呼ぶサーバーは、すべてのアドレスで待ち受けさせる。
python -m http.server 8000 --bind 0.0.0.0待ち受けを 0.0.0.0 に変えると、別のコンテナからの同じ curl が 200 を返した。
Node.js や Flask などの開発サーバーも、待ち受けるホストの設定に同じ考え方で 0.0.0.0 を渡す。
3. コンテナからはコンテナ名か host.docker.internal で呼ぶ
ユーザー定義ネットワークに入ったコンテナどうしは、コンテナ名で互いを呼べる(新しいタブで開く)。
Compose ならサービス名を使う。
docker network create app-net
docker run -d --name api --network app-net python:3.12 python -m http.server 8000
docker run --rm --network app-net curlimages/curl -sS http://api:8000/ホストで動いているサービスや、ホストに公開したポートを呼ぶなら、Docker Desktop では host.docker.internal を使う。http://host.docker.internal:18010/ に変えると 200 が返った。
番号が違うときは別の原因
ポートを公開したコンテナの中でサーバーが 127.0.0.1 だけで待ち受けていると、ホストからの curl は (7) ではなく (52) Empty reply from server になった。
接続自体は Docker のポート転送が受けるためである。
この場合も直し方は解決策 2 と同じになる。
よくある原因
- サーバーが起動していない。
起動直後に例外で落ちている場合も同じエラーになる。 - ポート番号が違う。
8000 で動いているサーバーに 8080 で接続すると、名前は引けても(7)になった。 - サーバーが
127.0.0.1だけで待ち受けている。python -m http.server 8000 --bind 127.0.0.1のコンテナに、同じネットワークの別のコンテナからコンテナ名で接続すると(7)になった。
同じコンテナの中から127.0.0.1で呼ぶと 200 が返る。 - コンテナの中の
localhostはそのコンテナ自身を指す。
ホストの 18010 番に公開したサーバーへ、別のコンテナからlocalhost:18010で接続すると(7)になった。