• Example is a server with Docker and an eth0 interface of 192.168.1.10.
  • When a container is run, different networking options are available, such as:
    docker run --network none nginx
    
  • With the none network, the container is not attached to any network and cannot reach the outside world. Likewise no one from the outside world can reach the container.
  • If you run multiple containers (for example running the above command multiple times), they cannot talk to each other or the outside world.
  • Next is the Host network - the container is attached to the Host’s network.
    • No network isolation between the Host and the container.
    • Can make a web application available on port 80.
    • The command for that is docker run --network host nginx.
    • No need for additional port mapping.
    • If you try to bring up another container that uses the same port, this won’t work (for example running the above command again).
  • Third networking option is the Bridge network - an internal private network on the host is created. The Docker host and containers attach to this.
    • By default, the network has an IP range of 172.17.0.0
    • Each device that connects receives its own internal private address.
    • How does Docker create and manage the network?
      • This bridge network (intentionally has a lowercase b) is created by default when Docker is installed on the host.
      • On the host itself, this bridge network is seen as docker0. This can be seen from the output of the ip link command.
      • When installing Docker, it essentially runs ip link add docker0 type bridge on the host OS.
      • When checking the network on the host with ip link, you’ll see that the docker0 interface is in a DOWN state.
      • The bridge network is like an interface to the host - but a switch to the namespaces or containers within the host.
      • The interface docker0 on the host is assigned an IP of 172.17.0.1/24
      • When a container is created, Docker creates a network namespace for it.
      • To list the namespace, run the ip netns command.
      • There is a hack required to get the ip netns command to list the namespaces created by Docker.
      • For example, ip netns outputs the following: b3123<numbers-letters>
      • If you inspect a Docker container, for example docker inspect 324ghj, you would see the above namespace as part of a larger string of alphanumeric charactersin the SandboxID and SandboxKey sections.
      • You can see this if you run docker network ls
  • How does Docker attach the container from its network namespace to the bridge network?
  • As said before, the container has two network interfaces on each end.
    • Running the ip link command shows the interface attached to the docker0 interface.
    • Run the same command again with ip -n b3123<numbers-letters> link (-n is for showing namespaces).
      • The output then shows the other end of the interface in the container namespace, for example eth0@if8.
      • The container is also assigned an IP, which can be viewed with the ip -n b3123<numbers-letters> addr. In this example, the container is assigned an IP of 172.17.0.3.
        • Can also view this same information by attaching to the container and seeing the information that way.
  • Essentially:
    • Docker creates a namespace and a pair of interfaces.
    • One interface is attached to the container.
    • The other interface is connected to the bridge network.
    • The interface pairs can be identified by their numbers - odd and even.
      • 9 and 10, 7 and 8, 11 and 12 as examples of paired interfaces.
  • Now to focus on Port Mapping
    • For example I want to bring up an nginx web server on port 80.
      • In the current bridge setup, only other containers on the host or the host itself, can access the nginx container.
      • For example, using a simple curl http://172.17.0.3:80 will view the webpage
      • Trying the same curl command outside of the host will not work.
  • In order to allow external users access, Docker provides a port publishing option.
    • When running containers, map port 8080 on the host to port 80 on the container.
    • Example command: docker run -p 8080:80 nginx
      • Any traffic to port 8080 on the Docker host, will be forwarded to port 80 on the container.
    • curl http://192.168.1.10:8080 on the Docker host’s external interface will then provide access to the container on port 80.
  • How does Docker forward traffic from one port to another?
    • A NAT rule is required, an example of how this can be utilised on the host with iptables:
      iptables \
         -t nat \
         -A PREROUTING \
         -j DNAT
         --dport 8080 \
         --to-destination 80
      
  • The rules are appended to the PREROUTING chain.
  • Docker does it the same way:
    iptables \
        -t nat \
        -A DOCKER \
        -j DNAT
        --dport 8080 \
        --to-destination 172.17.0.3:80
    
  • Sets the destination IP to include the container as well.
  • You can see the rules that Docker creates, when you list the rules in iptables with iptables -nvL -t nat

Updated: