[Docker][network][ipv6] Dockerのcontainerでipv6を使用し、かつ内から外へ疎通する。

AIX、UNIX、LinuxContainerNetwork
Screenshot-2018-6-16 Docker と IPv6 — Docker-docs-ja 17 06 Beta ドキュメント

はじめに

しっかりとDockerのipv6周りについては理解していないです。ドキュメントも読んでみたのですが、私の知識不足がたたってか、あまり呑み込めていないです。

Dockerを使用する前から、自宅のネットワーク環境にIPv6を整備しつつあったのですが、機能の一部をDockerに移していたところ、IPv6での疎通がうまくいっていないことをTwitterで呟いていたりしました。

で、改めてチャレンジした次第。

参考にした情報

最も参考になったのは以下のWebページ。

Dockerとipv6で調べてみるとよく出てくる情報は、Unique Local AddressとNAT66を併用したパターンになるかと思います。

ただ、こちらでも書かれているように、Unique Local Addressの場合は、RFC6724で定義されているpolicy tableに従って、IPv4/IPv6 dual stackのインスタンスとの通信ではIPv4が優先される、とのことで、通常とは逆の動作になるかと思います。

あと、ip6tablesの設定を投入するのが案外面倒な面もあるかもしれません。

もう一つとしてはGlobal unicast Addressを使用するパターンになるかと思います。
個人的には、こちらの方が、ホスト側に設定されたIPv6アドレスの拡張の範囲で設定できるので、あまり違うネットワークといえばいいのか、理解のずれ?みたいなものが少ないような気がします。

今回自分の場合は、後者で設定し、疎通できることを確認しました。

DockerでIPv6通信を行うようにするには

Dockerでipv6なネットワーク設定を行う場合は以下の方法があると思います。

  • Docker networkコマンドから、ipv6オプションを付与したうえで作成する。
  • daemon.jsonにipv6向け設定を追加する。
  • docker-composeファイルに、都度ipv6を付与するネットワーク設定を追加する。

というわけで、今回は一番よく使うパターンになる3番目のDocker-composeファイルを使用した形をメモしておこうと思います。

設定方法

docker-composeの場合

ちなみにDocker-composeファイルに記述するときは、versionは”3″だとダメなようで、私は”2.1″を使用しています。containerの設定で”3″固有の記述があるのであれば、見直すか、別の設定方法に変更する必要があるはずです。

version: "2.1"
  services:
  networks:
    default-net:
    driver: bridge
    enable_ipv6: true
    ipam:
    driver: default
    config:
      - subnet: 172.32.0.0/24
        gateway: 172.32.0.1
      - subnet: 240x:zzzz:xxxx:yyyy:1000::/80
        gateway: 240x:zzzz:xxxx:yyyy:1000::1

ここで設定するsubnetはDocker containerが所属するネットワークアドレス、gatewayはcontainerホストに設定されるipv6アドレスであり、各containerのデフォルトゲートウェイに設定されるアドレスになるはずです。

これでDockerゲスト?からDockerホスト側へはping6が飛ぶようになると思います。が、グローバルへ確認しても、返答をDockerホストからDockerゲストへ戻してあげることができないため、疎通不能になるはずです。

NDP Proxyを設定する

これを解消するために、Dockerホスト側にNDP Proxyを有効にします。

net.ipv6.conf.eth0.proxy_ndp=1

隣接するシステムとして、neighbor addを各containerで設定する必要があるのですが、さすがにこれは現実的ではないので、ndppd – NDP Proxy Daemonを導入する方が早いはずです。

$ sudo apt update
$ sudo apt install ndppd
$ cat /etc/ndppd.conf
proxy eth0 {
  rule 240x:zzzz:xxxx:yyyy:1000::/80 {
    static
  }
}

ndppdについては以下を参照してください。

これを設定することで、DockerゲストがDockerホストのneighbor tableに登録されることになるので、グローバルを含めた形で疎通ができるようになるはずです。

確認してみる

$ docker network inspect docker-env_default-net
"Containers": {
  "0c3c9bda23a7768031525ee92ed4b91af4fc42fc8be8ed3533795e6722bc4ee6": {
    "Name": "bind-9",
    "EndpointID": "4609709ec8c06d2f89eb5ecdce8a749134ffdb31ba96027b48a6fb302e6ed531",
    "MacAddress": "02:42:ac:20:00:08",
    "IPv4Address": "172.32.0.8/24",
    "IPv6Address": "240x:zzzz:xxxx:yyyy:1000::8/80"
$ docker exec -it bind-9 ip -6 a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 state UNKNOWN qlen 1000
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
219: eth0@if220: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 state UP
inet6 240x:zzzz:xxxx:yyyy:1000::8/80 scope global flags 02
valid_lft forever preferred_lft forever
inet6 fe80::42:acff:fe20:8/64 scope link
valid_lft forever preferred_lft forever
$ docker exec -it bind-9 ip -6 r
240x:zzzz:xxxx:yyyy:1000::/80 dev eth0 metric 256
fe80::/64 dev eth0 metric 256
ff00::/8 dev eth0 metric 256
default via 240x:zzzz:xxxx:yyyy:1000::1 dev eth0 metric 1024
$ docker exec -it bind-9 ping6 -c 3 www.google.com
PING www.google.com (2404:6800:4004:80b::2004): 56 data bytes
64 bytes from 2404:6800:4004:80b::2004: seq=0 ttl=51 time=5.824 ms
64 bytes from 2404:6800:4004:80b::2004: seq=1 ttl=51 time=6.240 ms
64 bytes from 2404:6800:4004:80b::2004: seq=2 ttl=51 time=6.378 ms
--- www.google.com ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 5.824/6.147/6.378 ms
Compose Specification(仕様) — Docker-docs-ja 24.0 ドキュメント

理解そのものの間違い等はあると思いますので、気が付いた方はご指摘いただければと思います。

この記事を書いた人

kometchtech

うつ病を患いながら、IT業界の末席にいるおっさんエンジニア。科学計算をしたことがないのに、HPC分野にお邪魔している。興味のある分野で学習したことをblogにまとめつつ、うつ病の経過症状のメモも置いておく日々。じつはRouterboard User Group JPの中の人でもある。 Amazon欲しいものリスト / Arm板を恵んでくれる人募集中

kometchtechをフォローする
タイトルとURLをコピーしました