Before we introduced Network Namespace (netNS) and Veth pair, we said that Docker uses these technologies to achieve Network isolation. Today, we will take a look at how Docker does it.
Start a netless container
First we use –net= None to start a netless container. For debugging purposes, we use a centos image.
docker run -itd --name centos-test --net=none centos
Copy the code
After successful startup, we go inside the container to confirm whether there is no network card.
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
28dc2e8853df centos "/bin/bash" 24 seconds ago Up 23 seconds centos-test
[root@localhost ~]# docker exec -it 28dc2e8853df bash
[root@28dc2e8853df /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
Copy the code
You can see that there is only one loopback network card.
How do I view the Netns corresponding to a Docker?
When the container is started, Docker automatically creates a NetNS inside the container for network isolation, but when we use IP Netns list to view the container, we don’t see any data, because Docker created netns elsewhere. The IP netns list command can read only the data under the /var/run/netns directory.
We can solve this problem by using the following command to facilitate our learning of docker network.
Get the process for the container
pid=docker inspect -f '{{.State.Pid}}' "$container_id"
Create a folder manually to prevent it from not existing
mkdir -p /var/run/netns/
Create a soft connection
ln -s /proc/$pid/ns/net /var/run/netns/$container_id
Copy the code
Modify the above command to match the current environment and verify the network adapter in netNS.
[root@localhost ~]# docker inspect -f '{{.State.Pid}}' "28dc2e8853df"
123624
[root@localhost ~]# mkdir -p /var/run/netns/
[root@localhost ~]# ln -s /proc/123624/ns/net /var/run/netns/28dc2e8853df
[root@localhost ~]# ip netns list
28dc2e8853df
[root@localhost ~]# ip netns exec 28dc2e8853df ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
Copy the code
You can see that we successfully output the nic information in netNS, and this information is consistent with what we see in the Docker container.
Add a nic to docker
Referring to the previous Linux Bridge section, we first create a Bridge, then create a veth pair, one end connected to the Bridge, the other end moved to the Docker corresponding Netns.
Add a bridge
brctl addbr br0
Start the bridge
ip link set br0 up
# Add a pair of veth
ip link add veth0-ns type veth peer name veth0-br
Move one end of the veth to the corresponding Netns of the Docker
ip link set veth0-ns netns 28dc2e8853df
Start local loopback and veth in netns and configure IP
ip netns exec 28dc2e8853df ip link set lo up
ip netns exec 28dc2e8853df ip link set veth0-ns up
ip netns exec 28dc2e8853df ip addr add 10.0.0.1/24 dev veth0-ns
Start the other end of the veth and mount it to the bridge
ip link set veth0-br up
brctl addif br0 veth0-br
Copy the code
Finally, verify the network card information in netNS and Docker containers.
[root@localhost ~]# ip netns exec 28dc2e8853df ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host LO valid_lft forever preferred_lft forever 91: veth0-ns@if90: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 86:29:e6:0a:2a:cb BRD ff:ff:ff:ff:ff:ff :ff link- netnSID 0 inet 10.0.0.1/24 scope global veth0-ns valid_lft forever preferred_lft forever [root@localhost ~]# docker exec -it 28dc2e8853df bash
[root@28dc2e8853df /]# ip a1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000 link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00 inet 127.0.0.1/8 scope host LO valid_lft forever preferred_lft forever 91: veth0-ns@if90: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000 link/ether 86:29:e6:0a:2a:cb BRD ff:ff:ff:ff:ff:ff :ff link- netnSID 0 inet 10.0.0.1/24 scope global veth0-ns valid_lft forever preferred_lft foreverCopy the code
It can be seen that the network card added in NetNS can also be correctly displayed in docker container, thus proving the corresponding relationship between netNS and Docker container. When we use docker command to create containers, Docker hides a lot of details for us, and can easily create containers by using a few commands. However, this way of knowing how and why is not enough for us to master Docker. Only after understanding the underlying principles can we master its functions more deeply.
Understand several network modes of Docker
It is very simple and clear to understand several network modes of Docker after understanding the principle of docker adding network cards. The main difference lies in whether there is an independent NetNS.
Network mode | Introduction to the |
---|---|
bridge | Containers have independentnetns Will connect the container todocker0 Virtual bridge and configure the IP address. The default mode is this. |
host | There are no separate containersnetns And share the network with the host. |
none | Containers have independentnetns , but it does not have any network Settings on it. |
container | The container is shared with an existing containernetns . |
The new version of Docker adds ipvLAN, MACVLAN and Overlay networks, mainly for the isolation and communication of docker containers on multiple host machines. The underlying network is much more complex, which will be introduced separately later.
And don’t forget to clean up your lab environment.
Delete the bridge
ip link del br0
# Delete veth pair
ip link del veth0-br
Delete the soft connection
rm -rf /var/run/netns/28dc2e8853df
# delete container
docker rm 28dc2e8853df -f
Copy the code