如何在Docker容器映像中创建tun接口?

时间:2019-12-23 07:26:12

标签: docker dockerfile tun mknod

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

请注意,将--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步骤中创建文件系统节点?这可能吗?

2 个答案:

答案 0 :(得分:1)

/dev目录是特殊的,并且Docker构建步骤无法真正在此放置任何内容。 answer to question 56346114中也提到了这一点。

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

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

答案 1 :(得分:0)

我设法通过在需要它的软件中以编程方式创建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功能。可以解决的另一种烦恼。