我正在尝试使用/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
步骤中创建文件系统节点?这可能吗?
答案 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
功能。可以解决的另一种烦恼。