ホストで動かしていたコンポーネント群をdocker-composeに乗せたところ、コンポーネント間の通信が通らなくなってしまった。 いずれもdocker-composeが作ったデフォルトのネットワークで動いているのでpingは通る。 コードを見てみたところサーバーが localhost で listen していたので 0.0.0.0 に修正した。
localhostは /etc/hosts で 127.0.0.1 に解決されるわけだが、これは loopback interface lo で通信するループバックアドレスで、自身を指す。
$ cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
...
$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
2: sit0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN qlen 1000
link/sit 0.0.0.0 brd 0.0.0.0
34: eth0@if35: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:12:00:03 brd ff:ff:ff:ff:ff:ff
inet 172.18.0.3/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
一方、0.0.0.0 は送信先にはできない特別なアドレスで、全てのネットワークインタフェースのアドレスで待ち受ける。 こちらは lo の 127.0.0.1 に加えて eth0@if35 の 172.18.0.3 でもアクセスできる。 したがって、外部からの通信を受けるには 127.0.0.1 ではなく 0.0.0.0 (あるいは 172.18.0.3) で listen する必要があった。
$ nc -l 0.0.0.0 12345 &
$ nc 127.0.0.1 12345
$ nc 172.18.0.3 12345