157

I'm a little bit beginner to Docker. I couldn't find any clear description of what this option does in docker run command in deep and bit confused about it.

Can we use it to access the applications running on docker containers without specifying a port? As an example if I run a webapp deployed via a docker image in port 8080 by using option -p 8080:8080 in docker run command, I know I will have to access it on 8080 port on Docker containers ip /theWebAppName. But I cannot really think of a way how --net=host option works.

Ravindu Nirmal Fernando
  • 4,272
  • 4
  • 18
  • 29

4 Answers4

189

After the docker installation you have 3 networks by default:

docker network ls
NETWORK ID          NAME                DRIVER              SCOPE
f3be8b1ef7ce        bridge              bridge              local
fbff927877c1        host                host                local
023bb5940080        none                null                local

I'm trying to keep this simple. So if you start a container by default it will be created inside the bridge (docker0) network.

$ docker run -d jenkins
1498e581cdba        jenkins             "/bin/tini -- /usr..."   3 minutes ago       Up 3 minutes        8080/tcp, 50000/tcp   friendly_bell

In the dockerfile of jenkins the ports 8080 and 50000 are exposed. Those ports are opened for the container on its bridge network. So everything inside that bridge network can access the container on port 8080 and 50000. Everything in the bridge network is in the private range of "Subnet": "172.17.0.0/16", If you want to access them from the outside you have to map the ports with -p 8080:8080. This will map the port of your container to the port of your real server (the host network). So accessing your server on 8080 will route to your bridgenetwork on port 8080.

Now you also have your host network. Which does not containerize the containers networking. So if you start a container in the host network it will look like this (it's the first one):

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                 NAMES
1efd834949b2        jenkins             "/bin/tini -- /usr..."   6 minutes ago       Up 6 minutes                              eloquent_panini
1498e581cdba        jenkins             "/bin/tini -- /usr..."   10 minutes ago      Up 10 minutes       8080/tcp, 50000/tcp   friendly_bell

The difference is with the ports. Your container is now inside your host network. So if you open port 8080 on your host you will acces the container immediately.

$ sudo iptables -I INPUT 5 -p tcp -m tcp --dport 8080 -j ACCEPT

I've opened port 8080 in my firewall and when I'm now accesing my server on port 8080 I'm accessing my jenkins. I think this blog is also useful to understand it better.

lvthillo
  • 28,263
  • 13
  • 94
  • 127
  • 6
    Is it possible to add the option `--net=host` inside a Dockerfile ? – AnirbanDebnath Feb 20 '18 at 14:22
  • 6
    @AnirbanDebnath I don't think it's possible to put it in a dockerfile but since docker v17 you can use it as a parameter for your docker build: `docker build --network=host`. The specified host network for docker build is only for downloading packages that are necessary for building the image. When you want to run your container on the host network you'll still need to define the --network=host option. – lvthillo Feb 20 '18 at 15:12
  • 1
    Yes @AnirbanDebnath, it's allowed in Dockerfile. e.g. In v3 -- `network_mode: "host"` (ref - https://docs.docker.com/compose/compose-file/#network_mode) – Mohnish Nov 07 '20 at 07:33
  • 5
    That's a Docker-Compose file which describes how to run the container. Not a Dockerfile. But indeed, there it is possible and does the same thing as docker run --network=host – lvthillo Nov 08 '20 at 17:53
  • 1
    very well explained. – Anshul Singhal Jun 27 '21 at 15:24
  • @ivthillo - you said it's possible to do inside a Dockerfile, but you didn't explain how. I can't seem to find the answer in a Google search. Can you or can you not do it somehow in a Dockerfile? – Adam Dec 02 '21 at 19:25
  • @Adam, no it's not supported. I believe he stated that quite clearly. – Igwe Kalu Jan 03 '22 at 22:01
  • does `--net=host` also allow the Docker container to access all ports on the host? E.g. I have a different server running on a port `abcd`, and from inside Docker I would like to query it. – axolotl Feb 03 '22 at 22:34
  • Regarding the final sentence of your answer: From **where** did you access port 8080? ***Was this from another machine on the same local network?*** There are potentially 3 machines in play here, and it's not clear from which one you have established a connection to which other one. You have: The docker container, the docker container *host*, and potentially some other machines on your local (or even external, ie internet) network. – FreelanceConsultant Apr 29 '23 at 15:22
86

The --net=host option is used to make the programs inside the Docker container look like they are running on the host itself, from the perspective of the network. It allows the container greater network access than it can normally get.

Normally you have to forward ports from the host machine into a container, but when the containers share the host's network, any network activity happens directly on the host machine - just as it would if the program was running locally on the host instead of inside a container.

While this does mean you no longer have to expose ports and map them to container ports, it means you have to edit your Dockerfiles to adjust the ports each container listens on, to avoid conflicts as you can't have two containers operating on the same host port. However, the real reason for this option is for running apps that need network access that is difficult to forward through to a container at the port level.

For example, if you want to run a DHCP server then you need to be able to listen to broadcast traffic on the network, and extract the MAC address from the packet. This information is lost during the port forwarding process, so the only way to run a DHCP server inside Docker is to run the container as --net=host.

Generally speaking, --net=host is only needed when you are running programs with very specific, unusual network needs.

Lastly, from a security perspective, Docker containers can listen on many ports, even though they only advertise (expose) a single port. Normally this is fine as you only forward the single expected port, however if you use --net=host then you'll get all the container's ports listening on the host, even those that aren't listed in the Dockerfile. This means you will need to check the container closely (especially if it's not yours, e.g. an official one provided by a software project) to make sure you don't inadvertently expose extra services on the machine.

Malvineous
  • 25,144
  • 16
  • 116
  • 151
  • What would be the behavior if multiple containers are started with '--net=host' options? Will requests be forwarded to a random container? – user482594 Aug 09 '20 at 08:29
  • @user482594: They'll all share the same network stack, just like you ran all the programs inside the same container. e.g. if you run two webservers you'll need to make sure they are listening on different ports otherwise the second container will get an error that the port is in use by the first. Incoming traffic will be forwarded to whichever container is listening for it (technically all the `--net=host` containers will see the traffic, but of course only one program at a time can listen on a given port no matter which container you run it in, in this set up). – Malvineous Aug 10 '20 at 07:36
15

Remember one point that the host networking driver only works on Linux hosts, and is not supported on Docker Desktop for Mac, Docker Desktop for Windows, or Docker EE for Windows Server

Suman M
  • 151
  • 1
  • 2
  • 7
    Note also that Docker for Windows/Mac won't warn you that it doesn't work - it just runs the container silently and DOESN'T bind to any local ports. – Marc Dec 15 '21 at 12:56
  • @Marc I have been stuck with the --network host issue in my windows machine for past 2 days.. thanks for your clarfication... – sms Apr 30 '23 at 03:14
6
  1. you can create your own new network like --net="anyname"
  2. this is done to isolate the services from different container.
  3. suppose the same service are running in different containers, but the port mapping remains same, the first container starts well , but the same service from second container will fail. so to avoid this, either change the port mappings or create a network.
Abhishek D K
  • 2,257
  • 20
  • 28
  • 2
    Thanks for mentioning "2. this is done to isolate the (network) services from different container". I truly see value of using other docker network configs (other than `host`) if there's a possibility of running multiple containers on same host. In other cases (where network isolation is not required), I would prefer `--net=host`. – CᴴᴀZ Feb 21 '20 at 08:29