VSCode Remote Container 間を 172.17.0.1 経由で通信する

TL;DR

~/.config/Code/User/settings.json

"remote.localPortHost": "allInterfaces"

を追加すると 172.17.0.1 でコンテナ間の通信ができる。

github.com

Remote Container だと 172.17.0.1 で他のコンテナに接続できない

普通に Docker を使っているときはコンテナの中から他のコンテナへのアクセスは 172.17.0.1 を使えばできました。

# コンテナ1
$ docker run --rm -p 9000:9000 python:3 python -m http.server 9000
172.17.0.1 - - [23/Feb/2022 06:59:03] "GET / HTTP/1.1" 200 -

# コンテナ2
$ docker run --rm alpine/curl http://172.17.0.1:9000
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   987  100   987    0     0   647k      0 --:--:-- --:--:-- --:--:--  963k
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".dockerenv">.dockerenv</a></li>
<li><a href="bin/">bin/</a></li>
<li><a href="boot/">boot/</a></li>
<li><a href="dev/">dev/</a></li>
<li><a href="etc/">etc/</a></li>
<li><a href="home/">home/</a></li>
<li><a href="lib/">lib/</a></li>
<li><a href="lib64/">lib64/</a></li>
<li><a href="media/">media/</a></li>
<li><a href="mnt/">mnt/</a></li>
<li><a href="opt/">opt/</a></li>
<li><a href="proc/">proc/</a></li>
<li><a href="root/">root/</a></li>
<li><a href="run/">run/</a></li>
<li><a href="sbin/">sbin/</a></li>
<li><a href="srv/">srv/</a></li>
<li><a href="sys/">sys/</a></li>
<li><a href="tmp/">tmp/</a></li>
<li><a href="usr/">usr/</a></li>
<li><a href="var/">var/</a></li>
</ul>
<hr>
</body>
</html>

Remote Container を2つ立ち上げて同じようにすると Connection refused になってしまいました。 172.17.0.1 だとつながりませんが、コンテナに割り振られた IP address である 172.17.0.2 だと接続できました。

# remote container 1
vscode ➜ /workspaces/exp $ python -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

# remote container 2
vscode ➜ /workspaces/exp_ubuntu $ curl http://172.17.0.1:8000
curl: (7) Failed to connect to 172.17.0.1 port 8000: Connection refused

vscode ➜ /workspaces/exp_ubuntu $ curl http://172.17.0.2:8000
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".devcontainer/">.devcontainer/</a></li>
</ul>
<hr>
</body>
</html>

ちなみにローカルから Remote Container で動かしているコンテナにはアクセスできます。 これがアクセスできるなら 172.17.0.1 からも接続できそうなものですができません。

# remote container 1
vscode ➜ /workspaces/exp $ python -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [23/Feb/2022 07:20:40] "GET / HTTP/1.1" 200 -

# ローカル
~ $ curl http://localhost:8000
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".devcontainer/">.devcontainer/</a></li>
</ul>
<hr>
</body>
</html>

違い

ss 使って remote container の場合とそうでない場合を比較してみます。

# remote container で python -m http.server 8000 を動かした場合
$ ss -atn
State  Recv-Q Send-Q Local Address:Port    Peer Address:Port Process
LISTEN 0      511        127.0.0.1:8000         0.0.0.0:*
...

# docker run --rm -p 8000:8000 python:3 python -m http.server 8000 で動かした場合
$ ss -atn | grep 8000
LISTEN    0      4096         0.0.0.0:8000        0.0.0.0:*           
LISTEN    0      4096            [::]:8000           [::]:*

remote container だと 127.0.0.1 になっていて 0.0.0.0 でない。どうやらここが原因のようです。

調べてみると VSCode 側の設定でデフォルトだと 0.0.0.0 でなく localhost で listen する設定になっているとのこと。

stackoverflow.com

設定を変えると無事に remote container 間で 172.17.0.1 経由で通信することができました。

# remote container 1
vscode ➜ /workspaces/exp $ python -m http.server 8000
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
127.0.0.1 - - [23/Feb/2022 08:20:34] "GET / HTTP/1.1" 200 -

# remote container 2
vscode ➜ /workspaces/exp_ubuntu $ curl http://172.17.0.1:8000
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".devcontainer/">.devcontainer/</a></li>
</ul>
<hr>
</body>
</html>