Network is the most complex part of virtualization technology, and of course it is also an important part of Docker application. Docker uses Linux's Namespace for resource isolation, which includes network resources, and network isolation is achieved through Network Namespace. A network Namespace provides an independent network environment, including network cards, routing, Iptable rules and so on, which are isolated from other Network Namespace. Generally, Docker containers allocate a separate Network Namespace.
Docker's four network modes:
Host mode: Shared host network, specified using -- net=host
bridge mode: bridge network mode, specified with -- net=bridge
Container mode: Use container network, specify using -- net=container:NAME_or_ID
None mode: No network is specified, specify using -- net=none (default is this option, not specified)
You can use docker networks to view docker network patterns:
[root@centos7 ~]# docker network ls NETWORK ID NAME DRIVER SCOPE 08892cb5e787 bridge bridge local 43fd42bc0f76 host host local 364fc46102ac none null local
host mode:
As mentioned above, Docker isolates the network through Network Namespace, and in general each Docker allocates a separate Network Namespace, but if the host mode is used when the Docker container starts, the container will not acquire a separate Network Namespace, but will share a Network Namespace with the host. Similarly, the container will not virtualize its own network card, configure its own IP, etc., but use the host's IP and port.
The host mode has the following characteristics:
Containers in host mode have no isolated network namespace;
The IP address of the container is the same as that of Docker host.
It is important to note that the port number of the service in the container does not conflict with the port number already used on Docker host.
The host mode can coexist with other modes.
Specific examples:
#Check the host network address [root@centos7 ~]# ifconfig |grep -A1 eth0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.49.40 netmask 255.255.255.0 broadcast 192.168.49.255 #Create a docker container [root@centos7 ~]# docker run -itd --name host-network --network host centos ad59993de7cf910cea4cfa20980968191d5ae7793d4f6018bf1015be16eea536 #Enter the docker container and view the container network address [root@centos7 ~]# docker exec -it host-network /bin/bash [root@centos7 /]# ifconfig eth0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 192.168.49.40 netmask 255.255.255.0 broadcast 192.168.49.255 inet6 fe80::20c:29ff:fe52:f550 prefixlen 64 scopeid 0x20<link> ether 00:0c:29:52:f5:50 txqueuelen 1000 (Ethernet) RX packets 8070 bytes 9993439 (9.5 MiB) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 1548 bytes 138564 (135.3 KiB) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 #Use the inspect command to view the container's network settings [root@centos7 ~]# docker inspect host-network --format='{{json .NetworkSettings.Networks}}' | jq . { "host": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "43fd42bc0f76afeb16dbb847ea5f4d19410cffc1cb870618c318eeb2b1ac0c5c", "EndpointID": "786130e14678b5399e39a5d472a5f9913562d98241f9ffb2969fbffad1d3e028", "Gateway": "", "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "" } }
bridge mode:
The bridge mode is Docker's default network settings, which assigns Network Namespace, IP settings, etc. to each container, and connects the Docker container on the host to a virtual bridge. When Docker server starts, a virtual bridge named docker0 is created on the host, and the Docker container started on the host is connected to the virtual bridge. Virtual bridges work like physical switches, so that all containers on the host are connected to a two-tier network through switches. The next step is to assign IP to the container. Docker will choose a different IP address and subnet from the host to assign to docker0, and the container connected to docker0 will choose an unoccupied IP use from the subnet.
The characteristics of bridge mode:
Use a linux bridge, docker0 by default;
Using veth pairs, one end is in the container's network namespace and the other end is on docker0.
In this mode, Docker Container does not have a public IP because the IP address of the host is not in the same segment as the IP address of veth pair.
Docker uses NAT to bind the port of service monitoring inside the container to one of the ports of the host, so that the network outside the host can actively send network messages to the container.
When accessing services in containers, it is necessary to access the IP of the host and the port of the host.
NAT mode is based on the implementation of three-tier network, so it will definitely affect the transmission efficiency of the network.
Containers have independent and isolated network stacks to facilitate the establishment of communication between networks other than containers and hosts through NAT.
Specific examples:
# Create a container for bridging patterns
[root@centos7 ~]# docker run -itd --name bridge-network -p 8080:80/tcp centos 30919e3ea354ad01233cacfbf580a95b6035eca3e3b3f449dbb50c337e54af6b
# View host docker0 segment
[root@centos7 ~]# ifconfig docker0 |grep -A1 docker0 docker0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.1 netmask 255.255.0.0 broadcast 0.0.0.0
# View Bridge Information
[root@centos7 ~]# brctl show bridge namebridge idSTP enabledinterfaces docker08000.0242a680db7enoveth6e54224 [root@centos7 ~]# ifconfig veth6e54224: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet6 fe80::e8ed:feff:fe31:b60d prefixlen 64 scopeid 0x20<link>
# Go inside the container to view network information
[root@centos7 ~]# docker exec -it bridge-network /bin/bash [root@30919e3ea354 /]# ifconfig |grep -A1 eth0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0 [root@30919e3ea354 /]# exit exit
# Looking at the iptables rules of the host, you can see that there is an additional DPORT forwarding rule in the DOCKER chain
[root@centos7 ~]# iptables -t nat -vnL Chain PREROUTING (policy ACCEPT 106 packets, 7376 bytes) pkts bytes target prot opt in out source destination 4 172 DOCKER all -- * * 0.0.0.0/0 0.0.0.0/0 ADDRTYPE match dst-type LOCAL Chain INPUT (policy ACCEPT 4 packets, 946 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 2 packets, 124 bytes) pkts bytes target prot opt in out source destination 0 0 DOCKER all -- * * 0.0.0.0/0 !127.0.0.0/8 ADDRTYPE match dst-type LOCAL Chain POSTROUTING (policy ACCEPT 2 packets, 124 bytes) pkts bytes target prot opt in out source destination 102 6430 MASQUERADE all -- * !docker0 172.17.0.0/16 0.0.0.0/0 0 0 MASQUERADE tcp -- * * 172.17.0.2 172.17.0.2 tcp dpt:80 Chain DOCKER (2 references) pkts bytes target prot opt in out source destination 0 0 RETURN all -- docker0 * 0.0.0.0/0 0.0.0.0/0 0 0 DNAT tcp -- !docker0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 to:172.17.0.2:80
# Try ping container network on host
[root@centos7 ~]# ping 172.17.0.2 PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data. 64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.042 ms 64 bytes from 172.17.0.2: icmp_seq=2 ttl=64 time=0.060 ms --- 172.17.0.2 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 999ms rtt min/avg/max/mdev = 0.042/0.051/0.060/0.009 ms
# Attempt to access in-container services on the host
[root@centos7 ~]# curl-I http://localhost:8080/ HTTP/1.1 200 OK Date: Fri, 01 Mar 2019 07:28:37 GMT Server: Apache/2.4.6 (CentOS) Last-Modified: Fri, 01 Mar 2019 07:27:22 GMT ETag: "d-58303567354cf" Accept-Ranges: bytes Content-Length: 13 Content-Type: text/html; charset=UTF-8 [root@centos7 ~]# curl -I http://localhost:8080/ curl hello,world.
container mode:
This pattern specifies that the newly created container and an existing container share a Network Namespace rather than the host. The newly created container will not create its own network card, configure its own IP, but share IP, port range, etc. with a specified container. Similarly, the two containers are isolated except for network aspects, such as file systems, process lists, and so on. The processes of the two containers can communicate through the lo network card device.
Specific examples:
# Create a container that specifies that the container uses a bridge-network network network
[root@centos7 ~]# docker run -itd --name container-network --network container:bridge-network centos 39191c944656dd5564bd0c4b2c172a04d64c810117521f6b34e57cfeef377659
# View the network settings of bridge-network container using docker inspect command
[root@centos7 ~]# docker inspect bridge-network --format='{{json .NetworkSettings}}'|jq . { "Bridge": "", "SandboxID": "0e0376642d908c6844ea1b936420e2e69432c09f4fa1e35a95ac735d866ae229", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": { "80/tcp": [ { "HostIp": "0.0.0.0", "HostPort": "8080" } ] }, "SandboxKey": "/var/run/docker/netns/0e0376642d90", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "6df44381183d3af48dbe4d549ebeca2049c9201fec408b0c9525e34623bfaf81", "Gateway": "172.17.0.1", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "MacAddress": "02:42:ac:11:00:02", "Networks": { "bridge": { "IPAMConfig": null, "Links": null, "Aliases": null, "NetworkID": "683b6614154a16dfcf42e6934a9bf2490dd719e4d83c0a1f7d72e1f90b56c432", "EndpointID": "6df44381183d3af48dbe4d549ebeca2049c9201fec408b0c9525e34623bfaf81", "Gateway": "172.17.0.1", "IPAddress": "172.17.0.2", "IPPrefixLen": 16, "IPv6Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "MacAddress": "02:42:ac:11:00:02" } } }
# Use the docker inspect command to view the network settings of the container-network container (output results are similar to those of the host mode container)
[root@centos7 ~]# docker inspect container-network --format='{{json .NetworkSettings}}'|jq . { "Bridge": "", "SandboxID": "", "HairpinMode": false, "LinkLocalIPv6Address": "", "LinkLocalIPv6PrefixLen": 0, "Ports": null, "SandboxKey": "", "SecondaryIPAddresses": null, "SecondaryIPv6Addresses": null, "EndpointID": "", "Gateway": "", "GlobalIPv6Address": "", "GlobalIPv6PrefixLen": 0, "IPAddress": "", "IPPrefixLen": 0, "IPv6Gateway": "", "MacAddress": "", "Networks": {} }
# Go inside the container, look at the ip address of the container and find that it is the same as the bridge-network container.
[root@centos7 ~]# docker exec -it container-network /bin/bash [root@30919e3ea354 /]# ifconfig |grep -A1 eth0 eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.2 netmask 255.255.0.0 broadcast 0.0.0.0
# Note: Because the two containers are sharing a network namespace at this time, we need to pay attention to port conflicts, otherwise the second container will not be able to start.
none mode:
In none mode, the Docker container has its own Network Namespace, but it does not configure any network and construct any network environment for the Docker container.
Docker container uses none network mode, so the container can only use loopback network devices, there will be no other network resources. Docker Container's none network mode means that the container can only use 127.0.0.1 local network without creating any network environment for the container.
User-defined network:
Custom networks can be added to docker by command. Custom networks can be used to configure the network of containers more flexibly. You can control which containers can communicate, which containers can access the host, and even automatically resolve the name of the container to an IP address. You can create as many networks as you need, and you can connect containers to zero or more of these networks at any given time. In addition, you can connect and disconnect the running containers in the network without restarting the containers. When a container is connected to multiple networks, its external connections are provided lexically through the first non-internal network.
Specific examples:
# Create a docker custom network driven by bridge with the name br0
[root@centos7 ~]# docker network create -d bridge br0 4fb906c45b587cecfe9670ed9a62d5b76147c83ab1fe17002d5afeabfece42b4
# View the details of docker custom network br0
[root@centos7 ~]# docker network inspect br0 [ { "Name": "br0", "Id": "4fb906c45b587cecfe9670ed9a62d5b76147c83ab1fe17002d5afeabfece42b4", "Created": "2019-03-02T00:11:26.905361179+08:00", "Scope": "local", "Driver": "bridge", "EnableIPv6": false, "IPAM": { "Driver": "default", "Options": {}, "Config": [ { "Subnet": "172.18.0.0/16", "Gateway": "172.18.0.1" } ] }, "Internal": false, "Attachable": false, "Containers": {}, "Options": {}, "Labels": {} } ]
# View the network card information corresponding to br0 on the host
[root@centos7 ~]# brctl show bridge namebridge idSTP enabledinterfaces br-4fb906c45b588000.02423ff261c3no [root@centos7 ~]# ifconfig br-4fb906c45b58 br-4fb906c45b58: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 inet 172.18.0.1 netmask 255.255.0.0 broadcast 0.0.0.0 ether 02:42:3f:f2:61:c3 txqueuelen 0 (Ethernet) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
# Create two containers that use docker to customize the network
[root@centos7 ~]# docker run -itd --name docker01 --network br0 centos 61638d20c2a2b115e47f0c5fe5a37612613e3e775b8929a74d21d73d1d397e36 [root@centos7 ~]# docker run -itd --name docker02 --network br0 centos f7711bce271687669473368d4a40e37a500e0ed81d468373c0b40ce7930acb70
# Enter docker01 and try to ping another container
[root@centos7 ~]# docker exec -it docker01 /bin/bash [root@61638d20c2a2 /]# ping docker02 PING docker02 (172.18.0.3) 56(84) bytes of data. 64 bytes from docker02.br0 (172.18.0.3): icmp_seq=1 ttl=64 time=0.152 ms 64 bytes from docker02.br0 (172.18.0.3): icmp_seq=2 ttl=64 time=0.054 ms ^C --- docker02 ping statistics --- 2 packets transmitted, 2 received, 0% packet loss, time 1002ms rtt min/avg/max/mdev = 0.054/0.103/0.152/0.049 ms
# Go into docker02 and try to ping another container
[root@centos7 ~]# docker exec -it docker02 /bin/bash [root@f7711bce2716 /]# ping docker01 PING docker01 (172.18.0.2) 56(84) bytes of data. 64 bytes from docker01.br0 (172.18.0.2): icmp_seq=1 ttl=64 time=0.145 ms 64 bytes from docker01.br0 (172.18.0.2): icmp_seq=2 ttl=64 time=0.040 ms 64 bytes from docker01.br0 (172.18.0.2): icmp_seq=3 ttl=64 time=0.065 ms 64 bytes from docker01.br0 (172.18.0.2): icmp_seq=4 ttl=64 time=0.040 ms ^C --- docker01 ping statistics --- 4 packets transmitted, 4 received, 0% packet loss, time 3004ms rtt min/avg/max/mdev = 0.040/0.072/0.145/0.043 ms
Modify the DNS and configuration files of the container:
The same Docker image can start many Docker containers, but the hostname of each container is different, that is, the hostname is not written to the image.
There are three files in the / etc / directory by running mount command in the container. They are / etc/hostname, / etc/hosts, / etc/resolv.conf:
[root@centos7 ~]# docker exec -it bridge-network /bin/bash [root@30919e3ea354 /]# mount ....... /dev/mapper/centos-root on /etc/resolv.conf type ext4 (rw,relatime,data=ordered) /dev/mapper/centos-root on /etc/hostname type ext4 (rw,relatime,data=ordered) /dev/mapper/centos-root on /etc/hosts type ext4 (rw,relatime,data=ordered) ......
Note: The three files are writable inside the container. The configuration can be temporarily validated by modifying the corresponding files, but once the container stops making changes, they will be lost.
Modify DNS and Hostname methods:
The dns and hostname configurations of docker containers can be set by the parameters provided by Docker in the following way:
- h HOSTNAME or - hostname=HOSTNAME: Set the host name of the container, which will be written to / etc/hostname and / etc/hosts files, as well as seen at the container's bash prompt. Externally, however, the host name of the container is not visible and will not appear in the hosts file of other containers, even with the docker ps command. This parameter is the parameter of the docker run command, not the startup parameter of docker daemon.
dns=IP_ADDRESS...: Configure DNS for the container and write it to / etc/resolv.conf. This parameter can be set at docker daemon startup or at docker run by default of 8.8.8.8 or 8.8.4.4.
Note: Modifications to the above three files will not be saved by docker commit, that is, they will not be saved in the mirror, and restarting the container will also cause the modifications to fail.
Pictures taken from: https://www.cnblogs.com/itzgr/p/10179003.html