18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

今一番楽なDockerのIPv6対応方法

Last updated at Posted at 2023-07-11

モチベーションと概要

  • Dockerのコンテナでも簡単にIPv6でサービスしたい。
  • docker composeでIPv4と同じノリでやりたい
  • 色んな方法が乱立していてわからない
  • 執筆現在で一番楽な方法をまとめた。
    • IPv6 NAPT を利用するので、それぞれの信条によっては相容れないかもしれない。

初稿時点(2023年)ではExperimentalな機能を利用しています。
新しめの機能を利用しているため、あなたが読んでる時には仕様が変わっている可能性があります。

環境

# docker --version
Docker version 27.3.1, build ce12230
# uname -r
6.8.0-45-generic
# cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=24.04
DISTRIB_CODENAME=noble
DISTRIB_DESCRIPTION="Ubuntu 24.04.1 LTS"

  • 改訂時点(2024/11)でlatestなversionのdocker

手順

後述する"自作bridgeでNAPT法"をベースに、dockerに最近実装された新しい機能を使って、自分でNATルールのケアをしなくて済むようにした...という内容。

1. /etc/docker/daemon.json : IPv6関連機能を有効化

/etc/docker/daemon.json
{
    "ipv6": true,
    "ip6tables": true,
    "userland-proxy": false,
    "fixed-cidr-v6": "fd00:ace:cafe:beaf::/80"
}

項目の説明

  • IPv6: trueにしてコンテナがIPv6を利用するようにする。
  • ip6tables : IPv4と同様にDNATによるポートフォワーディングを行う。
  • user-land-proxy: ip6tablesによるDNATを使う場合は通常使われないので、無効化する。
  • fixed-cidr-v6: default bridge(docker0)が使うIPv6 prefixを明示的に指定する場合がある。一般的にはULAの使用が推奨される。
    しかしにULAはアドレス選択ポリシーでプライベートIPv4アドレスに負けるので1、IPv4を無効化出来ない現状のdocker network実装ではIPv6シングルスタック環境で動作させる時に困る。アドレス選択ポリシーをオーバライドすることも可能ですが、IPv6インターネットで利用されてない別のアドレス2を使う荒業も無きにしもあらず。

おすすめ設定には書いてませんが、よく使われるオプションは下記の通り。

{
    "experimental": true,
    "default-address-pools": [
        { "base": "fd00:beaf:cafe::/48", "size": 64 }
    ]
}
  • experimental: 初稿時点ではexperimentalな機能だったのでflagが必要だったが、本稿改訂時点では不要になったみたい。少し前のバージョンでは必要。

  • "default-address-pools": docker composeやdocker network create --ipv6 MYBRIDGE でbrdigeを作成する際に、割り当てられるIPv6 ネットワークを変更することができる。指定しない場合、自動的にULAが都度生成される。

2. /etc/sysctl.confを編集 IPv6 Forwardingを有効化

IPv4はdockerデーモンが勝手に有効化してくれるが、初稿時点(2023)ではIPv6に関しては自前で有効化する必要があった。
改訂時点(2024/11)では勝手にやってくれるようになっているので、新しい環境では気にしなくても良い。

/etc/sysctl.conf
net.ipv6.conf.all.forwarding = 1

sysctl -p で有効化

3. docker再起動

systemctl stop docker.socket
systemctl stop docker

systemctl start docker

4. default bridgeにIPv6アドレスがついていることを確認

root@netbox:/opt/netbox-docker# ip addr show docker0 | grep inet6
    inet6 "fd00:ace:cafe:beaf::1/80 scope global tentative
    inet6 fe80::1/64 scope link tentative

5. 動かしたいアプリのdocker-composeに下記を追加

ここではサービスの例にnginxを挙げている。

docker-compose.yml
version: '3'
services:
  nginx:
    restart: unless-stopped
    image: nginx:latest
    ports:
    - '80:80'
    - '443:443'
networks:
  default:
    enable_ipv6: true

もし割り当てられるprefixを明示的に指定したい場合、下記のようにする。

networks:
  default:
    enable_ipv6: true
    ipam:
      config:
        - subnet: fdca:dead:cafe:ace::/80 # 好きなprefix。最低限/112があれば良いはず。
          gateway: fdca:dead:cafe:ace::1 # ホスト側につくアドレス

6. 起動して確認

docker compose up -d

dockerデーモンが勝手に、1)outbound用のNAPTルール作成 2) inbound用のDNATルール作成 までやってくれる。

# ip6tables-save -t nat
*nat
:PREROUTING ACCEPT [937:73340]
:INPUT ACCEPT [2:128]
:OUTPUT ACCEPT [137:13412]
:POSTROUTING ACCEPT [930:76752]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -o br-b6440381d435 -m addrtype --src-type LOCAL -j MASQUERADE
-A POSTROUTING -s fdca:dead:cafe:ace::/64  ! -o br-b6440381d435 -j MASQUERADE
-A POSTROUTING -o docker0 -m addrtype --src-type LOCAL -j MASQUERADE
-A POSTROUTING -s fd00:ace:cafe:beaf::1/80 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s fdca:dead:cafe:ace::3/128 -d fdca:dead:cafe:ace::3/128 -p tcp -m tcp --dport 443 -j MASQUERADE
-A POSTROUTING -s fdca:dead:cafe:ace::3/128 -d fdca:dead:cafe:ace::3/128 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -p tcp -m tcp --dport 443 -j DNAT --to-destination [fdca:dead:cafe:ace::3]:443
-A DOCKER -p tcp -m tcp --dport 80 -j DNAT --to-destination [fdca:dead:cafe:ace::3]:80
COMMIT

参考情報:これまで筆者がやってきた方法たち

Docker Proxy を利用する方法

  • メリット: 楽
  • デメリット:
    • コンテナ内からIPv6 Internetへのアクセスが出来ない
    • IPv6はdockerホスト内のproxy経由で、IPv4は通常はNAPT + ポートフォワード、とプロトコルファミリーによってサービス方法が変わるので直感的でない。

自作bridgeでNAPT法

  1. docker network createで自作bridgeを作成。
  2. IPv6 NAPT ruleを追加
    a. コンテナ -> Internet用のNAPTルール
    b. Internet -> コンテナ:特定ポートへのDNATのルール
  3. netfilter-persistent等で保存
  4. docker-composeで自作bridgeをコンテナにアサイン
  5. netfilter-persistent等で保存
  • メリット:
  • デメリット:
    • NAPTルールが再起動後に綺麗に効くようにするために工夫が必要

その他

NAPTを使わないIPv6らしい方法もあるが、可搬性が良くないのであまりオススメできない。

参考リンク

  1. Considerations For Using Unique Local Addresses

  2. 例えば3ffe::/16 6boneアドレス(3FFE::/16)の利用廃止について

18
6
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
18
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?