docker — container network

I. Overview

The container IP will change every time the Docker container is restarted.

This also means that if containers use IP addresses to communicate, once a container is restarted, the restarted container will no longer be accessible.

The Docker network can solve this problem.

Docker network mainly has the following two functions:

Interconnection and communication between containers and port mapping

When the container IP changes, direct network communication can be carried out through the service name without being affected.

Therefore, as long as the containers are under the same Docker network, they can use the service name for direct access without worrying about restarting.

This is also the most basic and commonly used application scenario of Docker network.

2. Docker network implementation principle

  1. Docker uses Linux bridging to virtualize a docker container bridge (docker0) on the host machine
  2. When docker starts a container, it will assign an IP address to the container based on the network segment of the docker bridge, called Container-IP.
  3. At the same time, the Docker bridge is the default gateway for each container. Because containers in the same host are all connected to the same network bridge, containers can communicate directly through the container's Container-IP.

The docker bridge is virtualized by the host and is not a real network device. It cannot be addressed by the external network, which also means that the external network cannot directly access the container through Container-IP. If the container wants to be accessible from the outside, it can be enabled by mapping the container port to the host (port mapping), that is, when docker run creates the container, pass the -p or -P parameter. When accessing the container, access the container through [Host IP]:[Container Port].

2. Docker’s four network modes

2. Docker’s four network modes

network mode Command specification method describe
bridge –networkbridge On the docker0 virtual bridge, this is also the default network mode
host –network host The container does not create its own network card, configure IP, etc., but uses the host's IP and port.
container –network Container name or id. The newly created container will not create its own network card and configure its own IP. Instead, it will share the IP and port range with a specified container.
none –network none The container has an independent Network namespace, but no network settings are set for it.

If you think –network is too long, you can also use the abbreviation -net, the effect is the same

When the Docker installation is completed, three networks will generally be automatically created:

NETWORK ID          NAME                DRIVER              SCOPE
40547f9137a5        bridge              bridge              local
b40bdb8f0356        host                host                local
0c7f9938f868        none                null                local

You can use the following command to view:

docker network ls

2.1 Bridge mode – bridge

When the Docker service starts, a bridge named docker0 will be created by default (with an internal interface named docker0 on it).

The name of the bridge network is docker0, which connects other physical or virtual network cards at the kernel layer, which puts all containers and local hosts on the same physical network.

Docker will specify the IP address and subnet mask of docker0 by default so that the host and container can communicate with each other through a network bridge.

1) Bridge mode schematic diagram

Insert image description here

2) Bridge mode analysis

Docker uses Linux bridging to virtualize a Docker container bridge (docker0) on the host machine.

Each time Docker starts a container, it will assign an IP address to the container based on the network segment of the Docker bridge.

At the same time, the Docker bridge is the default gateway for each container.

Containers in the same host are all connected to the same network bridge, so that containers can communicate directly through the container's Container-IP.

When docker run creates a container, the default network mode for containers that do not specify a network is bridge, and docker0 is used.

In the host ifconfig, you can see docker0 and the network you created:

eth0, eth1... represents network card one, network card two...
lo represents 127.0.0.1 (localhost)
inet addr represents the IP address of the network card
. Bridge docker0 will create a pair of peer virtual device interfaces: one is called veth, the other is called eth0, Match in pairs.

The bridge mode of the entire host is docker0, similar to a switch with a bunch of interfaces, each interface is called veth.

Create a virtual interface in the local host and the container respectively, and let them communicate with each other (such a pair of interfaces is called a veth pair);

Each container instance also has a network card inside, and each interface is called eth0;

Each veth on docker0 matches eth0 inside a certain container instance, paired in pairs.

2.2 Host mode –host

No network interface is created, and the host's IP address is directly used to communicate with the outside world. No additional NAT conversion is required.

You cannot publish port in host mode.

1) Host mode schematic diagram

Insert image description here

2) Host mode analysis

The container will not get an independent Network Namespace, but will share the same Network Namespace with the host.

The container will not virtualize its own network card but use the host's IP and port.

The container shares the host network IP. The advantage of this is that the external host and the container can communicate directly.

  • Small expansion:

Specify –network=host or -net=host when starting Docker. If -p mapping port is also specified, the following warning will appear:

NARNING: Published ports are discarded when using host network mode

And the parameters set by -p will not play any role. The port number will be based on the host port number, and will be incremented when repeated. You can choose to ignore this warning or use Docker's other network modes, such as --network=bridge

2.3 Container mode –container

1) Container pattern schematic diagram

Insert image description here

2) Container mode analysis

The new container shares a network IP configuration with an existing container rather than with the host.

The newly created container will not create its own network card and configure its own IP, but will share the IP, port range, etc. with a specified container.

In addition to the network, the two containers are isolated in other aspects such as file systems and process lists.

2.4 none mode

In none mode, no network configuration is performed for the Docker container.

In other words, this Docker container has no network card, IP, routing and other information, but only one lo interface.

The lo logo means disabling the network function, that is: 127.0.0.1, which means local loopback

We need to add network cards, configure IP, etc. to the Docker container ourselves.
Insert image description here

3. Commonly used commands

Before learning various Docker network modes, you must first understand the common commands of Docker network.

2.1 View network

docker network ls

2.2 Create a network

# 基础用法
docker network create 网络名称

# 创建网络时是可以添加一系列参数的:
# --driver:驱动程序类型
# --gateway:主子网的IPV4和IPV6的网关
# --subnet:代表网段的CIDR格式的子网
# mynet:自定义网络名称
docker network create --driver=bridge --gateway=192.168.137.1 --subnet=192.168.137.0/16 mynet

When no options are specified, the default –driver (network mode) is also bridge (bridge), but gateway and subnet will be automatically generated.

2.3 View network data sources

docker network inspect 网络名称 

2.4 Connect the container to the specified network

docker network connect 网络名称 容器名称

2.5 Disconnect the container from the network

docker network disconnect 网络名称 容器名称

2.6 Delete all networks that are no longer in use

docker network prune

2.7 Delete one or more networks

docker network rm 网络名称 

4. Usage examples

4.1 Mount the network when creating the container

1) Create a bridge type network

docker network create --driver=bridge --gateway=192.168.137.1 --subnet=192.168.137.0/16 myNet1

2) Specify the network when creating and running the container

docker run --name containerName -p 80:80 -d --network myNet1 myNginx

3) You can disconnect from the network when you don’t want to use it

docker network disconnect myNet1 myNginx

4.2 Connect to new network when container already exists

1) Create a bridge type network

docker network create --driver=bridge --gateway=192.168.137.1 --subnet=192.168.137.0/16 myNet2

2) Connect the container to a new network

# 执行后myNginx容器的网络就变成了myNet2
docker network connect myNet2 myNginx

3) You can disconnect from the network when you don’t want to use it

docker network disconnect myNet2 myNginx

4.3 Use docker-compose to mount the network to a group of containers

There is the following docker-compose.yml file.
Generally speaking, when you use the following command to orchestrate a group of containers, a network will be created by default, and all containers in this group will be added to the network.

docker-compose up -d

This is also the reason why this group of containers can directly use service names to communicate directly.

version: '3'
services:
  nginx:
    image: nginx:alpine
    container_name: nginx-dev
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "80:80"
    volumes:
      - /usr/local/docker/workspace/nginx/html:/usr/share/nginx/html
      - /usr/local/docker/workspace/nginx/conf/nginx.conf:/etc/nginx/conf.d/default.conf
      
  mysql:
    image: mysql:8
    container_name: mysql-dev
    environment:
      - TZ=Asia/Shanghai
      - MYSQL_ROOT_PASSWORD=89225300
      - MYSQL_DATABASE=nacos_config
      - MYSQL_USER=gddst
      - MYSQL_PASSWORD=123456
    ports:
      - "3306:3306"
    volumes:
      - /usr/docker/docker/workspace/mysql/data:/var/lib/mysql
      - /usr/docker/docker/workspace/mysql/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
      - /usr/docker/docker/workspace/mysql/initdb:/docker-entrypoint-initdb.d

But if you want to display the specified network, you can refer to the following configuration:

networks:
  mynet:
    driver: bridge
    ipam:
      config:
        - subnet: "192.168.0.101/16"
          gateway: 192.168.0.100

After configuring the network, you can specify the network to be used under each service. Here is nginx as an example:

version: '3'
services:
  nginx:
    image: nginx:alpine
    container_name: nginx-dev
    environment:
      - TZ=Asia/Shanghai
    ports:
      - "80:80"
    volumes:
      - /usr/local/docker/workspace/nginx/html:/usr/share/nginx/html
      - /usr/local/docker/workspace/nginx/conf/nginx.conf:/etc/nginx/conf.d/default.conf
    networks:
      - mynet
      
networks:
  mynet:
    driver: bridge
    ipam:
      config:
        - subnet: "192.168.0.101/16"
          gateway: 192.168.0.100

In this way, when orchestrating containers, all containers will join the custom network mynet.

5. Docker network port mapping

In Docker, internal network and external network mapping is a very important concept. This article will introduce you how to map intranet and external network in Docker. In Docker, each container has its own IP address. This IP address is used internally within Docker and cannot be directly accessed from the outside. However, in order for applications running within a container to be accessible over the network, we need to map the container's ports.

For intranet mapping, we can use Docker's port mapping function. This function can map the host's port to the container's port, so that the application running in the container can be accessed from the host's network. For example, we can use the following command to map the host's port 8080 to the container's port 80:

docker run -p 8080:80 nginx

This command will start an NGINX container and map its port 80 to the host's port 8080. Now, we can access NGINX running in the container through http://localhost:8080 in the host's browser.

In addition, when performing intranet mapping, we must also pay attention to the firewall inside the container. In some cases, a port needs to be opened inside the container to access the application inside the container . For example, we can use the following command inside the container --expose parameter command to open the port of the container and expose 80
http://<host IP>:80 to access the server running in the container.

6. docker firewall

Docker firewalls are often used to protect applications in Docker containers from malicious attacks. Firewalls maintain application security by filtering incoming and outgoing network traffic. In Docker, firewall-related rules are implemented based on iptables. Therefore, you need to know the relevant knowledge of iptables before using Docker firewall.
The main configuration file daemon.json in Docker firewall.

/etc/docker/daemon.json
/etc/docker/conf.d/daemon.json

In this configuration file, you can define firewall rules and the default behavior of the firewall. Here are some commonly used settings:

{
    "iptables": false,
    "ip-masq": true,
    "iptables-snat": true
}

In the above configuration file, "iptables": false means to turn off iptables, while the other two options are settings to enable the iptables function.

Building a Docker firewall

The steps to build a Docker firewall are as follows:

1. Install iptables

First, you need to install iptables. You can use the following command to install it:

sudo apt-get install iptables

2. Configure iptables rules

Next you need to configure iptables rules to ensure that applications in Docker containers can run safely. Here is a simple iptables rule example:

# 允许从所有地址接受TCP和UDP连接
iptables -A INPUT -p tcp -j ACCEPT
iptables -A INPUT -p udp -j ACCEPT

# 允许从特定地址接受SSH连接
iptables -A INPUT -p tcp -s 192.168.0.1 --dport 22 -j ACCEPT

# 允许从特定地址通过HTTP访问
iptables -A INPUT -p tcp -s 192.168.0.0/24 --dport 80 -j ACCEPT

# 默认设置为DROP
iptables -P INPUT DROP
iptables -P FORWARD DROP

3. Add rules to daemon.json

Before adding rules to the daemon.json file, you need to confirm that the default behavior of the firewall is correct. Normally, it is recommended to use iptables' default behavior of DROP.

Next, you need to add iptables rules to the daemon.json file:

{
    "iptables": true,
    "iptables-forward": true,
    "iptables-default": "DROP",
    "iptables-nat": false,
    "iptables-filter": [
        {
            "name": "allow-all",
            "rule": [
                "-j ACCEPT"
            ],
            "chain": "DOCKER-USER"
        },
        {
            "name": "allow-ssh",
            "rule": [
                "-p tcp --dport 22 -j ACCEPT"
            ],
            "chain": "DOCKER-USER"
        }
    ]
}

In the above configuration file, "iptables": true means turning on iptables, "iptables-default": "DROP" means setting the default behavior of iptables to DROP, and iptables-filter is the iptables rule for Docker containers, corresponding to "allow- There are two rules: "all" and "allow-ssh". The former allows all traffic, while the latter allows SSH connections.

Using Docker Firewall

Using Docker firewall is a very important operation. If used improperly, the application may not run or be attacked. Here are some tips for using Docker firewall:

1. Allow specific ports

If you need to allow a specific port through the Docker firewall, you can use the following command:

iptables -A INPUT -p tcp --dport 80 -j ACCEPT

2. Display rules

You can use the following command to display all iptables rules:

iptables -L

3. Modify the rules

You can use the following command to modify iptables rules:

iptables -R INPUT 1 -p tcp --dport 22 -j DROP

4. Clear rules

You can use the following command to clear all iptables rules:

iptables -F

Maintain and optimize Docker firewall

Maintaining and optimizing your Docker firewall is very important, here are some tips you can use:

1. Regular backup rules

Since iptables rules are very complex, it is recommended to back up the rules regularly to avoid losing data. Rules can be backed up using the following command:

iptables-save > /root/iptables.save

2. Clean up old rules

Since iptables rules are very complex, it is recommended to clean old rules regularly to keep the system healthy. You can use the following command to clean up old rules:

iptables -L --line-numbers | grep DROP | awk '{print$1}' | xargs -I{} iptables -D INPUT {}

3. Compression rules

The more iptables rules there are, the greater the system burden will be. Therefore it is recommended to compress the rules to reduce the burden. The following is a simple example of compression rules:

iptables-save | python -c "import re, sys; chain = ''; iptables = sys.stdin.readlines(); [print(f'{l.strip()}') if 'ACCEPT' in l or '\n' in l else exec(f'chain = re.match(r\'\:([A-Z]+)\', l).group(1)'); print(l.strip()) for l in iptables if l.strip() != '' ]" | iptables-restore

The above are some Docker firewall maintenance and optimization tips, which can help users better maintain the system and optimize iptables rules.

7. Test network port

Method 1, telnet

telnet ip port

Method 2, ssh

SSH is currently a more reliable protocol designed to provide security for remote login sessions and other network services. On Linux, you can use the ssh command to test port connectivity. The specific usage format is as follows:

ssh -v -p port username@ip

Description:
-v debug mode (log will be printed)
-p specifies port
username: login user
ip of remote host: remote host

If the remote host has opened the corresponding port, there will be a successful establishment prompt as shown in the figure below.

Insert image description here

If the remote host does not open the corresponding port, as shown in the figure below
Insert image description here

Method three, curl

Curl is an open source file transfer tool that uses URL syntax to work in command line mode. It can also be used to test the connectivity of the port. Specific usage:

curl ip:port

Note:
ip: is the ip address of the test host
port: is the port, such as 80

If the corresponding port is opened on the remote host, information will be output. If the corresponding port is not opened, there will be no prompt and CTRL+C is required to disconnect. .
Insert image description here

Method 4, wget

Wget is a free tool that automatically downloads files from the Internet. It supports downloading through the three most common TCP/IP protocols: HTTP, HTTPS, and FTP, and can use HTTP proxy. The origin of the name wget is
the combination of "World Wide Web" and "get". It can also be used to test the connectivity of the port. Specific usage:
wget ip:port
description:
ip: is the ip address of the test host
port: is the port, such as 80

If the port does not exist on the remote host, you will always be prompted to connect to the host.
Insert image description here
If a port exists on the remote host, you will see the corresponding information, as shown in the figure below.

Insert image description here

Eight docker container network FAQs

1.Docker container cannot be accessed

The vm host cannot access the container;
the virtual machine curl localhost cannot be accessed;
the port mapping is normal;
then check the kernel version and docker version and there is no problem;
then restart docker including the container, and kill the process. I have tried everything but to no avail;

2. Final solution

systemctl stop docker # 停止docker 服务
pkill docker # 杀掉docker进程
iptables -t nat -F # 清理iptables
ip link set docker0 down # 停止docker0网卡
brctl delbr docker0 # 删除docker0网卡--重点!
systemctl start docker # 启动docker服务

In the end, it turned out that the problem was indeed the docker0 network card, and it was useless to restart the network card without deleting it. It could only be deleted;

おすすめ

転載: blog.csdn.net/tian830937/article/details/132264112