Networking with Docker

Docker has some pretty nice networking options, from choosing which ports to expose to concurrently running isolated or bridged networks. It's pretty useful to quickly and easily simulate production environments, create better architectures, and increase container exposure on the network front. We'll see different ways to expose ports, create new networks, execute Docker containers inside them, and even have multiple networks per container.

Getting ready

To step through this recipe, you will need the following:

  • A working Docker installation
  • A sample HTTP server binary (sample code included)

How to do it…

To make a container network port available to others, it first needs to be exposed. Consider any service listening on a port not reachable unless properly exposed in the 3:

FROM debian:jessie-slim
COPY src/hello/hello /hello
EXPOSE 8000
ENTRYPOINT ["/hello"]

This service is listening on port 8000, and any other Docker container running on the host can access it, by default on the same network:

# curl -I http://172.17.0.2:8000/
HTTP/1.1 200 OK

However, this service is not available to the host system:

$ curl http://localhost:8000
curl: (7) Failed to connect to localhost port 8000: Connection refused

To make it available to the host system, the container has to be run with an explicit port redirection. It can be option -P to map exposed ports randomly (the port 8000 can be mapped to 32768 on the local machine), or the other option -p 8000:8000 to make it fixed:

$ docker run -ti --rm -P --name hello hello 

On another terminal, find the port redirection:

$ docker port hello
8000/tcp -> 0.0.0.0:32771

Also, try to connect to it:

$ curl -I http://localhost:32771/
HTTP/1.1 200 OK

These are the basics of networking with Docker containers.

Docker networks

Containers can also live inside dedicated networks for added security and isolation. To create a new Docker network, just give it a name:

$ docker network create hello_network
d01a3784dec1ade72b813d87c1e6fff14dc1b55fdf6067d6ed8dbe42a3af96c2

Grab some information about this network using the docker network inspect command:

$ docker network inspect hello_network -f '{{json .IPAM.Config }}'
[{"Subnet":"172.18.0.0/16","Gateway":"172.18.0.1/16"}]

This is a new subnet: 172.18.0.0/16 (in this case).

To execute a container in this specific Docker network, use the --network <docker_network_name> option like this:

$ docker run -it --rm --name hello --network hello_network hello

Confirm this container is in the 172.18.0.0/16 network space from the hello_network network:

$ docker inspect --format '{{json .NetworkSettings.Networks.hello_network.IPAddress }}' hello
"172.18.0.2"

This container will be protected from unauthorized access from any container not running on the correct network. Here's an example from a container running in the default network:

# curl -I --connect-timeout 5 http://172.18.0.2:8000/
curl: (28) Connection timed out after 5003 milliseconds 

However, connecting from a container in the same network is allowed and working as expected:

# curl -I http://hello:8000/
HTTP/1.1 200 OK

Connecting multiple networks for one container

It can be useful to have a few specific containers available on more than one network; proxies, internal services, and other similar services can face different networking configurations. A single Docker container can connect multiple Docker networks. Take this simple HTTP service listening on port 8000 and launch it on the default bridged network:

$ docker run -ti --rm --name hello hello

This service is now available to any other container on the default network:

# curl -I http://172.17.0.2:8000/
HTTP/1.1 200 OK

However, we'd like it to be also available on the hello_network Docker network. Let's connect them to the host:

$ docker network connect hello_network hello

The container now has a new network interface in the hello_network subnet:

$ docker exec -it hello ip addr
[...]
116: eth0@if117: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.2/16 scope global eth0
[...]
118: eth1@if119: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff
    inet 172.18.0.2/16 scope global eth1
[...]

This means that it's also available to answer requests from containers on this network!

$ curl http://hello:8000
Hello world

We'll eventually remove the link to the original network after we're done with it:

$ docker network disconnect bridge hello
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.21.97.61