仮想化通信

日本仮想化技術株式会社の公式エンジニアブログ

IPv6チェック用のイメージを作成する

前回は、IPv4/IPv6 Dualstackを設定したKubernetesの環境構築を行いました。

tech.virtualtech.jp

今回は「IPv6チェック用のイメージを作成する」という内容で、書いてみたいと思います。

内容

イメージ作成環境の作成

最終的にはクラスターでアプリケーションサーバーを動かして、IPv4とIPv6アドレスでそのアプリケーションコンテナーにアクセスするのが目標です。

最近よく使うRed Hat UBI 9イメージにはPython 3.9がインストール済みになっており、これを使ってSimple HTTPサーバーを動かせばチェックできるなと思いつき、早速テストに使うイメージをDockerで作ってみることにしました。

イメージを作ったあとに簡易的なチェックを行いたいところですが、現時点のDockerはコンテナーにIPv6アドレスを振る機能はLinuxホストで動くDockerが必要とのことです。

docs.docker.com

手元ではMultipassを利用して、Ubuntu VMでDockerが動くLinux環境を用意しました(もちろん、仮想マシンソフトウェアでVMを作って、その中でDockerを動かす方法でも問題ありません。手間を省力化するためにMultipassを使いました)。

Dockerインストール済みのUbuntuイメージ「docker」を使って、VMを作成するには、次のように実行するだけです。デフォルトのVMスペックでは動作しないので、CPU、メモリ、ストレージを指定しています。

% multipass launch -c2 -m4G -d40G -n docker docker
% multipass shell docker

$ cat /etc/docker/daemon.json  #こんな内容を`daemon.json`に追記
{
  "ipv6": true,
  "fixed-cidr-v6": "2001:db8:1::/64"
}

$ sudo systemctl restart docker

このあと、IPv6でもIPv4のアドレスでもアクセスできるイメージを作る流れで解説していきますが、これはこの作業を始める前に次のブログ記事を拝見したためです。

2年くらい前の記事なのですが、この記事によると当時のNGINXのコンテナイメージはIPv6アドレスでリッスンしてくれなかったようです。

後でわかったのですが、執筆日(2022年9月7日)現在はよく使われるWebサーバーであるNGINXとApache Web Server(httpd)の現在のイメージについては、IPv4,IPv6アドレスともに問題なく利用できるのを手元の環境で確認しています。あえて古いイメージを使わない限りは問題なさそうですが、場合によってはそういうこともありうるので、使うイメージによって事前にチェックが必要かもしれません。

  • docker.io/nginx:stable
  • docker.io/nginx:stable-alpine
  • docker.io/httpd:2.4
  • docker.io/httpd:2.4-alpine

イメージ作成

コンテナのカスタムイメージを作るため、まずは次のようなDockerfileを作成します。 ちょっとテストするだけなので、最小限にしてあります。

FROM docker.io/redhat/ubi9:latest
ENTRYPOINT ["python3", "-m","http.server","--bind","::"]
EXPOSE 8000

このDockerfileを使って、イメージをビルドします。

docker build --compress -t localhost/python-webserver -f Dockerfile .

イメージのテスト

作成したイメージを使って、コンテナを実行してみます。

docker container run -p 58000:8000 -d localhost/python-webserver 

curlを使ってアクセスしてみます。

curl http://127.0.0.1:58000
curl http://[::]:58000

どちらを実行しても同じ結果になるはずです。特にIPv6アドレスでアクセスできない場合は、IPv6オプションの記述に不備があるか環境にIPv6アドレスが設定されていない可能性が考えられます。

$ curl http://[::]:58000
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Directory listing for /</title>
</head>
<body>
<h1>Directory listing for /</h1>
<hr>
<ul>
<li><a href=".dockerenv">.dockerenv</a></li>
<li><a href="afs/">afs/</a></li>
<li><a href="bin/">bin@</a></li>
<li><a href="boot/">boot/</a></li>
<li><a href="dev/">dev/</a></li>
<li><a href="etc/">etc/</a></li>
<li><a href="home/">home/</a></li>
<li><a href="lib/">lib@</a></li>
<li><a href="lib64/">lib64@</a></li>
<li><a href="lost%2Bfound/">lost+found/</a></li>
<li><a href="media/">media/</a></li>
<li><a href="mnt/">mnt/</a></li>
<li><a href="opt/">opt/</a></li>
<li><a href="proc/">proc/</a></li>
<li><a href="root/">root/</a></li>
<li><a href="run/">run/</a></li>
<li><a href="sbin/">sbin@</a></li>
<li><a href="srv/">srv/</a></li>
<li><a href="sys/">sys/</a></li>
<li><a href="tmp/">tmp/</a></li>
<li><a href="usr/">usr/</a></li>
<li><a href="var/">var/</a></li>
</ul>
<hr>
</body>
</html>

コンテナの環境にiprouteパッケージを入れて確認すると、2001:から始まるIPv6アドレスが設定されていることがわかります。

[root@764bb1df55cb /]# ip a s eth0
14: eth0@if15: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 2001:db8:1::242:ac11:2/64 scope global nodad 
       valid_lft forever preferred_lft forever
    inet6 fe80::42:acff:fe11:2/64 scope link 
       valid_lft forever preferred_lft forever

というわけで、DockerコンテナでもIPv6アドレスを使えるようになりました。IPv6アドレスによる外部アクセスは、Dockerホストのブリッジインターフェイスを介してゲートウェイから外に出るので、IPv6接続サービスが提供されていればアクセスできるはずです(おそらく)。