How-To
Introduction to Docker, Part 3: Networking
This is the third article in a series on Docker. Previously, I walked you through installing a Docker container and downloading/starting images to create one or more run instances of the images. Almost all applications use networking to obtain and transmit information to other applications or the outside world. I showed how I was able to ping my local router from an Alpine Linux instance to verify that it had internet connectivity. However, running ip -a showed that its IP address was different than that of the host on which it was running, and did not come from my local DHCP server. In this article, I will cover how networking works with containers.
Docker has various networking schemes, and if you are going to run and/or manage Docker containers in large-scale production environments, you will want to spend time with the official Docker document on them. In this article, I will just be covering the basics of networking with Docker.
Docker supports various types of networking schemes -- bridge, host, none, macvlan, and overlay -- each of which is designed for a different use case. You can see these by entering:
docker network ls
Bridge Networking
The default networking scheme for Docker containers is bridge. When the dockerd process is started, a bridge network is built, and when new images are instantiated, they will be connected to it. The bridge allows containers to connect to one another and the outside world, but they will have an IP address assigned to it by Docker and use NAT to communicate externally.
As an example, I was able to show the status of the Docker network, instantiate two different Docker Linux instances, show the status of the instances, and show the status of the networking again by entering:
docker network ls
docker run -itd --name Alpine_001 alpine
docker run -itd --name Ubuntu_001 ubuntu
docker ps
docker network ls
I then showed the host names and IP addresses that were assigned to the instances by entering:
docker network inspect bridge | egrep 'Name|IPv4Address'
I attached to the Alpine instance, displayed its host name and IP address, pinged the other Linux instance, and then looked to see if I could resolve the other instance's host name by entering:
docker attach Alpine_001
hostname
ping -c 2 172.17.0.3
nslookup 172.17.0.3
nslookup Ubuntu_001
This told me that, although there was networking on the instance, they didn't have DNS entries.
I was able to ping and do a name lookup for Google.
Bridged networking is a quick way to get internet access to instances; however, it is not recommended for production as they will have DNS names attached to them and programmatic deployment will have issues as the IP address of the instances will not be resolvable.
Host Networking
Unlike bridged networks, host networks use the networking of the host machine; as such, only certain ports will be assigned to the instance, which are most often specific applications. The --network host switch is used to designate a host network when instantiating the image.
I instantiated an Alpine Linux image using the host network by entering:
docker network ls
docker run -itd --network host --name Alpine_006 alpine
The instance showed the same hostname and IP address as the host machine. Obviously, the container having the same IP address as the host machine could cause issues. To overcome these limitations, application images can only expose specific ports; for example, nginx is a highly performant reverse proxy server load balancer, HTTP cache and a web server.
In the example below, I instantiated an image (ngnix) that was designed to work with host networking by entering:
docker run -itd --network host --name nginx_001 nginx
docker ps -a
docker network inspect host | egrep 'Name|IPv4Address'
I entered the host's IP address in the web browser and was presented with the Nginx home web page.
None Networking
Sometimes you will want to have a totally isolated image with access to the internet. The --network no switch can be used to designate this.
In the example below, I instantiated a Linux instance without IP networking access and verified it:
docker run -itd --network none --name Alpine_007 alpine
hostname
ip a
I exited the instance, restarted, and examined it to see if it had an IP address attached to it.
Upon inspecting the "none" network, I could see the instance and also confirm that it didn't have an IP address.
Macvlan Networking
If you want an instance to appear as any other device with its own unique IP address, you can create and use a macvlan network. Using macvlan does come with some cautions, including the fact that the NIC needs to handle promiscuous mode, and that you can consume all the IP addresses or overload your local networking due to the number of instances that you can create.
I created a new macvlan network and listed it by entering:
docker network create -d macvlan --subnet=10.0.0.1/24 --gateway=10.0.0.1 -o parent=enp2s0 MyMacvlan_001
docker network ls
docker network inspect MyMacvlan_001
This created a new macvlan network (MyMacvlan_001) on my home network using the wired interface (enp2s0) on the host.
I created a new Linux instance attached to the macvlan (MyMacvlan_001) with an assigned IP address (10.0.0.43). I displayed the instance's host name and IP address by entering:
docker run -it --network MyMacvlan_001 --ip=10.0.0.43 --name Alpine_011 alpine
hostname
ip a
I checked connectivity to my local router and Google by entering:
Ping -c 2 10.0.0.1
Ping -c 2 google.com
I exited the instance, displayed the active instances, listed the networks, and displayed the macvlan network by entering:
docker ps -a
docker network ls
docker inspect MyMacvlan_001
This showed the subnet and gateway of the macvlan network and indicated that it had a container named Alpine_011 with an IP address of 10.0.0.43.
I stopped and removed the containers. Then, I removed the macvlan network by entering:
docker network rm MyMacvlan_001
Overlay Networking
Not all networking is local to a single host, and in many cases, you will want to span two or more hosts. To facilitate this, Docker has overlay networks that use VXLAN tunnels to pass container traffic seamlessly and transparently between instances running on different hosts.
As this is just a basic primer on Docker, however, we will not be discussing overlay networks.
Conclusion
Below is a summary list of Docker commands used in this article:
Command
|
Notes
|
docker
network ls
|
List the
container networking schemes
|
docker
network inspect bridge | egrep 'Name|IPv4Address'
|
List the
instances that use the bridge network and use grep to display the name of the
instance and IP address of them
|
docker run
-itd --network host --name Alpine_006 alpine
|
Use the host
network with the instance
|
docker run
-itd --network none --name Alpine_007 alpine
|
The instance
will not have any network connectivity
|
docker
network create -d macvlan --subnet=10.0.0.1/24 --gateway=10.0.0.1 -o parent=enp2s0 MyMacvlan_001
|
Create a
macvlan network
|
docker run
-it --network MyMacvlan_001 --ip=10.0.0.43 --name Alpine_011 alpine
|
Use the
macvlan network with the instance
|
docker
network rm MyMacvlan_001
|
Remove the MyMacvlan_001
network
|
Networking is an enabling technology in IT. Docker realizes this and provides various options to meet most situations. For example, it has bridge networking that gives instances their own IP address and allows them to communicate with each other. It also has host networking where the IP address is shared with the instances. For isolated instances, you can specify the "none" network. If you want your container to have a routable IP address, you can use macvlan networking. When deploying containers on multiple nodes, an overlay network can be used.
So far in this series of articles, we have not worried about the persistence of data. In the next article, however, we will remediate this by discussing persistent storage for Docker.
Update: Part 4 is now available here.