Docker 网络配置
Docker 网络
docker网络从覆盖范围可分文单个host上的容器网络和跨多个host的网络。
docker安装时会自动在host创建三个网络
[root@localhost ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
91f24d00be88 bridge bridge local
ecda711e303a host host local
18bdb4a24230 none null local
none网络
none网络就是什么都没有的网络。除了lo,没有任何其他网卡。容器创建时,可以通过- -network=none指定none网络。
[root@localhost ~]# docker run -it --network=none centos7:latest /bin/bash
封闭意味着隔离,一些对安全性要求高并且不需要联网的应用可以使用none网络。
host网络
连接到host网络的容器会共享Docker host的网络,容器的网络配置与host完全一样,连主机名也一样,可以通过- -network=host指定。
[root@localhost ~]# docker run -it --network=host centos7:latest /bin/bash
直接使用host网络的好处就是性能,如果容器对网络传输效率有较高要求。则可以选择host网络。不便之处就是缺乏灵活性,有端口冲突问题。
docker host的另一个用途是让容器可以直接配置host网络,。比如某些跨host的网络解决方案,其本身也是以容器方式运行的,这些方案需要对网络进行配置,比如管理iptables。
bridge网络
Docker 安装时会创建一个命名为docker0的linux bridge。如果不指定- -network,创建的容器默认都会挂在docker0上。
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02426206accb no
virbr0 8000.5254008f7f41 yes virbr0-nic
当前docker0上没有任何其他网络设备,创建一个容器看看变化
[root@localhost ~]# docker run -d centos7
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.02426206accb no veth4e9b21e
virbr0 8000.5254008f7f41 yes virbr0-nic
一个新的网络接口veth4e9b21e被挂在了docker0上,其就是新建容器的虚拟网卡。
bridge还会自动分配网段和网关
[root@localhost ~]# docker network inspect bridge
[
{
"Name": "bridge",
"Id": "91f24d00be88e2536da2a391a1d9b2cff4cd7d0bbe4e9c953016a246481818f8",
"Created": "2020-05-31T12:59:14.229408704+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.17.0.0/16",
"Gateway": "172.17.0.1"
容器创建时,docker会自动从这个网段分配一个ip。
自定义容器网络
除了三个自动创建的网络,也可以自定义网络(user-defined)。
Docker 提供三种user-defined网络驱动:bridge,overlay和macvlan。overlay和macvlan用于创建跨主机的网络。
我们可以通过bridge驱动创建默认的bridge网络
[root@localhost ~]# docker network create --driver bridge my_net
a67b27e62fc31468dd04fc9dd9768208de667843f9bfa45b2e9e347a347453cc
查看一下当前host的网络结构变化:
[root@localhost ~]# brctl show
bridge name bridge id STP enabled interfaces
br-a67b27e62fc3 8000.02424a4f47b9 no
docker0 8000.02426206accb no
virbr0 8000.5254008f7f41 yes virbr0-nic
这个br-a67b27e62fc3就是新建的网络my_net
[root@localhost ~]# docker network inspect my_net
[
{
"Name": "my_net",
"Id": "a67b27e62fc31468dd04fc9dd9768208de667843f9bfa45b2e9e347a347453cc",
"Created": "2020-05-31T13:05:33.822662463+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
也会自动分配网段和网关
可以自己指定IP网段
在创建时指定 - -subent 和 - -gateway 参数:
[root@localhost ~]# docker network create --driver bridge --subnet 172.22.16.0/24 --gateway 172.22.16.254 my_net2
容器若要使用新的网络,只需在启动是通过 - -network 指定:
[root@localhost ~]# docker run -it --network=my_net2 centos7:latest /bin/bash
[root@c52c86f5ea27 /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
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
10: eth0@if11: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:16:10:01 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.22.16.1/24 brd 172.22.16.255 scope global eth0
valid_lft forever preferred_lft forever
容器自动分配的一个IP,也可以通过 - -ip 指定一个静态IP。
[root@localhost ~]# docker run -it --network=my_net2 --ip 172.22.16.200 centos7:latest
注:只有使用 - -subent 创建的网络才能指定静态IP
容器间的连通性
两个centos7都挂在 my_net2 上,是互通的。
[root@c7244d87d18e /]# ping 172.22.16.2
PING 172.22.16.2 (172.22.16.2) 56(84) bytes of data.
64 bytes from 172.22.16.2: icmp_seq=1 ttl=64 time=0.069 ms
64 bytes from 172.22.16.2: icmp_seq=2 ttl=64 time=0.065 ms
但是两个bridge不同的是无法互通的
[root@c7244d87d18e /]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
--- 172.17.0.2 ping statistics ---
3 packets transmitted, 0 received, 100% packet loss, time 2000ms
查看host上的路由:
[root@localhost ~]# ip r
default via 192.168.19.254 dev ens33 proto static metric 100
172.17.0.0/16 dev docker0 proto kernel scope link src 172.17.0.1
172.18.0.0/16 dev br-a67b27e62fc3 proto kernel scope link src 172.18.0.1
172.22.16.0/24 dev br-1fc7c0127dd2 proto kernel scope link src 172.22.16.254
192.168.19.0/24 dev ens33 proto kernel scope link src 192.168.19.130 metric 100
192.168.122.0/24 dev virbr0 proto kernel scope link src 192.168.122.1
之间路由是定义好了的,再查看路由转发
[root@localhost ~]# sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
还得看看iptables
[root@localhost ~]# iptables-save
iptables DROP掉了双方之间的流量。
要实现通信,得为容器添加一块my_net2 的网卡
[root@localhost ~]# docker network connect my_net2 2d12563c377
再看一下它的网络配置
[root@2d12563c377e /]# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
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
16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0
valid_lft forever preferred_lft forever
18: eth1@if19: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
link/ether 02:42:ac:16:10:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.22.16.2/24 brd 172.22.16.255 scope global eth1
valid_lft forever preferred_lft forever
容器中新增了一个网卡eth1,分配了 my_net2 的IP,这下可以互通了
容器访问外网
容器是可以访问外网的
[root@c7244d87d18e /]# ping baidu.com
PING baidu.com (39.156.69.79) 56(84) bytes of data.
64 bytes from 39.156.69.79: icmp_seq=1 ttl=127 time=44.0 ms
64 bytes from 39.156.69.79: icmp_seq=2 ttl=127 time=43.4 ms
64 bytes from 39.156.69.79: icmp_seq=3 ttl=127 time=44.3 ms
注:这里外网指的是容器网络以外的网络环境,并非特指internet
外部访问容器
使用端口映射
docker 可将容器对外提供服务的端口映射到host的某个端口,外网通过该端口访问容器
[root@localhost ~]# docker run -d -p 80 httpd
db7047ec271e0170a47a2e8b2ad1a1d66e4d5408b5b4623a7c8aba51d9dc40cf
[root@localhost ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
db7047ec271e httpd "httpd-foreground" 3 seconds ago Up 2 seconds 0.0.0.0:32768->80/tcp fervent_wozniak
[root@localhost ~]# docker port db7047ec271e 80/tcp > 0.0.0.0:32768
[root@localhost ~]# curl 0.0.0.0:32768
<html><body><h1>It works!</h1></body></html>
除了映射动态端口,也可以在 -p 中指定映射到 host 某个特定端口
[root@localhost ~]# docker run -d -p 8080:80 httpd
[root@localhost ~]# curl 0.0.0.0:8080
<html><body><h1>It works!</h1></body></html>