5

我正在尝试使用/dev/net/tun设备创建 Docker 映像,以便可以在 Linux、Mac 和 Windows 主机上使用该映像。该设备不需要访问主机的网络接口。

请注意,传递--device /dev/net/tun:/dev/net/tundocker 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步骤中创建一个文件系统节点?这可能吗?

4

2 回答 2

2

/dev目录很特殊,Docker 构建步骤并不能真正将任何内容放在那里。在对问题 56346114 的回答中也提到了这一点。

显然,其中的设备/dev不是包含数据的文件,而是占位符,地址,指针,指向内存中驱动程序代码的链接,在访问时会执行某些操作。内存中的此类驱动程序代码不是 Docker 映像所持有的。

.sh通过将您的命令行代码放在包装我们真正想要运行的应用程序的脚本中,我可以在容器中创建设备。

于 2020-05-30T02:40:59.150 回答
1

我设法通过在需要它的软件中以编程方式创建 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);

然后在程序的拆解中我们关闭并删除临时文件。

剩下的一个问题是该程序仅在以 root 用户身份运行时才有效,因为该程序没有cap_net_admin,cap_net_raw功能。另一个可以解决的烦恼。

于 2019-12-23T22:14:36.280 回答