前言
现在对于Docker容器的隔离性都有所了解了,但对容器IP地址的分配、容器间的访问等还是有点小疑问,如果容器的IP由于新启动导致变动,那又怎么才能保证原有业务不会被影响,这就和网络有挂钩了,接下来就大概说说。
正文
1. Docker网络模式简介
当Docker进程启动时,会在主机上创建一个名为docker0的虚拟网桥,此主机上启动的Docker容器默认会连接到这个虚拟网桥上。这样所有容器通过这个虚拟网桥就打通了,所以这里的docker0工作方式和物理交换机很像。
在主机上可以执行命令ip link show docker0
查看:
![4a92285ef393fd0e2a122aa7d98cd670.png](https://i-blog.csdnimg.cn/blog_migrate/d31add253a4afc405e578e153fd43b3d.png)
Docker在启动容器时可以指定网络模式,如果不指定,默认就是采用Bridge模式;Docker的网络模式有如下几种:
Bridge(桥接)模式:默认的网络模式,比较适用于在同一Docker Daemon主机上运行的容器,用户也可以自定义bridge网络,优于默认的bridge网络;如果需要不同Docker主机进行通信,可以通过操作系统网络配置,也可以使用Overlay模式。
Host模式:和宿主机共用一个Network Namespace。即容器不会虚拟出自己的网卡和配置自己的IP等,而是使用宿主机的IP和端口;
Overlay模式:覆盖网络可以将多个 Docker Daemon主机连接在一起,并使 swarm 服务能够相互通信;也可以让Docker Daemon主机上的两个独立容器进行通信。
Macvlan模式:Macvlan 网络允许为容器分配 MAC 地址,使其在网络上显示为物理设备。Docker Deamon通过容器的 MAC 地址将流量路由到容器。
None模式:Docker容器拥有自己的Network Namespace,但是并不为容器进行任何网络配置。即容器没有网卡、IP、路由等信息。需要单独为Docker容器添加网卡、配置IP;
Docker在启动容器的时候可以通过--net指定网络模式,不指定,默认就是bridge模式,如下:
# --net指定网络模式,这里指定为host模式
docker run -d --name testnet --net host nginx
# 通过docker inspect 容器 看网络细节,如下图
docker inspect testnet
![b4af58523ded4bdab1f9ae90459065c4.png](https://i-blog.csdnimg.cn/blog_migrate/c8037ba9c87426aa0b9c5ee3d835339b.png)
2. Bridge默认模式了解一下
这里就以默认的Bridge(桥接)展开来说说,其他模式后续根据应用场景再具体细说。
这里主要看看主机和容器之间的网络、容器和容器之间的网络。
在Bridge模式下,当启动容器时,Docker会分配一个IP给容器,并设置docker0的IP地址为容器的默认网关;这个时候会在主机上创建一对虚拟网卡veth pair设备接口,Docker将veth pair设备的一端配置在新启动的容器中,并命名为eth0@ifxxx(容器的网卡),另一端在主机中以veth***@ifxxx这样类似的名字命名,并将这个网络设备加入到docker0网桥中。
容器没有启动时主机的网络配置如下:
![ef3d5825d2f9404968a7161b2266560b.png](https://i-blog.csdnimg.cn/blog_migrate/32ebb75f8e535d0448f5e8f21f305352.png)
当启动容器时,Docker主机就会创建一对虚拟网卡vethpair设备接口,如下:
![5cd568557b7d01112afdb177889470ed.png](https://i-blog.csdnimg.cn/blog_migrate/1b360a4e571345bf0db23108052e52ed.png)
可以进入到容器看看IP分配情况,如果ip addr
命令在容器内找不到,那是因为基础镜像只包含核心命令,如果要执行其他命令,需要额外安装。可以在容器内执行如下命令进行安装。
apt update && apt install -y iproute2
安装好之后,就可以查看容器内的IP情况了,如下:
![442ef6d554ff43cf0be7e0a365308390.png](https://i-blog.csdnimg.cn/blog_migrate/8bd1282f3bb2fec8801e8e4aa8bbe3f1.png)
这里有没有发现容器内的IP是和主机多出来的虚拟网卡是成对出现,这样主机网络和容器之间肯定能通;
![f030e8eaa5e252d3305c2fba665dfdd9.png](https://i-blog.csdnimg.cn/blog_migrate/c5b7c67c5138f74ca09a7942574d3e67.png)
当然容器内部也可以ping通主机。
那容器之间能不能访问呢?
容器内ping命令也找不到,需要进行安装,执行如下命令:
apt update && install iputils-ping
这里新启动一个容器mynginx2,IP内部分配如下:
![0412636d391b7f1fdd033bc2c1594e1a.png](https://i-blog.csdnimg.cn/blog_migrate/35efe570ee926769fd6434cf667abfd0.png)
mynginx容器内能ping通mynginx2,那是因为两个容器之间共用了docker0,通过docker0进行转发。
![44fd5a3da5a27f2f13be323c532fbbf7.png](https://i-blog.csdnimg.cn/blog_migrate/e8f2f18f9293f01065537655743a28d8.png)
大概一个网络流程如下:
![9ef2208c4ff1957d29450cdada2a8a6a.png](https://i-blog.csdnimg.cn/blog_migrate/a26cbab805d38f2e2aa4b3dce129b49b.png)
这里的Docker0就好比是交换机,形成了网络桥梁。
3. 如何能通过容器名进行访问
默认情况,容器间的访问只能通过IP,不能通过容器名访问;
![e1060f3c32000acb661c66964a37c153.png](https://i-blog.csdnimg.cn/blog_migrate/f9344c5d027cdc23138a19d81dc4b33f.png)
这种情况对于线上项目很不灵活,比如数据库备份需要临时迁移,IP可能会不一样,所以项目中的地址要重新配置,如果能通过容器名访问,那么就不用操心更换啦,只要容器名一样即可,就好比域名和IP的关系一样,IP再怎么变,域名不变就行。
3.1 通过--link方式;
新启动一个容器mynginx3,如下:
# 通过--link关联 mynginx容器
docker run -d --name mynginx3 --link mynginx nginx
容器启动之后,可以进入到容器测试:
# 进入容器
docker exec -it mynginx3 /bin/bash
# 安装ping工具
apt update && apt install iputils-ping
![379a122387791b2214605410da513946.png](https://i-blog.csdnimg.cn/blog_migrate/ab0163376871ba65469c2586fa17611b.png)
内部原理其实是在mynginx3内部做了个映射配置,容器mynginx3的hosts内容如下:
![3226cea36bd7a3ad17e42dfbda58606e.png](https://i-blog.csdnimg.cn/blog_migrate/a1eef5d023cb8b3c2185faca4aca2e60.png)
这样只能在容器mynginx3内部通过mynginx容器名ping通,不能在mynginx内部通过容器名mynginx3访问,如果要达到同样的效果,就得在启动mynginx时通过--link和mynginx3关联起来。
![34bd0fae4104b57e4bfe25f772dad0c7.png](https://i-blog.csdnimg.cn/blog_migrate/2282624af888ca2a9fb8a57b08293a60.png)
如果每个容器都这样的显示指定的话,感觉就有点麻烦啦,通常的做法都是通过自定义网络方式来达到这个目的。
3.2 通过自定义网络方式;
首先新创建一个网络,如下:
![9fbfb56e51d2d35bcbc61ba1c6cd53ba.png](https://i-blog.csdnimg.cn/blog_migrate/107e41d4dc2689108356257193ae18a4.png)
命令解析:
# --driver 指定网络模式,这里为bridge桥接模式
# --subnet 指定子网IP 192.168.0.0/16
# --gateway 指定网关 192.168.0.1
# my-net 创建的网络名
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 my-net
# 显示网络
docker network ls
让启动的容器使用自定义的网络,即在启动容器时使用--net指定即可:
![ce477bc4febb906854deaf2f4af4ac61.png](https://i-blog.csdnimg.cn/blog_migrate/7ae641a0260924b6f8c19a4084c1e076.png)
启动容器时不需要--link,只需要接入到自定义网络就可以通过容器名ping通了,如下:
![b15bdd6165fe063f12315793bf129712.png](https://i-blog.csdnimg.cn/blog_migrate/d858973502728c1d20cc167bd822b3da.png)
自定义网络之所以能通过容器名ping通,那是容器内运行了一个本地DNS解析器,该解析器将请求转发到Docker内部DNS服务器当中,DNS服务器中记录了容器启动时通过--name或--net-alias参数指定的名称与容器之间的关系。
另外还有一个点,现在分配给容器的IP是按照预先设置的子网范围进行分配的,而不是默认的docker0子网范围,执行如下命令看详细:
# 看容器详细信息
docker inspect testmynetnginx1
![5fb52fa42b723a8ee4bc9bc6d4f40e80.png](https://i-blog.csdnimg.cn/blog_migrate/d4e850a0ae3b34b342d4ad12455d8912.png)
总结
关于Docker网络简单先说这么多,后续根据实际应用场景再好好细说,这里主要的目的是了解一下默认的网络模式和自定义网络方式的使用和解决的问题。
Docker之前文章目录:
到目前为止,一般的Docker使用没问题了,但当容器比较多时,一个一个的拉取镜像和启动容器就显得有点不方便了,所以下次我们来学学Docker Compose,关注“Code综艺圈”,和我一起学习吧;最后祝小伙伴们中秋快乐~~~