Docker Networking Basics
The four basic resources of virtualization are CPU, memory, storage and network connection. In this chapter, we go through the various network solutions that are technically available and which solutions are recomended for software developers to implement in their work environment.
Types of Docker networks
Host contained networks
default bridge
The default network driver that will be created when docker installs on the system. All containers get an internal IP address and these containers can access each other, using this internal IP. Default bridge will not support container DNS resolving. For that you need User-defined bridge
User-defined bridge
networks are best when you need multiple containers to communicate on the same Docker host. Support for internal container DNS resolving
Host networks
are best when the network stack should not be isolated from the Docker host, but you want other aspects of the container to be isolated. Good chose for network or VPN solution. Unfortunately Host networks will not work on Windows computers.
none
disable all networking. Usually used in conjunction with a custom network driver or container that don’t need network access.
Solutions that require network device management
Overlay networks
are best when you need containers running on different Docker hosts to communicate, or when multiple applications work together using swarm services.
Macvlan networks
are best when you are migrating from a VM setup or need your containers to look like physical hosts on your network, each with a unique MAC address.
https://medium.com/edureka/docker-networking-1a7d65e89013 && https://docs.docker.com/network/ && https://docs.docker.com/network/bridge/
Docker Networking practice
In this lab you’ll look at the most basic networking components that come with a fresh installation of Docker.
You will complete the following steps as part of this lab.
- Step 1 - The
docker network
command - Step 2 - List networks
- Step 3 - Inspect a network
- Step 4 - List network driver plugins
- Step 5: Connect a container
- Step 6: Test network connectivity
- Step 7: Configure NAT for external connectivity
- Step 8: Configure User user-defined bridges
- Step 9: Configure Host network (only on Linux machines)
Step 1: The docker network
command
The docker network
command is the main command for configuring and managing container networks.
Run a simple docker network
command from any of your lab machines.
$ docker network
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
The command output shows how to use the command as well as all of the docker network
sub-commands. As you can see from the output, the docker network
command allows you to create new networks, list existing networks, inspect networks, and remove networks. It also allows you to connect and disconnect containers from networks.
Step 2: List networks
Run a docker network ls
command to view existing container networks on the current Docker host.
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
1befe23acd58 bridge bridge local
726ead8f4e6b host host local
ef4896538cc7 none null local
The output above shows the container networks that are created as part of a standard installation of Docker.
New networks that you create will also show up in the output of the docker network ls
command.
You can see that each network gets a unique ID
and NAME
. Each network is also associated with a single driver. Notice that the “bridge” network and the “host” network have the same name as their respective drivers.
Step 3: Inspect a network
The docker network inspect
command is used to view network configuration details. These details include; name, ID, driver, IPAM driver, subnet info, connected containers, and more.
Use docker network inspect
to view configuration details of the container networks on your Docker host. The command below shows the details of the network called bridge
.
$ docker network inspect bridge
[
{
"Name": "bridge",
"Id": "1befe23acd58cbda7290c45f6d1f5c37a3b43de645d48de6c1ffebd985c8af4b",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
}
]
},
"Internal": false,
"Containers": {},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
NOTE: The syntax of the
docker network inspect
command isdocker network inspect <network>
, where<network>
can be either network name or network ID. In the example above we are showing the configuration details for the network called “bridge”. Do not confuse this with the “bridge” driver.
Step 4: List network driver plugins
The docker info
command shows a lot of interesting information about a Docker installation.
Run a docker info
command on any of your Docker hosts and locate the list of network plugins.
$ docker info
Client:
Context: default
Debug Mode: false
Plugins:
buildx: Docker Buildx (Docker Inc., v0.8.2)
compose: Docker Compose (Docker Inc., v2.7.0)
extension: Manages Docker extensions (Docker Inc., v0.2.8)
sbom: View the packaged-based Software Bill Of Materials (SBOM) for an image (Anchore Inc., 0.6.0)
scan: Docker Scan (Docker Inc., v0.17.0)
Server:
Containers: 1
Running: 0
Paused: 0
Stopped: 1
Images: 5
Server Version: 20.10.17
Storage Driver: overlay2
Backing Filesystem: extfs
Supports d_type: true
Native Overlay Diff: true
userxattr: false
Logging Driver: json-file
Cgroup Driver: cgroupfs
Cgroup Version: 1
Plugins:
Volume: local
Network: bridge host ipvlan macvlan null overlay
Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
Swarm: inactive
Runtimes: io.containerd.runtime.v1.linux runc io.containerd.runc.v2
Default Runtime: runc
Init Binary: docker-init
...
The output above shows the bridge, host, null, and overlay drivers.
Step 5: Connect a container
The bridge network is the default network for new containers. This means that unless you specify a different network, all new containers will be connected to the bridge network.
Create a new container.
$ docker run --name sleeping-ubuntu -dt ubuntu sleep infinity
6dd93d6cdc806df6c7812b6202f6096e43d9a013e56e5e638ee4bfb4ae8779ce
This command will create a new container named sleeping-ubuntu
based on the ubuntu:latest
image and will run the sleep
command to keep the container running in the background. As no network was specified on the docker run
command, the container will be added to the bridge network.
Inspect the bridge network again to see the new container attached to it.
$ docker network inspect bridge
<Snip>
},
"ConfigOnly": false,
"Containers": {
"d74c80f164a64e4d1d13c195ac1f4acdbe78d7aa13bb5ffde25354639cff8812": {
"Name": "sleeping-ubuntu",
"EndpointID": "29ca85f851fcad5bc308a97a82add1072119b075f42bc60156afe27207630a69",
"MacAddress": "02:42:ac:11:00:02",
"IPv4Address": "172.17.0.2/16",
"IPv6Address": ""
}
},
<Snip>
Step 6: Test network connectivity
The output to the previous docker network inspect
command shows the IP address of the new container. In the previous example it is “172.17.0.2” but yours might be different.
Ping the IP address of the container from the shell prompt of your Docker host. Remember to use the IP of the container in your environment.
$ ping 172.17.0.2
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 172.17.0.2: icmp_seq=3 ttl=64 time=0.050 ms
64 bytes from 172.17.0.2: icmp_seq=4 ttl=64 time=0.049 ms
64 bytes from 172.17.0.2: icmp_seq=5 ttl=64 time=0.049 ms
^C
--- 172.17.0.2 ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 3999ms
rtt min/avg/max/mdev = 0.049/0.053/0.069/0.012 ms
Press Ctrl-C
to stop the ping. The replies above show that the Docker host can ping the container over the bridge network.
Log in to the container, install the ping
program and ping Yle.fi
.
# Get the ID of the container started in the previous step.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
6dd93d6cdc80 ubuntu "sleep infinity" 5 mins Up sleeping-ubuntu
# Exec into the container
$ docker exec -it 6dd93d6cdc80 /bin/bash
# Update APT package lists and install the iputils-ping package
root@6dd93d6cdc80:/# apt update
apt install iputils-ping
# Ping yle.fi from within the container
root@6dd93d6cdc80:/# ping yle.fi
PING yle.fi (108.156.22.49) 56(84) bytes of data.
64 bytes from 108.156.22.49 (108.156.22.49): icmp_seq=1 ttl=37 time=28.5 ms
64 bytes from 108.156.22.49 (108.156.22.49): icmp_seq=2 ttl=37 time=32.2 ms
64 bytes from 108.156.22.49 (108.156.22.49): icmp_seq=3 ttl=37 time=34.4 ms
64 bytes from 108.156.22.49 (108.156.22.49): icmp_seq=4 ttl=37 time=33.1 ms
^C
--- yle.fi ping statistics ---
7 packets transmitted, 7 received, 0% packet loss, time 6009ms
rtt min/avg/max/mdev = 28.516/33.495/42.324/4.141 ms
This shows that the new container can ping the internet and therefore has a valid and working network configuration.
Step 7: Configure NAT for external connectivity
In this step we’ll start a new NGINX container and map port 8080 on the Docker host to port 80 inside of the container. This means that traffic that hits the Docker host on port 8080 will be passed on to port 80 inside the container.
NOTE: If you start a new container from the official NGINX image without specifying a command to run, the container will run a basic web server on port 80.
Start a new container based off the official NGINX image.
$ docker run --name web1 -d -p 8080:80 nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
386a066cd84a: Pull complete
7bdb4b002d7f: Pull complete
49b006ddea70: Pull complete
Digest: sha256:9038d5645fa5fcca445d12e1b8979c87f46ca42cfb17beb1e5e093785991a639
Status: Downloaded newer image for nginx:latest
b747d43fa277ec5da4e904b932db2a3fe4047991007c2d3649e3f0c615961038
Check that the container is running and view the port mapping.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b747d43fa277 nginx "nginx -g 'daemon off" 3 seconds ago Up 2 seconds 443/tcp, 0.0.0.0:8080->80/tcp web1
6dd93d6cdc80 ubuntu "sleep infinity" About an hour ago Up About an hour sleeping-ubuntu
There are two containers listed in the output above. The top line shows the new web1 container running NGINX. Take note of the command the container is running as well as the port mapping - 0.0.0.0:8080->80/tcp
maps port 8080 on all host interfaces to port 80 inside the web1 container. This port mapping is what effectively makes the containers web service accessible from external sources (via the Docker hosts IP address on port 8080).
Now that the container is running and mapped to a port on a host interface you can test connectivity to the NGINX web server.
Point your web browser to the IP and port 8080 of your Docker host. The following example shows a web browser pointed to localhost:8080
. You can also open webpage using Docker Desktop.
If for some reason you cannot open a session from a web browser, you can connect from your Docker host using the curl
command.
$ curl 127.0.0.1:8080
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<Snip>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>
If you try and curl the IP address on a different port number it will fail.
NOTE: The port mapping is actually port address translation (PAT).
Step 8: Configure User user-defined bridges
So far in the exercises, we have used the default network connection, which has been sufficient for the exercises. However, from the point of view of data security, it is important to isolate different containers from each other if it is not necessary for the containers to talk to each other.
In addition, in user-defined networks, containers can use the names of other containers for DNS addressing, which enables working connections even if the containers’ IP space changes. DNS service is critical when we use several different docker containers to form a single service entity, such as a WWW server and Mysql databases
Lets create a user-defined bridge network named
docker network create my-nginx
Lets create and start the container. We will start it as a detached process. The -d flag means to start the container detached (in the background). The –rm option means to remove the container once it exits/stops. The -p forwards container 80 port to host 8080 port.
docker run --name my-nginx --network my-net -d --rm -p 8080:80 nginx:latest
Next we will stop Step 6 sleeping-ubuntu container if it still running. If you have already stopped it you can skip to docker network command.
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
6dd93d6cdc80 ubuntu "sleep infinity" 5 mins Up sleeping-ubuntu
$ docker stop 6dd93d6cdc80
We will transfer sleeping-ubuntu
container from default network to your new user define network, start it and inspect the my-net network for successful connection
$ docker network connect my-net sleeping-ubuntu
$ docker start sleeping-ubuntu
$ docker network inspect my-net
<Snip>
"Name": "my-nginx",
"EndpointID": "7f69cd1f607744cb38122ad6e884e2fd5dd0d1fdb3f66e01e7c697f70020e7e2",
"MacAddress": "02:42:ac:13:00:02",
"IPv4Address": "172.19.0.2/16",
"IPv6Address": ""
},
"cea4adb35d4d107b531ea9add3884b2250173268afc786ee6c32683cf06eba8a": {
"Name": "sleeping-ubuntu",
"EndpointID": "da9266a37c8a5d05d2ea74b3d90826fa3ff5f80f9c80740aadbc1b2f6912bd1c",
"MacAddress": "02:42:ac:13:00:03",
"IPv4Address": "172.19.0.3/16",
"IPv6Address": ""
}
<Snip>
Exec into the container to log in and install the ping
program if needed.
$ docker exec -it sleeping-ubuntu /bin/bash
Lets ensure that traffic between containers and DNS names work using the ping command
$ root@6dd93d6cdc80:/# ping my-nginx
PING my-nginx (172.19.0.2) 56(84) bytes of data.
64 bytes from my-nginx.my-net (172.19.0.2): icmp_seq=1 ttl=64 time=0.094 ms
64 bytes from my-nginx.my-net (172.19.0.2): icmp_seq=2 ttl=64 time=0.056 ms
64 bytes from my-nginx.my-net (172.19.0.2): icmp_seq=3 ttl=64 time=0.044 ms
64 bytes from my-nginx.my-net (172.19.0.2): icmp_seq=4 ttl=64 time=0.064 ms
64 bytes from my-nginx.my-net (172.19.0.2): icmp_seq=5 ttl=64 time=0.067 ms
64 bytes from my-nginx.my-net (172.19.0.2): icmp_seq=6 ttl=64 time=0.052 ms
This shows that the container can talk to each other and have a valid connect to the internet. If you want to see my-nginx webpage install curl package using apt install curl
and curl my-nginx
To remove user define network you have to stop containers then remove them from network.
$ docker network disconnect my-net my-nginx
$ docker network disconnect my-net sleeping-ubuntu
$ docker network rm my-net
Step 9: Configure Host network (only on Linux machines)
Host network setting can not be run in Windows + Docker Desktop environment because Windows network stack is incompatible to Docker host settings. You can this settings with Linux host using HAMK lab environments or your own linux servers
Lets create and start the container. We will start it as a detached process. The -d flag means to start the container detached (in the background).
$ docker run -d --network host --name hello_nginx nginxdemos/hello
Point your web browser to the IP and port 80 of your Docker host. The following example shows a web browser pointed to localhost:80
. You can also open webpage using Docker Desktop. You will see a basic information of the container.
Server address: 172.17.0.2:80
Server name: ac7bfe9a3569
Date: 30/Aug/2022:09:53:11 +0000
URI: /
To remove the container and free up port 80 we need to stop container. Container will be removed automatically because of –rm option.
$ docker container stop hello_nginx
https://docs.docker.com/get-started/docker_cheatsheet.pdf