一、Docker默认的网络通信
1.1 Docker安装后默认的网络设置
Docker服务器安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡,其IP地址都是172.17.0.1/16
[root@ubuntu1804 ~]#apt -y install bridge-utils
[root@ubuntu1804 ~]#brctl show另外会额外创建三个默认网络,用于不同的使用场景:
root@docker-server1:~# docker network list
NETWORK ID NAME DRIVER SCOPE
438a9be14ef8 bridge bridge local #桥接网络,默认使用的模式,容器基于SNAT进行地址转换访问宿主机以外的环境
4c026356e4d1 host host local #host网络,直接使用宿主机的网络( 不创建net namespace),性能最好,但是容器端口不能冲突
8d70da095b8e none null local #空网络,容器不会分配有效的IP地址(只有一个回环网卡用于内部通信),用于离线数据处理等场景。
1.2 创建容器后的网络配置
每次新建容器后:
宿主机多了一个虚拟网卡,和容器的网卡组合成一个网卡,比如:11: vetha114b5a@if10,而在容器内的网卡名为:10: eth0@if11,可以看出和宿主机的网卡之间的关联。
容器会自动获取一个172.17.0.0/16网段的随机地址,默认从172.17.0.2开始,第二次容器为172.17.0.3,以此类推。
容器获取的地址并不固定,每次容器重启,可能会发生地址变化。
1.3 容器间的通信
默认情况下:同一个宿主机的不同容器可以相互通信
1.4 修改默认网络设置
新建容器默认使用docker0的网络配置,可以修改默认指向自定义的网桥网络
范例:用自定义的网桥代替默认的docker0
新建网桥:brctl addbr docker1
[root@Node2 ~]#:brctl addbr docker1
[root@Node2 ~]#:brctl show
bridge name bridge id STP enabled interfaces
docker0 8000.0242ab0f8bd9 no
docker1 8000.000000000000 no
virbr0 8000.525400d20f75 yes virbr0-nic
仅仅是创建了一个网桥。然后给网桥设置一个IP地址:ip a a 192.168.115.1/24 dev docker1
[root@Node2 ~]#:ip a a 192.168.115.1/24 dev docker1
[root@Node2 ~]#:
[root@Node2 ~]#:ip a
......
12: docker1: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN group default qlen 1000
link/ether fa:da:9a:80:d4:5d brd ff:ff:ff:ff:ff:ff
inet 192.168.115.1/24 scope global docker1
valid_lft forever preferred_lft forever
这样就创建了一个网桥并设置了一个地址:192.168.115.1/24
我们启动容器,让容器使用docker1网桥:
需要修改service文件:vim /usr/lib/systemd/system/docker.service
[root@Node2 ~]#:vim /usr/lib/systemd/system/docker.service
修改了启动命令,在该行后添加-b docker1
重启后,运行一个容器,进入查看IP
由于这里运行的系统容器,不要退出,否则容器关闭了,再开一个终端,查看:brctl show
如果运行的是一个nginx可以后台运行,直接查看网桥:
1.5 修改docker默认的网段
docker0是默认网桥,172.17.0.0/16是默认网段。我们可以指定docker0默认的网段。
这里还是修改docker的service文件。在启动后面添加-bip 192.168.200.1/24。指定IP。
vim /usr/lib/systemd/system/docker.service
在启动命令行加入:--bip 192.168.200.1/24
重新加载service文件,重启docker。
[root@Node2 ~]#:systemctl daemon-reload
[root@Node2 ~]#:systemctl restart docker
[root@Node2 ~]#:ip a
......
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:ab:0f:8b:d9 brd ff:ff:ff:ff:ff:ff
inet 192.168.200.1/24 brd 192.168.200.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:abff:fe0f:8bd9/64 scope link
valid_lft forever preferred_lft forever
12: docker1: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
inet 192.168.115.1/24 scope global docker1
valid_lft forever preferred_lft forever
inet6 fe80::f8da:9aff:fe80:d45d/64 scope link
valid_lft forever preferred_lft forever
可以运行一个容器查看ip:
这样就是我们指定的docker0的网段了。
二、容器名称互联
新建容器时,docker会自动分配容器名称,容器ID和IP地址,导致容器名称,容器ID和IP都不固定,那么如何区分不同的容器,实现和确定目标容器的通信呢?解决方案是给容器起个固定的名称,容器之间通过固定名称实现确定目标的通信。
有两种固定名称:
容器名称
容器名称的别名
2.1 容器名称介绍
即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问,比如:一个业务前端静态页面的使用nginx,动态页面使用的是tomcat,另外还需要负载均衡调度器,如:haproxy对请求调度至nginx和tomcat的容器,由于容器在启动的时候其内部IP地址是DHCP随机分配的,而给容器起个固定的名称,则是相对比较固定的,因此比较适用于此场景。
2.2 容器名称实现
docker run 创建容器,可以用--link选项实现容器名称的引用。
--link list #Add link to another container
格式:
docker run --name <容器名称> #先创建指定名称的容器
docker run --link <目标通信的容器ID或容器名称> #再创建容器时引用上面容器的名称
先建立一个自定义名字的容器:
再开一个终端,在该终端建立第二个容器和第一容器名字连接:
需要注意的是如果c1 容器发生改变 将无法改变
三、Docker网络连接模式
3.1 网络模式介绍
Docker的网路支持5种网络模式:
none:没有网络只有一块回环网卡
bridge:网桥模式,默认的模式,nat地址转换
host:容器和真机共享网络,直连
container:容器和容器共享网络,两个容器共用一块网卡
network-name:自定义模式
查看默认的网络模式:
3.2 网络模式指定
默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式
格式:
docker run --network <mode>
docker run --net=<mode>
<mode>: 可是以下值
none
bridge
host
container:<容器名或容器ID>
<自定义网络名称>
3.3 Bridge网络模式
可以和外部网络之间进行通信,通过SNAT访问外网,使用DNAT可以让容器被外部主机访问,所以此模式也称为NAT模式,此模式宿主机需要启动ip_forward功能。
bridge网路模式的特点:
网络资源隔离:不同宿主机的容器无法直接通信,各自使用独立网络
无需手动配置:容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
可访问外网:利用宿主机的物理网卡,SNAT连接外网
外部主机无法直接访问容器:可以通过配置DNAT接受外网的访问
低性能较低:因为通过NAT,网络转换带来更多的损耗
端口管理繁琐:每个容器必须手动指定唯一的端口,容器产生端口冲突。
修改默认的bridge模式网络配置:
vim /etc/docker/daemon.json
[root@Node2 data]#:vim /etc/docker/daemon.json
重新加载配置文件;重启:
[root@Node2 ~]#:systemctl daemon-reload
[root@Node2 ~]#:systemctl restart docker
查看docker0的地址:
[root@Node2 ~]#:ip a
......
5: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:dc:b6:08:41 brd ff:ff:ff:ff:ff:ff
inet 192.168.100.100/24 brd 192.168.100.255 scope global docker0
valid_lft forever preferred_lft forever
3.4 Host模式
host模式就是直接使用宿主机的IP地址,创建的容器如果指定host模式启动的容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+端口号即可,不过容器中内除了网络以外的其他资源,如:文件系统、系统进程等仍然和宿主机保持隔离。
此模式由于直接使用宿主机的网络无需切换,网络性能最高,但是各容器内使用的端口不能相同,适用于运行容器端口比较固定的业务。
Host网络模式特点:
此模式的网络性能最高,但是各容器之间端口不能想同,适用于运行容器端口比较固定的业务。
使用参数--network host 指定
共享宿主机网络
网络性能无损耗
网络故障排除相对简单
各容器网络无隔离
网络资源无法分别统计
端口管理困难:容器产生端口冲突
不支持端口映射
例如:我们--network指定网络模式为host。那么就与宿主机共享网卡IP地址。
两种方法都可以:--network host 与 --net=host
docker run -it --network host centos bash
docker run -it --net=host centos bash
容器中查看ip a与宿主机中查看ip a是一样的,连主机名Node2都一样。
3.5 None模式
None模式就是无IP模式,在使用none模式后,Docker容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以及少使用。
none模式特点:
使用参数:--network none 指定
默认无网络功能,无法和外部通信
指定模式:--net=none
这里只有一个本地地址。
3.6 Container模式
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个被指定的已经存在的容器共享IP和端口范围,因此这个容器的端口不能和被指定的容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信。
Container模式特点:
使用参数--network container:名称或ID指定
与宿主机网络空间隔离
容器间共享网络空间
适合频繁的内容间的网络通信
直接使用对方的网络,较少使用。
3.7 建立容器时选择相应的网络模式
使用docker run 创建Docker容器时,可以用--net或--network选项指定容器的网络模式
1.host模式:使用--net=host指定。
2.none模式:使用--net=none指定
3.container模式:使用--net=container:[name or id]
4.bridge模式:使用--net=bridge指定,默认设置,可以省略。
Container模式即容器模式,使用参数--net=container:[目标容器名称/ID]指定,使用此模式创建的容器需指定和一个已经存在的容器共享一个网络namespace,而不会创建独立的namespace,即新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个已经存在的被指定的目标容器共享对方的IP和端口范围,因此这个容器的端口不能和被指定的目标容器端口冲突,除了网络之外的文件系统、用户信息、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡及容器IP进行通信。
新建的容器,会有自己的网络命名空间。
查看网络命名空间:
查看操作 ip netns exec 命名空间id ip a
需要先做软链接:
[root@Node2 ~]#:mkdir /var/run/netns/
[root@Node2 ~]#:
[root@Node2 ~]#:ln -s /var/run/docker/netns/* /var/run/netns/
查看操作:
删除容器后:
[root@Node2 ~]#:docker rm -f `docker ps -aq`
a52e268bee52
be21514503f5
32ac7ccb563b
[root@Node2 ~]#:
[root@Node2 ~]#:ls /var/run/docker/netns/
default
建立 container
[root@Node2 ~]#:docker run -it -d --name nc -p 80:80 nginx
0f6492fb549f43d3a57242fce985b046ab68c8b8f96c6f6a5a534f20f171c369
[root@Node2 ~]#:
[root@Node2 ~]#:docker run -it -d --name php-container --net=container:nc php
ace4841507790a8837ca1f08df426014d4d6adf6433f3e0011cc9d5444e2f458
查看命名空间只有一个
查看IP:
---end---