📖

Rootless DockerでIPv6を使いたい

2025/02/11に公開

はじめに

Rootless Dockerのコンテナ内からIPv6でホスト外にアクセスするための設定方法について紹介します。

デフォルトで使われるネットワークドライバであるslirp4netnsvpnkitはIPv6に対応していないため、代わりにpastaを使います。

環境

説明で利用するOSはUbuntu 24.04 LTSです。それ以外のOSでも動くと思いますが、pastaを手動インストールする必要があるかもしれません。

もちろんホストがIPv6ネットワークで外にアクセスできる状態になっていることが前提です。ping6 www.google.com等で確認しておきましょう。

セットアップ

必要なパッケージのインストール

必要なパッケージをインストールします。pastapasstパッケージに含まれています。動作確認にDocker Composeを使うため、そのパッケージもインストールします。

$ sudo apt install docker.io docker-compose-v2 passt

Rootless Dockerのインストール

公式サイトのインストーラを用います。古いバージョンだとpastaをうまく利用できないため、再インストールした方が良いかもしれません。

この時Rootless Dockerでpastaを利用するための設定ファイルを用意しておきます。

$ curl -fsSL https://get.docker.com/rootless | sh
$ mkdir -p ~/.config/systemd/user/docker.service.d
$ cat > ~/.config/systemd/user/docker.service.d/pasta.conf <<EOF
[Service]
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_NET=pasta"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_FLAGS=--ipv6"
Environment="DOCKERD_ROOTLESS_ROOTLESSKIT_PORT_DRIVER=implicit"
EOF
$ systemctl --user daemon-reload
$ systemctl --user restart docker

動作確認

コンテナの起動

Docker ComposeでUbuntuコンテナを起動します。

$ cat > compose.yaml <<EOF
services:
  ubuntu:
    image: "ubuntu:24.04"
    command: sleep infinity
    networks:
      - ip6net
networks:
  ip6net:
    enable_ipv6: true
    ipam:
      config:
        - subnet: 2001:db8::/64
EOF
$ docker compose up -d

動作確認

docker compose execでコンテナに入り、必要なパッケージをインストールし動作確認をします。

$ docker compose exec ubuntu bash
root@ab3c11f44d40:/# apt update && apt install -y iproute2 iputils-ping curl

アドレスや経路が設定されており、外のサーバにping6curl -6が通ると思います。

root@ab3c11f44d40:/# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8::2/64 scope global nodad 
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe12:2/64 scope link 
       valid_lft forever preferred_lft forever
root@ab3c11f44d40:/# ip -6 route
2001:db8::/64 dev eth0 proto kernel metric 256 pref medium
fe80::/64 dev eth0 proto kernel metric 256 pref medium
default via 2001:db8::1 dev eth0 metric 1024 pref medium

余談:Rootless Dockerのネットワークネームスペース

ここからは余談です。

インターンレポート: RootlessコンテナのTCP/IP高速化 | by 松本直樹 | nttlabs | Mediumの記事にあるように、Rootless Dockerはネットワークネームスペースが入れ子になっています。ホストとから隔離されたネットワークネームスペースでrootlesskitが動作し、さらにその中の別のネットワークネームスペースでコンテナが動いています。(なおpastaはホストのネットワークネームスペースで動作しています。)

ここではrootlesskitが動作するネットワークネームスペースに入る方法を紹介します。IPv6でうまく通信できずデバッグしたい時に必要になるかもしれません。

lsnsコマンドでネットワークネームスペース一覧を表示し、入りたいネームスペースで動くプロセスのPIDを指定してnsenterコマンドでネットワークネームスペースに入ります。

$ lsns -t net
        NS TYPE NPROCS     PID USER       NETNSID NSFS COMMAND
4026531840 net      25    1869 ozaki-r unassigned      /usr/bin/pipewire
4026533035 net       5 1159554 ozaki-r unassigned      /proc/self/exe --state-dir=/run/user/1000/dockerd-rootless --net=pasta --mtu=1500 --slirp4netn
4026533105 net      24  860887 ozaki-r unassigned      /usr/libexec/polkitd --no-debug
4026533181 net       1 1667631 ozaki-r unassigned      -/usr/bin/fish
4026533252 net       1 3043978 ozaki-r unassigned      sleep infinity
$ sudo nsenter --target 1159554 --net

わかりにくいですが/proc/self/exerootlesskitなので、nsenterには1159554を指定しています。

ip aip -6 routeコマンドでIPアドレスや経路を表示し、ホストのものと比較してみると面白いと思います。

おわりに

Rootless Dockerのコンテナ内からIPv6で外に出るための設定方法について紹介しました。

今回利用したpastaを始め、Rootless Dockerでコンテナ外と通信するためのソフトウェアはとても面白い処理をしているので、興味がある人はその構造や動きを調べてみると良いかもしれません。

Discussion