除了自动创建的网络,还可以根据业务需要创建自定义网络。Docker提供三种自定义网络驱动: bridge 、 overlay 和 macvlan , overlay 和 macvlan 用于创建跨主机的网络。
注:建议使用自定义的网络来控制哪些容器可以相互通信,可以自动DNS解析容器名称到IP地址
自定义创建bridge网络
测试通过 bridge 驱动创建类似于默认的 bridge 网络(自定义网桥中会自己分配ip地址和网关地址)
- 创建自定义网桥 ```shell [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` 的配置信息```bash[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 nginx2104ba150f62d9ea552d09b05ccb0b376db10ce054b50908d16361a639826b84
查看容器配置
容器分配到的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 nginx5506e7ca82c8252727d8e7e4ae2c25ae1e3e5276fcf031112a17702ac4194e77docker: 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指定网关-
同网桥下的容器通信
nginx1:
[root@centos-01 ~]# docker run -d --name nginx1 --network=my-net nginx96a448f4c29fef3038abdd91410d7f9264ef3620cb1a80974bcb63694e61953c

[root@centos-01 ~]# docker exec -it nginx1 /bin/bashroot@96a448f4c29f:/# ping 172.19.0.3PING 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 ms64 bytes from 172.19.0.3: icmp_seq=2 ttl=64 time=0.052 ms64 bytes from 172.19.0.3: icmp_seq=3 ttl=64 time=0.044 ms
nginx2:
[root@centos-01 ~]# docker run -d --name nginx2 --network=my-net nginx8d47f51c8138e0ef935f3e8a7447c16a655ce21f18e87a0af0bc6e5ea2daaa21

[root@centos-01 ~]# docker exec -it nginx2 /bin/bashroot@8d47f51c8138:/# ping 172.19.0.2PING 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 ms64 bytes from 172.19.0.2: icmp_seq=2 ttl=64 time=0.064 ms64 bytes from 172.19.0.2: icmp_seq=3 ttl=64 time=0.049 ms
容器跨网桥通信
这里有个问题是
my-net与默认的bridge网络是否可以通信,正常来说两个网络属于不同的网桥应该不能通信,测试一下: ```bash [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
<br />新建容器 `nginx3` 但不指定网桥所以会使用默认的 `bridge` 网络,结果显示 `br-c62a2e3d6ad5` 上绑定了两个虚拟网卡 `veth0a1e1ba` 和 `veth1069d0c` 对应 `nginx1` 和 `nginx2` , `docker0` 上绑定了 `veth3147348` ,对应 `ngnix3` ,分配的IP地址是 `172.17.0.2` 也可以看出来不在一个网段。```bash[root@centos-01 ~]# docker exec -it nginx1 /bin/bashroot@96a448f4c29f:/# ping 172.17.0.2PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
结果可知:不同网段的确是 **ping** 不通的
思考:“不同的网络如果加上路由是否可以通信”,如果host上对每个网络都有一条路由,同时操作系统上打开了 ip forwarding ,host就成了一个路由器,挂接在不同网桥上的网络就能够相互通信。试试看
查看路由表
[root@centos-01 ~]# ip rdefault via 192.168.126.67 dev ens33 proto static metric 100172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1172.19.0.0/16 dev br-c62a2e3d6ad5 proto kernel scope link src 172.19.0.1192.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_forwardnet.ipv4.ip_forward = 1
这里看到路由转发也是开启的,条件都满足的情况下为什么还不行呢,再看看 iptables 
这里看到原因是因为: **iptables** **DROP** 掉了网桥 **dockero** 与 **br-c62a2e3d6ad5** 之间双向的流量。从规则命名 **DOCKER-ISOLATION** 可知 **docker** 在设计上就是要隔离不同的 **netwrok** ,这里可以通过使用 **docker network connect** 命令添加一块网卡来实现不同网桥容器通信
[root@centos-01 ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES220cc3010771 nginx "/docker-entrypoint.…" 34 hours ago Up 34 hours 80/tcp nginx38d47f51c8138 nginx "/docker-entrypoint.…" 34 hours ago Up 34 hours 80/tcp nginx296a448f4c29f 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/bashroot@96a448f4c29f:/# ping 172.19.0.4PING 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 ms64 bytes from 172.19.0.4: icmp_seq=2 ttl=64 time=0.046 ms64 bytes from 172.19.0.4: icmp_seq=3 ttl=64 time=0.060 ms
外部访问容器
容器访问外网是通过 iptables 的 SNAT 实现的,docker容器在启动的时候,如果不指定端口映射参数,容器外部无法通过网络访问容器内的网络应用和服务。需要设置端口映射,也可以使用 Dockerfile 文件中的 EXPOSE 指令来配置。
端口映射使用 **-p** 、 **-P** 来实现
-p容器内部端口绑定到指定的主机端口-P容器内部端口随机映射到主机的高端口IP:HOSTPORT:CONTAINERPORT指定ip:指定宿主机port:指定容器port: 适用于映射到指定地址的指定端口
[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 -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES4927cb5dfe67 redis "docker-entrypoint.s…" 49 seconds ago Up 48 seconds 127.0.0.1:5000->5000/tcp, 6379/tcp redis
IP::CONTAINERPORT
指定ip、未指定宿主机port(随机)、指定容器port:适用于映射到指定地址的任意端口
[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 -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMESc19e6b8f249d redis "docker-entrypoint.s…" 2 seconds ago Up 2 seconds 6379/tcp, 127.0.0.1:49153->5000/tcp redis
HOSTPORT:CONTAINERPORT
未指定ip、指定宿主机port、指定容器port:适用于将容器指定端口指定映射到宿主机的一个端口上(映射所有接口地址)
[root@wangpengliang ~]# docker run -it -d -p 80:8000 --name redis redis #将容器的8000端口映射到宿主机的80端口上3ad63ffd90665413e644cd16f2eb7d404fcb14bb509eee05f67e0db8f1c067a4[root@wangpengliang ~]# docker ps -aCONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES3ad63ffd9066 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/flaskapp6aa30aa070a6e77f0d3f8653df69c654edf6e8bb68cea475aefbc68f6f7f9572
绑定多个端口
多次使用
-p参数可以映射多个端口
[root@wangpengliang ~]# docker run -d -p 5552:5000 -p 5551:5001 jcdemo/flaskappfa116ae4f5c19d82d9d4f40560c3219c85540a21d88f7fa999b60382ab57524a
查看映射端口配置
docker port container_ID #容器ID#结果输出80/tcp -> 0.0.0.0:800
跨主机网络解决方案
TODO
