Linux、Mac、Windowsホストマシンでイメージを使用できるように、/dev/net/tun
デバイスでDockerイメージを作成しようとしています。デバイスはホストのネットワークインターフェイスにアクセスする必要はありません。
--device /dev/net/tun:/dev/net/tun
をdocker run
に渡すことは、Linuxでのみ機能するため、望ましくありません。
コンテナーが起動したら、次のコマンドを実行して手動でデバイスを追加できます。
$ Sudo mkdir /dev/net
$ Sudo mknod /dev/net/tun c 10 200
$ Sudo ip tuntap add mode tap tap
しかし、これらの行をDockerfileに追加すると、エラーが発生します。
Step 35/46 : RUN mkdir /dev/net
---> Running in 5475f2e4b778
Removing intermediate container 5475f2e4b778
---> c6f8e2998e1a
Step 36/46 : RUN mknod /dev/net/tun c 10 200
---> Running in fdb0ed813cdb
mknod: /dev/net/tun: No such file or directory
The command '/bin/sh -c mknod /dev/net/tun c 10 200' returned a non-zero code: 1
ここで重要なのは、docker build
ステップ内からファイルシステムノードを作成していると思いますか?これは可能ですか?
私は、それを必要とするソフトウェアでTUNデバイスをプログラムで作成することによってこれを回避することができました(ほとんどが単体テストです)。プログラムのセットアップで、メジャー/マイナーコード10/200の一時ファイルノードを作成できます。
// Create a random temporary filename. We are not using tmpfile() or the
// usual suspects because we need to create the temp file using mknod(),
// below.
snprintf(tmp_filename_, IFNAMSIZ, "/tmp/ect_%d_%d", Rand(), Rand());
// Create a temporary file node for use as a TUN interface.
// Device 10, 200 is the device code for a TAP/TUN device.
// See https://www.kernel.org/doc/Documentation/admin-guide/devices.txt
int result = mknod(tmp_filename_, S_IFCHR | 0644, makedev(10, 200));
if (result < 0) {
perror("Failed to make temporary file");
}
ASSERT_GE(result, 0);
次に、プログラムのティアダウンで一時ファイルを閉じて削除します。
残っている問題の1つは、このプログラムにはcap_net_admin,cap_net_raw
機能。回避できるもう1つの問題。
/dev
ディレクトリは特別であり、Dockerのビルドステップでは実際に何も置くことができません。 質問56346114への回答 にも記載されています。
どうやら/dev
のデバイスは、データが入っているファイルではなく、プレースホルダー、アドレス、ポインター、アクセスされたときに何かを実行するメモリ内のドライバーコードへのリンクです。メモリ内のそのようなドライバーコードは、Dockerイメージが保持するものではありません。
実際に実行したいアプリをラップする.sh
スクリプトにコマンドラインコードを配置することで、コンテナーでデバイスを作成しました。