Docker網路管理

本文章內容:

Docker網路管理。

 

1. 列出Docker網路類型

執行docker network ls

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
355a0d93cc67   bridge    bridge    local  #不是物理橋,是NAT橋
b7ac9b974d83   host      host      local
6375f3007dfa   none      null      local

2. 查看Docker網路類型的詳細訊息

執行docker network inspect bridge

[root@localhost ~]# docker network inspect bridge
[
    {
        "Name": "bridge",
        "Id": "355a0d93cc674335c82d34659db98d7cfe539e5142cfc658d7e0ff556ab695c1",
        "Created": "2021-02-19T09:28:30.041562915-05:00",
        "Scope": "local",
        "Driver": "bridge",
        "EnableIPv6": false,
        "IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",  #該bridge的網段
                    "Gateway": "172.17.0.1"  #該bridge的ip
                }
            ]
        },
        "Internal": false,
        "Attachable": false,
        "Ingress": false,
        "ConfigFrom": {
            "Network": ""
        },
        "ConfigOnly": false,
        "Containers": {  #該bridge關聯到的容器
            "639eecef5599146f33ad0494fa09cb3a17add85614b967c73e78198a9bc502cd": {
                "Name": "busybox1",
                "EndpointID": "7214ce5171364918c214ddbdcec0eeb0aeb0c17b16e4a8a8e49c920313ae633b",
                "MacAddress": "02:42:ac:11:00:02",
                "IPv4Address": "172.17.0.2/16",
                "IPv6Address": ""
            },
        },
        "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",  #該bridge的名稱
            "com.docker.network.driver.mtu": "1500"
        },
        "Labels": {}
    }
]

3. 創建封閉式網路容器

執行docker container run --name busybox1 --network none -it busybox:latest

[root@localhost ~]# docker container run --name busybox1 --network none -it busybox      
/ # ifconfig -a
lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

4. 創建橋接式網路容器

執行docker container run --name busybox1 --network bridge -it busybox:latest  #默認就是bridge網路且是NAT橋

[root@localhost ~]# docker container run --name busybox1 --network bridge -it busybox:latest
WARNING: IPv4 forwarding is disabled. Networking will not work.
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:656 (656.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

5. 創建聯盟式網路容器

1. 執行docker container run --name busybox1 -it busybox:latest,然後執行ifconfig看到busybox1容器的ip是172.17.0.2

[root@localhost ~]# docker container run --name busybox1 -it busybox:latest
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:516 (516.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #

2. 執行docker container run --name busybox2 --network container:busybox1 -it busybox:latest,然後執行ifconfig看到容器busybox2容器的ip也是172.17.0.2

[root@localhost ~]# docker container run --name busybox2 --network container:busybox1 -it busybox:latest
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:AC:11:00:02  
          inet addr:172.17.0.2  Bcast:172.17.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:8 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:656 (656.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ #

6. 創建開放式網路容器

1. 執行docker contaienr run --name busybox1 --network host -it busybox:latest  #與宿主機執行ifconfig一樣

[root@localhost ~]# docker container run --name busybox1 --network host -it busybox:latest
/ # ifconfig
docker0   Link encap:Ethernet  HWaddr 02:42:ED:27:3E:42  
          inet addr:172.17.0.1  Bcast:172.17.255.255  Mask:255.255.0.0
          inet6 addr: fe80::42:edff:fe27:3e42/64 Scope:Link
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:144 errors:0 dropped:0 overruns:0 frame:0
          TX packets:154 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:15731 (15.3 KiB)  TX bytes:12815 (12.5 KiB)

ens33     Link encap:Ethernet  HWaddr 00:0C:29:98:00:1A  
          inet addr:192.168.128.228  Bcast:192.168.128.255  Mask:255.255.255.0
          inet6 addr: fe80::12da:f368:4b08:ba51/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:187210 errors:0 dropped:0 overruns:0 frame:0
          TX packets:37918 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:177881154 (169.6 MiB)  TX bytes:5699987 (5.4 MiB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:98 errors:0 dropped:0 overruns:0 frame:0
          TX packets:98 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:8608 (8.4 KiB)  TX bytes:8608 (8.4 KiB)

/ #

2. 宿主機執行ifconfig

[root@localhost ~]# ifconfig
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        inet6 fe80::42:edff:fe27:3e42  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ed:27:3e:42  txqueuelen 0  (Ethernet)
        RX packets 144  bytes 15731 (15.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 154  bytes 12815 (12.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.128.228  netmask 255.255.255.0  broadcast 192.168.128.255
        inet6 fe80::12da:f368:4b08:ba51  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:98:00:1a  txqueuelen 1000  (Ethernet)
        RX packets 187247  bytes 177884280 (169.6 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 37928  bytes 5704255 (5.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 98  bytes 8608 (8.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 98  bytes 8608 (8.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

7. DNAT容器服務(暴露端口)

7.1  -p, --publish list

[root@localhost ~]# docker container run --help
...
  -p, --publish list                   Publish a container's port(s) to the host
...

提示:如果要暴露多個端口的話,-p選項可以使用多次。

7.1.1  -p <containerPort>

將指定的容器端口<containerPort>映射至主機所有地址的一個動態端口。

1. 執行docker container run --name nginx1 -p 80 -d nginx:stable-alpine  #可以發現沒有指定tcp或udp,它會自動判斷的

[root@localhost ~]# docker container run --name nginx1 -p 80 -d nginx:stable-alpine
38f2be99f566f1b74c4778a7531ed77973d7eba03dd8c4abb0c77fdd4e91a862
[root@localhost ~]# docker container ls
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                   NAMES
38f2be99f566   nginx:stable-alpine   "/docker-entrypoint.…"   6 seconds ago   Up 5 seconds   0.0.0.0:49153->80/tcp   nginx1

2. 執行docker container inspect nginx1,查看nginx1容器的ip地址

[root@localhost ~]# docker container inspect nginx1
...
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "355a0d93cc674335c82d34659db98d7cfe539e5142cfc658d7e0ff556ab695c1",
                    "EndpointID": "46ce923e610565d7d0378214bb01f28412b51eda57ae67bb473f5689b862b4b2",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
...

3. 執行docker container port nginx1或iptables -t nat -vnL,查看nginx1容器暴露哪個端口。提示:第1步驟執行docker container ls時就可以看到暴露哪個端口了

[root@localhost ~]# docker container port nginx1   
80/tcp -> 0.0.0.0:49154  #nginx1容器的tcp協議80端口映射到宿主機所有地址的49154端口

or

[root@localhost ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   38  2300 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 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 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    4   288 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         
   12   720 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:49154 to:172.17.0.2:80  #這條規則是加-p選項自動生成的,如果停止容器這條會刪除。0.0.0.0/0是宿主機ip;dpt:49154是暴露的端口;172.17.0.2:80是nginx1容器的服務

4. 執行ip a,查看宿主機ip

[root@localhost ~]# 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:98:00:1a brd ff:ff:ff:ff:ff:ff
    inet 192.168.128.228/24 brd 192.168.128.255 scope global noprefixroute dynamic ens33
       valid_lft 1660sec preferred_lft 1660sec
    inet6 fe80::12da:f368:4b08:ba51/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ed:27:3e:42 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:edff:fe27:3e42/64 scope link 
       valid_lft forever preferred_lft forever
123: veth50387b6@if122: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 72:59:b1:66:c5:79 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::7059:b1ff:fe66:c579/64 scope link 
       valid_lft forever preferred_lft forever

5. 其他主機訪問192.168.128.228:49154

7.1.2  -p <hostPort>:<containerPort>

將容器端口<containerPort>映射至指定的主機端口<hotPort>。

1. 執行docker container run --name nginx1 -p 80:80 -d nginx:stable-alpine  #可以發現沒有指定tcp或udp,它會自動判斷的

[root@localhost ~]# docker container run --name nginx1 -p 80:80 -d nginx:stable-alpine
6f392a5beb037c85147022763b86a66ea87a506a7c485235551e92dca7687370
[root@localhost ~]# docker container ls
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS              PORTS                NAMES
6f392a5beb03   nginx:stable-alpine   "/docker-entrypoint.…"   About a minute ago   Up About a minute   0.0.0.0:80->80/tcp   nginx1

2. 執行docker container inspect nginx1,查看nginx1容器的ip地址

[root@localhost ~]# docker container inspect nginx1
...
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "355a0d93cc674335c82d34659db98d7cfe539e5142cfc658d7e0ff556ab695c1",
                    "EndpointID": "46ce923e610565d7d0378214bb01f28412b51eda57ae67bb473f5689b862b4b2",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
...

3. 執行docker container port nginx1或iptables -t nat -vnL,查看nginx1容器暴露哪個端口。提示:第1步驟執行docker container ls時就可以看到暴露哪個端口了

[root@localhost ~]# docker container port nginx1
80/tcp -> 0.0.0.0:80  #nginx1容器的tcp協議80端口映射到宿主機所有地址的80端口
or
[root@localhost ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 2 packets, 307 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   41  2456 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 2 packets, 307 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 1 packets, 328 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 1 packets, 328 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    4   288 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         
   12   720 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:80 to:172.17.0.2:80  #這條規則是加-p選項自動生成的,如果停止容器這條會刪除。0.0.0.0/0是宿主機ip;dpt:80是暴露的端口;172.17.0.2:80是nginx1容器的服務

4. 執行ip a,查看宿主機ip

[root@localhost ~]# 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:98:00:1a brd ff:ff:ff:ff:ff:ff
    inet 192.168.128.228/24 brd 192.168.128.255 scope global noprefixroute dynamic ens33
       valid_lft 1485sec preferred_lft 1485sec
    inet6 fe80::12da:f368:4b08:ba51/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ed:27:3e:42 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:edff:fe27:3e42/64 scope link 
       valid_lft forever preferred_lft forever
131: vethd8bbd55@if130: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 76:a3:9b:5a:4a:af brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::74a3:9bff:fe5a:4aaf/64 scope link 
       valid_lft forever preferred_lft forever

5. 其他主機訪問192.168.128.228

7.1.3  -p <ip>::<containerPort>

將指定的容器端口<containerPort>映射至主機指定<ip>的動態端口。

1. 執行docker container run --name nginx1 -p 192.168.128.228::80 -d nginx:stable-alpine  #可以發現沒有指定tcp或udp,它會自動判斷的

[root@localhost ~]# docker container run --name nginx1 -p 192.168.128.228::80 -d nginx:stable-alpine
68a226bfb48e7fe59567bc44ec8e21c332e64e50330de8bf131d1dd41c6bb7d5
[root@localhost ~]# docker container ls 
CONTAINER ID   IMAGE                 COMMAND                  CREATED              STATUS              PORTS                           NAMES
68a226bfb48e   nginx:stable-alpine   "/docker-entrypoint.…"   About a minute ago   Up About a minute   192.168.128.228:49155->80/tcp   nginx1

2. 執行docker container inspect nginx1,查看nginx1容器的ip地址

[root@localhost ~]# docker container inspect nginx1
...
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "355a0d93cc674335c82d34659db98d7cfe539e5142cfc658d7e0ff556ab695c1",
                    "EndpointID": "46ce923e610565d7d0378214bb01f28412b51eda57ae67bb473f5689b862b4b2",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
...

3. 執行docker container port nginx1或iptables -t nat -vnL,查看nginx1容器暴露哪個端口。提示:第1步驟執行docker container ls時就可以看到暴露哪個端口了

[root@localhost ~]# docker container port nginx1
80/tcp -> 192.168.128.228:49155  #nginx1容器的tcp協議80端口映射到宿主機192.168.128.228地址的49155端口

or

[root@localhost ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 2 packets, 307 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   41  2456 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 2 packets, 307 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 1 packets, 328 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 1 packets, 328 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    4   288 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         
   12   720 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0           
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            192.168.128.228      tcp dpt:49155 to:172.17.0.2:80  #這條規則是加-p選項自動生成的,如果停止容器這條會刪除。192.168.128.228是宿主機ip;dpt:49155是暴露的端口;172.17.0.2:80是nginx1容器的服務

4. 執行ip a,查看宿主機ip

[root@localhost ~]# 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:98:00:1a brd ff:ff:ff:ff:ff:ff
    inet 192.168.128.228/24 brd 192.168.128.255 scope global noprefixroute dynamic ens33
       valid_lft 1485sec preferred_lft 1485sec
    inet6 fe80::12da:f368:4b08:ba51/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ed:27:3e:42 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:edff:fe27:3e42/64 scope link 
       valid_lft forever preferred_lft forever
131: vethd8bbd55@if130: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 76:a3:9b:5a:4a:af brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::74a3:9bff:fe5a:4aaf/64 scope link 
       valid_lft forever preferred_lft forever

5. 其他主機訪問192.168.128.228:49155

7.1.4  -p <ip>:<hostPort>:<containerPort>

將指定的容器端口<containerPort>映射至主機指定<ip>的端口<hostPort>。

1. 執行docker container run --name nginx1 -p 192.168.128.228:80:80 -d nginx:stable-alpine  #可以發現沒有指定tcp或udp,它會自動判斷的

[root@localhost ~]# docker container run --name nginx1 -p 192.168.128.228:80:80 -d nginx:stable-alpine
3120d1f4b94d4b9c6a8f05a308fee3c68678ba43df5349ca1ef029d30f2fb997
[root@localhost ~]# docker container ls
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                        NAMES
3120d1f4b94d   nginx:stable-alpine   "/docker-entrypoint.…"   4 seconds ago   Up 3 seconds   192.168.128.228:80->80/tcp   nginx1

2. 執行docker container inspect nginx1,查看nginx1容器的ip地址

[root@localhost ~]# docker container inspect nginx1
...
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "355a0d93cc674335c82d34659db98d7cfe539e5142cfc658d7e0ff556ab695c1",
                    "EndpointID": "46ce923e610565d7d0378214bb01f28412b51eda57ae67bb473f5689b862b4b2",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
...

3. 執行docker container port nginx1或iptables -t nat -vnL,查看nginx1容器暴露哪個端口。提示:第1步驟執行docker container ls時就可以看到暴露哪個端口了

[root@localhost ~]# docker container port nginx1
80/tcp -> 192.168.128.228:80  #nginx1容器的tcp協議80端口映射到宿主機192.168.128.228地址的80端口
or
[root@localhost ~]# iptables -t nat -vnL
Chain PREROUTING (policy ACCEPT 2 packets, 307 bytes)
 pkts bytes target     prot opt in     out     source               destination         
   41  2456 DOCKER     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ADDRTYPE match dst-type LOCAL

Chain INPUT (policy ACCEPT 2 packets, 307 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 1 packets, 328 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 1 packets, 328 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    4   288 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         
   12   720 RETURN     all  --  docker0 *       0.0.0.0/0            0.0.0.0/0           
    0     0 DNAT       tcp  --  !docker0 *       0.0.0.0/0            192.168.128.228      tcp dpt:80to:172.17.0.2:80  #這條規則是加-p選項自動生成的,如果停止容器這條會刪除。192.168.128.228是宿主機ip;dpt:80是暴露的端口;172.17.0.2:80是nginx1容器的服務

4. 執行ip a,查看宿主機ip

[root@localhost ~]# 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
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 00:0c:29:98:00:1a brd ff:ff:ff:ff:ff:ff
    inet 192.168.128.228/24 brd 192.168.128.255 scope global noprefixroute dynamic ens33
       valid_lft 1485sec preferred_lft 1485sec
    inet6 fe80::12da:f368:4b08:ba51/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:ed:27:3e:42 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:edff:fe27:3e42/64 scope link 
       valid_lft forever preferred_lft forever
131: vethd8bbd55@if130: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 76:a3:9b:5a:4a:af brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::74a3:9bff:fe5a:4aaf/64 scope link 
       valid_lft forever preferred_lft forever

5. 其他主機訪問192.168.128.228

7.2  -P, --publish-all

如果容器內有多個要暴露的端口,那使用-P選項可以一次暴露,但映射的端口是隨機的。

[root@localhost ~]# docker container run --help
...
  -P, --publish-all                    Publish all exposed ports to random ports...
...

8. 顯示容器的端口映射

[root@localhost ~]# docker container --help
...
  port        List port mappings or a specific mapping for the container
...

1. 執行docker container run --name nginx1 -p 80 -d nginx:stable-alpine

[root@localhost ~]# docker container run --name nginx1 -d -p 80 nginx:stable-alpine
38f2be99f566f1b74c4778a7531ed77973d7eba03dd8c4abb0c77fdd4e91a862
[root@localhost ~]# docker container ls
CONTAINER ID   IMAGE                 COMMAND                  CREATED         STATUS         PORTS                   NAMES
38f2be99f566   nginx:stable-alpine   "/docker-entrypoint.…"   6 seconds ago   Up 5 seconds   0.0.0.0:49153->80/tcp   nginx1

2. 執行docker container port nginx1

[root@localhost ~]# docker container port nginx1   
80/tcp -> 0.0.0.0:49154  #容器的tcp協議80端口映射到宿主機所有地址的49154端口,這是DNAT

9. 修改Docker0橋的網路屬性

1. 執行vim /etc/docker/daemon.json,新增以下黃色部分

[root@localhost ~]# vim /etc/docker/daemon.json 
{
  "registry-mirrors":["https://mirror.baidubce.com"],  #不是最後一行最後要加","
  "bip":"10.0.0.1/16",  #bip:bridge ip
  "dns":["1.1.1.1","8.8.8.8"]  #配置給容器的DNS;最後一行最後不用加","
}

可修改的屬性:bip、fixed-cidr、fixed-cidr-v6、mtu、default-gateway、default-gateway-v6、dns

2. 執行systemctl restart docker.service

[root@localhost ~]# systemctl restart docker.service

3. 執行ifconfig,可看到docker0橋的ip改為10.0.0.1了,netmask、broadcast會自動計算出來

[root@localhost ~]# ifconfig 
docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 10.0.0.1  netmask 255.255.0.0  broadcast 10.0.255.255
        inet6 fe80::42:edff:fe27:3e42  prefixlen 64  scopeid 0x20<link>
        ether 02:42:ed:27:3e:42  txqueuelen 0  (Ethernet)
        RX packets 144  bytes 15731 (15.3 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 154  bytes 12815 (12.5 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.128.228  netmask 255.255.255.0  broadcast 192.168.128.255
        inet6 fe80::12da:f368:4b08:ba51  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:98:00:1a  txqueuelen 1000  (Ethernet)
        RX packets 188786  bytes 178042071 (169.7 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 38731  bytes 5846809 (5.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 98  bytes 8608 (8.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 98  bytes 8608 (8.4 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

4. 執行docker container run --name busybox1 -it busybox:latest,執行ifconfig可看到配置的ip是10.0.0.2,執行cat /etc/resolve可看到DNS是1.1.1.1和8.8.8.8

[root@localhost ~]# docker container run --name busybox1 -it busybox:latest
/ # ifconfig
eth0      Link encap:Ethernet  HWaddr 02:42:0A:00:00:02  
          inet addr:10.0.0.2  Bcast:10.0.255.255  Mask:255.255.0.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:516 (516.0 B)  TX bytes:0 (0.0 B)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

/ # cat /etc/resolv.conf 
search localdomain
nameserver 1.1.1.1
nameserver 8.8.8.8

10. 創建橋

1. 執行docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" mybr0

[root@localhost ~]# docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" mybr0 
3038d5305c9ffc366223c7c0c377d0441dc9a8ac96f837c14dafbf197450b1da

2. 執行docker network ls可看到自創建的mybr0橋

[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
c5aa6b757333   bridge    bridge    local
b7ac9b974d83   host      host      local
3038d5305c9f   mybr0     bridge    local
6375f3007dfa   none      null      local

3. 執行ifconfig可看到"br-3038d5305c9f",3038d5305c9fg是第2步驟的NETWORK ID

[root@localhost ~]# ifconfig
br-3038d5305c9f: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500  #注意:br-3038d5305c9f不要使用ip命令更改其名稱,否則創建容器綁定此網橋會無法識別到,需使用docker network create加上"-o"選項來更改,例如docker network create -d bridge --subnet "172.26.0.0/16" --gateway "172.26.0.1" -o "com.docker.network.bridge.name"="mybr0" mybr0
        inet 172.26.0.1  netmask 255.255.0.0  broadcast 172.26.255.255
        ether 02:42:d4:89:32:20  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

docker0: flags=4099<UP,BROADCAST,MULTICAST>  mtu 1500
        inet 172.17.0.1  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:b6:d9:35:2f  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

ens33: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
        inet 192.168.128.228  netmask 255.255.255.0  broadcast 192.168.128.255
        inet6 fe80::12da:f368:4b08:ba51  prefixlen 64  scopeid 0x20<link>
        ether 00:0c:29:98:00:1a  txqueuelen 1000  (Ethernet)
        RX packets 766  bytes 83389 (81.4 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 474  bytes 94883 (92.6 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10<host>
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 68  bytes 5920 (5.7 KiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 68  bytes 5920 (5.7 KiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

11. 允許Docker服務被外部客戶端訪問

參考資料:https://www.cxyzjd.com/article/qq_21187515/90262324、https://gist.github.com/styblope/dc55e0ad2a9848f2cc3307d4819d819f

Docker服務默認監聽在Unix Socket,文件為/var/run/docker.sock,僅允許本地客戶端訪問,如果要被外部客戶端訪問需要增加監聽在TCP協議的套接字上。

1. 執行ll /var/run/docker.sock,這是Docker服務默認監聽在Unix Socket文件

[root@localhost ~]# ll /var/run/docker.sock
srw-rw----. 1 root docker 0 Feb 19 09:06 /var/run/docker.sock

2. 執行vim /etc/docker/daemon.json,新增以下黃色部分

[root@localhost ~]# vim /etc/docker/daemon.json
{
  "registry-mirrors":["https://mirror.baidubce.com"],
  "hosts":["tcp://0.0.0.0:2375","unix:///var/run/docker.sock"]  #新增這條
}

3. 新增/etc/systemd/system/docker.service.d/override.conf文件,填寫以下內容

[root@localhost ~]# mkdir /etc/systemd/system/docker.service.d    
[root@localhost ~]# vim /etc/systemd/system/docker.service.d/override.conf
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd

4. 重新載入systemd daemon

[root@localhost ~]# systemctl daemon-reload

5. 執行systemctl restart docker.service

[root@localhost ~]# systemctl restart docker.service

6. 執行ss -tnl,可以看到監聽2375端口

[root@localhost ~]# ss -tnl
State      Recv-Q Send-Q                                  Local Address:Port                                                 Peer Address:Port              
LISTEN     0      128                                                 *:22                                                              *:*                  
LISTEN     0      100                                         127.0.0.1:25                                                              *:*                  
LISTEN     0      128                                              [::]:22                                                           [::]:*                  
LISTEN     0      100                                             [::1]:25                                                           [::]:*                  
LISTEN     0      128                                              [::]:2375                                                         [::]:* 

7. 外部客戶端訪問

[root@client ~]# docker -H 192.168.128.228:2375 version
Client:
Version:         1.13.1
API version:     1.26
Package version: 
Go version:      go1.10.3
Git commit:      0be3e21/1.13.1
Built:           Thu Nov 12 15:11:46 2020
OS/Arch:         linux/amd64
Server:
Version:         20.10.6
API version:     1.41 (minimum version 1.12)
Package version: 
Go version:      go1.13.15
Git commit:      8728dd2
Built:           Fri Apr  9 22:43:57 2021
OS/Arch:         linux/amd64
Experimental:    false