I'm trying to create a Docker image with a /dev/net/tun device so that the image can be used across Linux, Mac and Windows host machines. The device does not need access to the host's network interface.
Note that passing --device /dev/net/tun:/dev/net/tun to docker run is undesirable because this only works on Linux.
Once the container is started, I can manually add the device by running:
$ sudo mkdir /dev/net
$ sudo mknod /dev/net/tun c 10 200
$ sudo ip tuntap add mode tap tap
but when I add these lines to the Dockerfile it results in an error:
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
I believe the crux here is creating a filesystem node from within a docker build step? Is this possible?
I managed to work around this by programmatically creating the TUN device in our software that needs it (which are mostly unit tests). In the setup of the program we can create a temporary file node with major/minor code 10/200:
and then in the tear-down of the program we close and delete the temporary file.
One issue remaining is this program only works when run as the root user because the program doesn't have
cap_net_admin,cap_net_rawcapabilities. Another annoyance that can be worked-around.