LoginSignup
3
1

More than 3 years have passed since last update.

「Docker-proxyでらくらくにIPv6対応しようとしたらいつの間にか出来なくなっていた件」が解決していた件

Last updated at Posted at 2021-01-20

(自分用の備忘録)

2021/04/21: 追記

本問題は2021/04/12にリリースされたDocker version 20.10.6で修正された模様.
やっぱ仕様ではなくバグだった.
ワホーイ

Before docker 20.10, published ports were accessible through both IPv4 and IPv6 by default, but the API only included information about the IPv4 (0.0.0.0) 

Docker Engine release note

ということでDocker version 20.10.6に上げると解決します.

やりたいこと

デュアルスタックのDockerホスト上で、Dockerプロキシを利用してIPv4シングルスタックのDockerコンテナでIPv6のサービスをしたい。

共通環境

Ubuntu 20.04

# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=20.04
DISTRIB_CODENAME=focal
DISTRIB_DESCRIPTION="Ubuntu 20.04.1 LTS"
# uname -a
Linux server 5.8.0-36-generic #40~20.04.1-Ubuntu SMP Wed Jan 6 10:15:55 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux

期待している挙動

以下のようなdocker-composeで適当なDockerコンテナを起動し、portsでポートフォワーディングを実施する。


version: '3'
services:
  grafana:
    image: grafana/grafana
    ports:
    - 3000:3000

コンテナ起動後、該当のポートフォワーディングを行うdocker-proxyプロセスが同時に立ち上がる。

root      120970  0.0  0.0 475320  3912 ?        Sl   18:27   0:00 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 3000 -container-ip 172.18.0.4 -container-port 3000

  • IPv4のトラフィック iptablesに以下のようなDNATルールが登場するため、docker-proxyプロセスに達する前に処理される。
# iptables -t nat -L DOCKER
Chain DOCKER (2 references)
target     prot opt source               destination
RETURN     all  --  anywhere             anywhere
RETURN     all  --  anywhere             anywhere
DNAT       tcp  --  anywhere             anywhere             tcp dpt:3000 to:172.18.0.3:3000

ちなみに返りのパケットはPOSTROUTINGでIPマスカレードされる

# iptables -t nat -L POSTROUTING 

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
MASQUERADE  all  --  172.17.0.0/16        anywhere
MASQUERADE  all  --  172.18.0.0/16        anywhere
MASQUERADE  tcp  --  172.18.0.3           172.18.0.3           tcp dpt:3000
MASQUERADE  tcp  --  172.18.0.4           172.18.0.4           tcp dpt:8888

  • IPv6のトラフィック IPv6の場合IPv4とは異なりDNATのルールが挿入されず、上述docker-proxyプロセスがL4〜レベルで変換を実施する。

実際の挙動

これまで

確認したバージョン: Docker version 19.03.14, build 5eb3275d40

TypeIPv6になっており、IPv4/IPv6の両方でLISTENすることがわかる。

参考:
netstatやlsofでLISTENしているアドレスポートが IPv6と表示されてもIPv4でアクセスできる罠

# lsof -i:3000
COMMAND      PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
docker-pr 120970 root    4u  IPv6 1065660      0t0  TCP *:3000 (LISTEN)

最近(20.10.6)まで

確認したバージョン: Docker version 20.10.2, build 2291f61

TypeIPv4になっており、IPv4でしかLISTENしていない。
そのためIPv6でサービス提供が行えていないない

# lsof -i:3000
COMMAND     PID USER   FD   TYPE  DEVICE SIZE/OFF NODE NAME
docker-pr 14845 root    4u  IPv4 6231154      0t0  TCP *:3000 (LISTEN)

対処方法

Docker versionを20.10.6以降にすると以前(version 19)までの挙動に戻る。
公式ドキュメントを参照して指定したバージョンのdocker-ce, docker-ce-cliをinstallする。

Install Docker Engine

- installできるdocker-ceのバージョンを確認

# apt-cache madison docker-ce | head -n 4
 docker-ce | 5:20.10.6~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.5~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.4~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages
 docker-ce | 5:20.10.3~3-0~ubuntu-focal | https://download.docker.com/linux/ubuntu focal/stable amd64 Packages


  • 現在のdocker-ceをuninstall
# apt-get remove docker-ce docker-ce-cli 
  • 指定したバージョンののdocker-ce, docker-ce-cliをinstall
# apt-get install docker-ce=<VERSION_STRING> docker-ce-cli=<VERSION_STRING>  containerd.io

所感と今後

このような仕様変更が行われた経緯に関してはま調べられていないが、めっちゃ困る
追記: version 20.10.6で修正されました.
Docker Engine release note

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1