docker容器创建后,必不可少的要与其他主机与容器进行通信
https://docs.docker.com/network/
docker默认的网络通信
docker安装后默认的网络设置:
Docker服务安装完成之后,默认在每个宿主机会生成一个名称为docker0的网卡其IP地址都是
172.17.0.1/16
创建容器后的网络设置
每次新建容器之后
- 宿主机多了一个虚拟网卡,和容器的网卡组合成一个网卡,比如: 137: veth8ca6d43@if136,而在容器内的网卡名为136,可以看出和宿主机的网卡之间的关联
- 容器会自动获取一个172.17.0.0/16网段的随机地址,默认从172.17.0.2开始,第二次容器为
172.17.0.3,以此类推 - 容器获取的地址并不固定,每次容器重启,可能会发生地址变化
创建第一个容器后的网络状态
创建容器,容器自动获取IP地址
新建第一个容器,宿主机的网卡多了一个新网卡
查看新建容器后桥接状态
(若提示没有此命令请安装 yum -y install bridge-utils
)
容器间的通信
同一个宿主机的不同容器可相互通信
默认情况下
- 同一个宿主机的不同容器之间可以相互通信
dockerd --icc Enable inter-container communication (default true)
--icc=false #此配置可以禁止同一个宿主机的容器之间通信
- 不同宿主机之间的容器IP地址重复,默认不能相互通信
同一个宿主机的容器之间访问
禁止同一个宿主机之间不同容器的通信
dockerd 的 --icc=false 选项可以禁止同一个宿主机的不同容器间通信
此处使用的docker版本为
【centos 上的配置文件略有不同或不支持容器间的隔离通信】
root@ubuntu:~# docker --version
Docker version 23.0.3, build 3e7cbfd
root@ubuntu:~# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--icc=false
root@ubuntu:~# systemctl daemon-reload
root@ubuntu:~# systemctl restart docker
创建两个容器默认不能通信
修改默认docker0
网桥的网络配置
默认docker后会自动生成一个docker0的网桥,使用的IP是172.17.0.1/16,可能和宿主机的网段发生冲突,可以将其修改为其它网段的地址,避免冲突
将docker0的IP修改为指定IP
#方法一:
[root@centos7-1 ~]# cat /etc/docker/daemon.json
{
"bip": "192.168.100.1/24"
}
[root@centos7-1 ~]# systemctl restart docker
#方法二:
[root@centos7-1 ~]# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
--bip=192.168.100.1/24
[root@centos7-1 ~]# systemctl daemon-reload
[root@centos7-1 ~]# systemctl restart docker.service
#注意两种方法不可混用,否则将无法启动docker服务
修改默认网络设置使用自定义网桥
新建容器默认使用docker0的网络配置,可以修改默认指向自定义的网桥网络
用自定义的网桥代替默认的docker0
root@ubuntu:~# brctl addbr br0
root@ubuntu:~# ip a a 192.168.100.1/24 dev br0
root@ubuntu:~# vim /lib/systemd/system/docker.service
ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock -b br0
root@ubuntu:~# systemctl daemon-reload
root@ubuntu:~# systemctl restart docker
容器名称互联
新建容器时,docker会自动分配容器名称,容器ID和IP地址,导致容器名称,容器ID和IP都不固定,那么如何区分不同的容器,实现和确定目标容器的通信呢?解决方案是给容器起个固定的名称,容器之间通过固定名称实现确定目标的通信。
有两种固定名称:
- 容器名称
- 容器名称的别名
注意: 两种方式都最少需要两个容器才能实现
通过容器名称互联
容器名称介绍
即在同一个宿主机上的容器之间可以通过自定义的容器名称相互访问,比如: 一个业务前端静态页面是使用nginx,动态页面使用的是tomcat,另外还需要负载均衡调度器,如: haproxy 对请求调度至nginx和tomcat的容器,由于容器在启动的时候其内部IP地址是DHCP 随机分配的,而给容器起个固定的名称,则是相对比较固定的,因此比较适用于此场景
注意: 如果被引用的容器地址变化,必须重启当前容器才能生效
容器名称的实现
docker run 创建容器,可使用–link选项实现容器名称的引用,其本质就是在容器内的/etc/hosts中添加–link后指定的容器的IP和主机名的对应关系,从而实现名称解析
--link list #Add link to another container
格式:
docker run --name <容器名称> #先创建指定名称的容器
docker run --link <目标通信的容器ID或容器名称> #再创建容器时引用上面容器的名称
使用容器名称进行容器间通信:
1、先创建第一个指定容器名称的容器
2、新建第二个容器时引用第一个容器的名称
会自动将第一个主机的名称加入/etc/hosts文件,从而可以利用第一个容器名称进行访问
docker网络连接模式
网络模式介绍
Docker 的网络支持5种网络模式:
- none
- bridge
- host
- container
- network-name
查看默认的网络模式有三个
网络模式指定
默认新建的容器使用Bridge模式,创建容器时,docker run 命令使用以下选项指定网络模式
格式:
docker run --network <mode>
docker run --net=<mode>
<mode>: 可是以下值
none
bridge
host
container:<容器名或容器ID>
<自定义网络名称
bridge网络模式
可以和外部网络之间进行通信,通过SNAT访问外网,使用DNAT可以让容器被外部主机访问,所以此模式也称为NAT模式
此模式宿主机需要启动ip_forward功能
bridge网络模式特点
- 网络资源隔离: 不同宿主机的容器无法直接通信,各自使用独立网络
- 无需手动配置: 容器默认自动获取172.17.0.0/16的IP地址,此地址可以修改
- 可访问外网: 利用宿主机的物理网卡,SNAT连接外网
- 外部主机无法直接访问容器: 可以通过配置DNAT接受外网的访问
- 低性能较低: 因为可通过NAT,网络转换带来更的损耗
- 端口管理繁琐: 每个容器必须手动指定唯一的端口,容器产生端口冲容
可以用 docker network inspect bridge
查看bridge模式信息
安装docker后,默认启用ip_forward
修改默认的 bridge 模式网络配置
有两种方法修改默认的bridge 模式的网络配置,但两种方式只能选一种,否则会导致冲容,docker服务无法启动,修改方法参考修改默认docker0网桥的网络配置
Host 模式
如果指定host模式启动的容器,那么新创建的容器不会创建自己的虚拟网卡,而是直接使用宿主机的网卡和IP地址,因此在容器里面查看到的IP信息就是宿主机的信息,访问容器的时候直接使用宿主机IP+容器端口即可,不过容器内除网络以外的其它资源,如: 文件系统、系统进程等仍然和宿主机保持隔离
此模式由于直接使用宿主机的网络无需转换,网络性能最高,但是各容器内使用的端口不能相同,适用于运行容器端口比较固定的业务
Host 网络模式特点:
- 使用参数 --network host 指定
- 共享宿主机网络
- 网络性能无损耗
- 网络故障排除相对简单
- 各容器网络无隔离
- 网络资源无法分别统计
- 端口管理困难: 容易产生端口冲突
- 不支持端口映射
none模式
在使用none 模式后,Docker 容器不会进行任何网络配置,没有网卡、没有IP也没有路由,因此默认无法与外界通信,需要手动添加网卡配置IP等,所以极少使用
none模式特点:
- 使用参数 --network none 指定
- 默认无网络功能,无法和外部通信
- 无法实现端口映射
- 适用于测试环境
Container 模式
使用此模式创建的容器需指定和一个已经存在的容器共享一个网络,而不是和宿主机共享网络,新创建的容器不会创建自己的网卡也不会配置自己的IP,而是和一个被指定的已经存在的容器共享IP和端口范围,因此这个容器的端口不能和被指定容器的端口冲突,除了网络之外的文件系统、进程信息等仍然保持相互隔离,两个容器的进程可以通过lo网卡进行通信
Container 模式特点
- 使用参数 –-network container:名称或ID 指定
- 与宿主机网络空间隔离
- 空器间共享网络空间
- 适合频繁的容器间的网络通信
- 直接使用对方的网络,较少使用
先创建第一个容器
在创建第二个容器,基于第一个容器的container的网络模式(且IP地址相同)
也可以访问外网
自定义网络模式
除了以上的网络模式,也可以自定义网络,使用自定义的网段地址、网关信息
注意:自定义网络内的容器可以通过容器名进行相互的访问,而无需使用 --like
可以使用自定义网络模式,实现不同集群应用的独立网络管理,而互不影响,而且在同一个网络内,可以直接利用容器名称进行访问,非常便利。
自定义网络实现
创建自定义网络
docker network create -d <mode> --subnet <CIDR> --gateway <网关> <自定义网络名称> #注意mode不支持host和none,默认是bridge模式
查看自定义网络信息
docker network inspect <自定义网络名称或网络ID>
引用自定义网络
docker run --network <自定义网络名称> <镜像名称>
删除自定义网络
doccker network rm <自定义网络名称或网络ID>
注意:内置的三个网络没有办法删除
root@ubuntu:~# docker network create -d bridge --subnet 172.27.0.0/16 --gateway 172.27.0.1 test-net
be8eaf433310b0dacb1db71c5c87758cacd2362395eefce122d687dbe208deab
root@ubuntu:~# docker network ls
NETWORK ID NAME DRIVER SCOPE
d06c7267dc63 bridge bridge local
87e4763dfd86 host host local
2a9b897f14c9 none null local
be8eaf433310 test-net bridge local
查看创建网络的详细信息
发现并且多出来一块虚拟网卡
利用自定义网络创建容器