ポートについて迷っていたらAIが、「netstat -tuln」とコマンドを打ち込んでん結果を見せろと言ったので色々と聞いてみた。
netstat -tulnとその結果
netstat -tuln
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 127.0.0.53:53 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN
tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN
tcp 0 0 127.0.0.1:43025 0.0.0.0:* LISTEN
Proto
: プロトコル(tcp, udp, tcp6, udp6)Recv-Q
: 受信キューSend-Q
: 送信キューLocal Address
: ローカルのIPアドレスとポート番号0.0.0.0
: 全てのネットワークインターフェースでリッスン127.0.0.1
: ローカルホストのみでリッスン:::
: IPv6の全てのインターフェースでリッスン
Foreign Address
: 接続相手のアドレスとポート0.0.0.0:*
: どのアドレスからの接続も受け付ける
State
: 接続の状態LISTEN
: 接続待ち受け状態
Local Addressってなに?
Local Address
は「どのインターフェースで待ち受けるか」を指定しています。
例えば:
127.0.0.1:37589
の場合- localhost(=loopbackインターフェース)のみがPort
37589
を待ち受けできる
- localhost(=loopbackインターフェース)のみがPort
0.0.0.0:32791
の場合- 全てのインターフェースでPort
32791
を待ち受けできる
- 全てのインターフェースでPort
つまり
Local Address Foreign Address State
127.0.0.1:37589 0.0.0.0:* LISTEN
ならば
Local Address
=>localhost(=loopbackインターフェース)の37589ポートで待ち受けるForeign Address
=>接続してくる相手のアドレスは制限なし(ただしloopbackインターフェースからしかアクセスできないため、実質的には同じマシン内からのみ)State
: 待ち受け中
という意味になります。
Local Address
で指定できる主なものは:
0.0.0.0
: 全てのインターフェース127.0.0.1
: loopbackインターフェースのみ- 特定のIPアドレス : その特定のインターフェースのみ
です。
ネットワークインターフェース
ネットワークインターフェースには物理的なものと論理的(仮想的)なものがある
- 物理インターフェース:
- eth0(イーサネットカード)
- wlan0(無線LANカード) など、実際のハードウェアデバイス
- 論理インターフェース:
- localhost = loopback(lo、127.0.0.1)
- docker0(Dockerの仮想ネットワーク)
- tun0/tap0(VPNの仮想インターフェース)
- vethXXXXX(コンテナ用の仮想イーサネット) など、ソフトウェアで作られた仮想的なインターフェース
Local Addressが「0.0.0.0:32791」と書いてあったら
Local Addressが「127.0.0.53:53」と書いてあったら
53ポートで待ち受けているのは127.0.0.53
Foreign Addressで、0.0.0.0:*
と書いてあって、「どのアドレスからの接続も受け付ける」と決められていても、既に「127.0.0.53」がポートを(待ち受けのために)占有しているので他のネットワークインターフェースは接続できない。
じゃあ、dockerのymlファイルでPortsって書いてあるのは何?
ymlでPortsで指定すると、その内容をDocker Daemonが察して指定のポートで待ち受けてその内容をコンテナ内の指定された仮想ポートに転送する
ports:
# 全インターフェースでの待ち受け(0.0.0.0)
- "32791:80"
# Dockerインターフェースのみ(172.17.0.1)
- "172.17.0.1:32791:80"
# eth0の特定IPのみ
- "x123-45-67-89:32791:80"
dockerでNginx Proxyを使って複数のサイトを作るとき、それぞれのサイトのymlではPortsは使わない!
それぞれのサイトのymlでPorts: 80:80みたいにしたら、Docker Daemonにそれぞれ別々に80ポートの監視を依頼して、コンフリクトする!
なのでNginx ProxyのymlファイルだけPorts: 80:80, 443:443を書いて、あとのymlファイルではexpose: 80のように書く。
docker psでDocker Daemonに監視を依頼しているコンテナがわかる
docker psコマンドで->
の矢印がある表示があるものが、Docker Daemonにホストのポート監視を依頼しているコンテナということ
$ docker ps
PORTS
80/tcp hogehoge1-nginx
80/tcp hogehoge2-nginx
0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp nginx-proxy
この例だと、nginx-proxyが、全てのネットワークインターフェースの80と443ポートを監視してdocker内の仮想ポート80に転送していることになる。