除了自动创建的网络,还可以创建自定义网络。Docker提供三种自定义网络驱动: bridge /overlay / macvlan ,其中 overlay 和 macvlan 用于创建跨主机的网络。
注意:建议使用自定义的网络来控制哪些容器可以相互通信,可以自动DNS解析容器名称到IP地址
除了自动创建的网络还可以创建自定义网络。Docker提供三种自定义网络驱动:
bridgeoverlaymacvlan
其中 overlay 和 macvlan 用于创建跨主机的网络。
注意:建议使用自定义的网络来控制哪些容器可以相互通信,可以自动DNS解析容器名称到IP地址
自定义创建bridge网络#
通过 bridge 驱动创建类似于默认的 bridge 网络(自定义网桥中会自己分配ip地址和网关地址)。
创建自定义网桥
[root@centos-01 ~]# docker network create --driver bridge my-net
c62a2e3d6ad5dece71a470cde488ad9c41c24fac9380689f43905ffbd70d4389
[root@centos-01 ~]# brctl show
bridge name bridge id STP enabled interfaces
br-c62a2e3d6ad5 8000.0242ae4b8680 no
docker0 8000.0242cbf135ea no
[root@centos-01 ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
f6524186651f bridge bridge local
ed7ffc7437dd host host local
c62a2e3d6ad5 my-net bridge local
fa66bc1a17f4 none null local看到新增网桥 br-c62a2e3d6ad5, c62a2e3d6ad5 是新建网桥 my-net 的短id,docker network inspect 看下 my-net 的配置信息:
[root@centos-01 ~]# docker network inspect my-net
[
{
"Name": "my-net",
"Id": "c62a2e3d6ad5dece71a470cde488ad9c41c24fac9380689f43905ffbd70d4389",
"Created": "2021-06-18T11:16:55.17530733+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.19.0.0/16",
"Gateway": "172.19.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]这里 172.19.0.0/16 是 Docker 自动分配的IP网段,网关为 172.19.0.1 ,在 my-net 对应的网桥br-c62a2e3d6ad5上
如果想要指定IP网段。只需在创建网段时指定 --subnet 和 -gateway 参数即可,命令如下:
docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.1 my-net容器要使用新的网络,需要在启动时通过 --network 指定:
[root@centos-01 ~]# docker run -d --network=my-net --name nginx nginx
2104ba150f62d9ea552d09b05ccb0b376db10ce054b50908d16361a639826b84查看容器配置:

容器分配到的IP为 172.19.0.2 到目前为止,这里的IP是docker自动从 subnet 中分配的,如果想要指定一个静态IP可以通过 --ip 指定。
这里有个问题需要注意:
[root@centos-01 ~]# docker run -d --network=my-net --ip 172.19.0.110 --name nginx nginx
5506e7ca82c8252727d8e7e4ae2c25ae1e3e5276fcf031112a17702ac4194e77
docker: Error response from daemon: user specified IP address is supported only when connecting to networks with user configured subnets.Docker中只有使用 --subnet 创建的网络才能指定静态IP。因此在使用 docker-compose 或者 docker run 命令创建容器时,如果需要指定可以使用 :
–subnet指定 IP 段–gateway指定网关my-net指定网桥名称
同网桥下容器通信#
nginx1:
[root@centos-01 ~]# docker run -d --name nginx1 --network=my-net nginx
96a448f4c29fef3038abdd91410d7f9264ef3620cb1a80974bcb63694e61953c
[root@centos-01 ~]# docker exec -it nginx1 /bin/bash
root@96a448f4c29f:/# ping 172.19.0.3
PING 172.19.0.3 (172.19.0.3) 56(84) bytes of data.
64 bytes from 172.19.0.3: icmp_seq=1 ttl=64 time=0.175 ms
64 bytes from 172.19.0.3: icmp_seq=2 ttl=64 time=0.052 ms
64 bytes from 172.19.0.3: icmp_seq=3 ttl=64 time=0.044 msnginx2:
[root@centos-01 ~]# docker run -d --name nginx2 --network=my-net nginx
8d47f51c8138e0ef935f3e8a7447c16a655ce21f18e87a0af0bc6e5ea2daaa21
[root@centos-01 ~]# docker exec -it nginx2 /bin/bash
root@8d47f51c8138:/# ping 172.19.0.2
PING 172.19.0.2 (172.19.0.2) 56(84) bytes of data.
64 bytes from 172.19.0.2: icmp_seq=1 ttl=64 time=0.043 ms
64 bytes from 172.19.0.2: icmp_seq=2 ttl=64 time=0.064 ms
64 bytes from 172.19.0.2: icmp_seq=3 ttl=64 time=0.049 ms结果可知:同一网络中的容器、网关之间都是可以通信的。
容器跨网桥通信#
这里有个问题是 my-net 与默认的 bridge 网络是否可以通信,正常来说两个网络属于不同的网桥应该不能通信,测试一下:
[root@centos-01 ~]# docker ps -a
1CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8d47f51c8138 nginx "/docker-entrypoint.…" 32 minutes ago Up 32 minutes 80/tcp nginx2
96a448f4c29f nginx "/docker-entrypoint.…" 32 minutes ago Up 32 minutes 80/tcp nginx1
[root@centos-01 ~]# docker run -d --name nginx3 nginx
220cc3010771f7a3b0c778d4d5668baa860e969e8d5a6cde830290b31dad89fd
[root@centos-01 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
220cc3010771 nginx "/docker-entrypoint.…" 3 seconds ago Up 2 seconds 80/tcp nginx3
8d47f51c8138 nginx "/docker-entrypoint.…" 32 minutes ago Up 32 minutes 80/tcp nginx2
96a448f4c29f nginx "/docker-entrypoint.…" 32 minutes ago Up 32 minutes 80/tcp nginx1
[root@centos-01 ~]# brctl show
bridge name bridge id STP enabled interfaces
br-c62a2e3d6ad5 8000.0242ae4b8680 no veth0a1e1ba
veth1069d0c
docker0 8000.0242cbf135ea no veth3147348
[root@centos-01 ~]# docker inspect nginx3
新建容器 nginx3 但不指定网桥所以会使用默认的 bridge 网络,结果显示 br-c62a2e3d6ad5 上绑定了两个虚拟网卡 veth0a1e1ba 和 veth1069d0c 对应 nginx1 和 nginx2 , docker0 上绑定了 veth3147348 ,对应 ngnix3 ,分配的IP地址是 172.17.0.2 也可以看出来不在一个网段。
[root@centos-01 ~]# docker exec -it nginx1 /bin/bash
root@96a448f4c29f:/# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.结果可知:不同网段的确是 ping 不通的。
思考:“不同的网络如果加上路由是否可以通信”,如果host上对每个网络都有一条路由,同时操作系统上打开了 ip forwarding ,host就成了一个路由器,挂接在不同网桥上的网络就能够相互通信。试试看。
查看路由表:
[root@centos-01 ~]# ip r
default via 192.168.126.67 dev ens33 proto static metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.19.0.0/16 dev br-c62a2e3d6ad5 proto kernel scope link src 172.19.0.1
192.168.126.0/24 dev ens33 proto kernel scope link src 192.168.126.143 metric 100
172.17.0.0/16 和 172..16.0/24 两个网络的路由都定义好了。再看看 ip forwarding :
[root@centos-01 ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1这里看到路由转发也是开启的,条件都满足的情况下为什么还不行呢,再看看 iptables

这里看到原因是因为: iptables DROP掉了网桥 dockero 与 br-c62a2e3d6ad5 之间双向的流量。从规则命名 DOCKER-ISOLATION 可知 docker 在设计上就是要隔离不同的 netwrok, 这里可以通过使用 docker network connect 命令添加一块网卡来实现不同网桥容器通信:
[root@centos-01 ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
220cc3010771 nginx "/docker-entrypoint.…" 34 hours ago Up 34 hours 80/tcp nginx3
8d47f51c8138 nginx "/docker-entrypoint.…" 34 hours ago Up 34 hours 80/tcp nginx2
96a448f4c29f nginx "/docker-entrypoint.…" 34 hours ago Up 34 hours 80/tcp nginx1
[root@centos-01 ~]# docker network connect my-net 220cc3010771 #将nginx3连接到my-net中[root@centos-01 ~]# docker exec -it nginx1 /bin/bash
root@96a448f4c29f:/# ping 172.19.0.4
PING 172.19.0.4 (172.19.0.4) 56(84) bytes of data.
64 bytes from 172.19.0.4: icmp_seq=1 ttl=64 time=0.130 ms
64 bytes from 172.19.0.4: icmp_seq=2 ttl=64 time=0.046 ms
64 bytes from 172.19.0.4: icmp_seq=3 ttl=64 time=0.060 ms此时发现 nginx1 已经可以访问到 nginx3 了。
端口映射#
容器访问外网是通过 iptables 的 SNAT 实现的,docker容器在启动的时候,如果不指定端口映射参数,容器外部无法通过网络访问容器内的网络应用和服务。需要设置端口映射,也可以使用 Dockerfile 文件中的 EXPOSE 指令来配置。
端口映射使用 -p 、 -P 来实现
-p容器内部端口绑定到指定的主机端口-P容器内部端口随机映射到主机的高端口
格式:指定ip:指定宿主机端口:指定容器端口/IP:HOSTPORT:CONTAINERPORT
这适用于将容器端口映射到指定地址的指定端口:
[root@wangpengliang ~]# docker run -it -d -p 127.0.0.1:5000:5000 --name redis redis #将容器的5000端口映射到指定地址127.0.0.1的5000端口上
c2179a906b05e210c42eb6561cf76285f3391e703d5db249a154e06d4d025f28
[root@wangpengliang ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4927cb5dfe67 redis "docker-entrypoint.s…" 49 seconds ago Up 48 seconds 127.0.0.1:5000->5000/tcp, 6379/tcp redis格式:指定ip、宿主机随机端口、指定容器端口 /IP::CONTAINERPORT
这适用于将容器端口映射到指定地址的任意端口:
[root@wangpengliang ~]# docker run -it -d -p 127.0.0.1::5000 --name redis redis #将容器的5000端口映射到指定地址127.0.0.1的任意端口上
c19e6b8f249db67b2f50455d35159f718a1d68e6efd02c106f0148bae14ba496
[root@wangpengliang ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
c19e6b8f249d redis "docker-entrypoint.s…" 2 seconds ago Up 2 seconds 6379/tcp, 127.0.0.1:49153->5000/tcp redis格式:不指定ip、指定宿主机端口、指定容器端口/HOSTPORT:CONTAINERPORT
这适用于将容器指定端口映射到宿主机的指定端口:
[root@wangpengliang ~]# docker run -it -d -p 80:8000 --name redis redis #将容器的8000端口映射到宿主机的80端口上
3ad63ffd90665413e644cd16f2eb7d404fcb14bb509eee05f67e0db8f1c067a4
[root@wangpengliang ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3ad63ffd9066 redis "docker-entrypoint.s…" 5 seconds ago Up 4 seconds 6379/tcp, 0.0.0.0:80->8000/tcp, :::80->8000/tcp redis绑定 UDP 端口#
默认情况下 -p 和 -P 绑定的都是 tcp 协议端口,如果要绑定 udp 协议端口,只能使用 -p 参数,且在最后添加 /udp 字符串。
[root@wangpengliang ~]# docker run -d -p 127.0.0.1:5553:5000/udp jcdemo/flaskapp
6aa30aa070a6e77f0d3f8653df69c654edf6e8bb68cea475aefbc68f6f7f9572绑定多个端口#
多次使用 -p 参数可以映射多个端口。
[root@wangpengliang ~]# docker run -d -p 5552:5000 -p 5551:5001 jcdemo/flaskapp
fa116ae4f5c19d82d9d4f40560c3219c85540a21d88f7fa999b60382ab57524a查看映射端口#
docker port container_ID #容器ID
#结果输出
80/tcp -> 0.0.0.0:800跨主机网络解决方案#
TODO