Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

docker build - Cannot open TUN/TAP dev /dev/net/tun

Tags:

docker

ubuntu

I'll try build docker image with openvpn connect to HideMyAss VPN. Look at Dockerfile:

FROM ubuntu:16.04

RUN apt-get update
RUN apt-get clean && apt-get -y update && apt-get install -y locales curl
RUN apt-get install -y php apache2 curl openvpn zip unzip bridge-utils
RUN apt-get install nano

RUN mkdir -p /dev/net && \
 mknod /dev/net/tun c 10 200 && \
 chmod 600 /dev/net/tun && \
 cat /dev/net/tun

COPY tcp/Anguilla.TheValley.TCP.ovpn /etc/openvpn
COPY tcp/Angola.Luanda.TCP.ovpn /etc/openvpn
COPY tcp/Belgium.Brussels.TCP.ovpn /etc/openvpn
COPY tcp/pass.txt /etc/openvpn

EXPOSE 8888

RUN openvpn --config /etc/openvpn/Belgium.Brussels.TCP.ovpn

When I try build this code I have an error:

cat: /dev/net/tun: File descriptor in bad state

But if I remove this 2 lines:

cat /dev/net/tun

RUN openvpn --config /etc/openvpn/Belgium.Brussels.TCP.ovpn

than container successfully build and when I enter to him (docker exec) and run command

openvpn --config /etc/openvpn/Belgium.Brussels.TCP.ovpn

then all works fine.

Can somebody help me, why it doesn't work via image building?

like image 463
Serhii R Avatar asked Oct 29 '18 19:10

Serhii R


1 Answers

First of all try to nest Dockerfile instructions to keep the layers up to a minimum (its known best practice)

For example instead of this:

RUN apt-get update
RUN apt-get clean && apt-get -y update && apt-get install -y locales curl
RUN apt-get install -y php apache2 curl openvpn zip unzip bridge-utils
RUN apt-get install nano

Do like so

RUN apt-get update && \
    apt-get clean && apt-get -y update && apt-get install -y locales curl && \
    apt-get install -y php apache2 curl openvpn zip unzip bridge-utils && \
    apt-get install nano

So you will have only one RUN instruction therefore only one RUN layer in build image.

Secondly when you want to add default execution for running container use CMD instead of RUN. The main difference is that RUN is used during build to execute all the steps necessary to build an image and CMD is being executed after the container starts. Default docker entry point is /bin/bash -c but does not have a default command. CMD instruction passes whatever you put there to that entry point. Why am I saying this? Because you want to start openvpn after container startup, not during the build.

The main purpose of a CMD is to provide defaults for an executing container. These defaults can include an executable, or they can omit the executable, in which case you must specify an ENTRYPOINT instruction as well

Maybe silly question but why you need this part?

cat /dev/net/tun

Please try this Dockerfile:

FROM ubuntu:16.04

RUN apt-get update && \
    apt-get clean && apt-get -y update && apt-get install -y locales curl && \
    apt-get install -y php apache2 curl openvpn zip unzip bridge-utils && \
    apt-get install nano && \
    mkdir -p /dev/net && \
    mknod /dev/net/tun c 10 200 && \
    chmod 600 /dev/net/tun

COPY tcp /etc/openvpn

EXPOSE 8888

CMD openvpn --config /etc/openvpn/Belgium.Brussels.TCP.ovpn

!NOTE! There can be only one CMD instruction per Dockerfile.

like image 159
Raoslaw Szamszur Avatar answered Nov 15 '22 07:11

Raoslaw Szamszur