Docker进阶一:网络篇
理解Docker0
查看本地ip ip addr
[root@VM-0-6-centos ~]# ip addr
#本机回环地址
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
#阿里云的私有IP
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
link/ether 52:54:00:9a:88:4d brd ff:ff:ff:ff:ff:ff
inet 172.17.0.6/20 brd 172.17.15.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe9a:884d/64 scope link
valid_lft forever preferred_lft forever
# docker网桥
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:d1:ba:72:7a brd ff:ff:ff:ff:ff:ff
inet 172.18.0.1/16 brd 172.18.255.255 scope global docker0
valid_lft forever preferred_lft forever
inet6 fe80::42:d1ff:feba:727a/64 scope link
valid_lft forever preferred_lft forever
Docker 是如何处理容器网络访问的?
我们之前安装ES的时候,留过一个问题,就是安装Kibana的问题,Kibana得指定ES的地址!或者我们实际场景中,我们开发了很多微服务项目,那些微服务项目都要连接数据库,需要指定数据库的url地址,通过ip。但是我们用Docker管理的话,假设数据库出问题了,我们重新启动运行一个,这个时候数据库的地址就会发生变化,docker会给每个容器都分配一个ip,且容器和容器之间是可以互相访问的。 我们可以测试下容器之间能不能ping通过。
[root@VM-0-6-centos ~]# docker run -d -P --name tomcat01 tomcat
# 查看tomcat01的ip地址,docker会给每个容器都分配一个ip!
[root@VM-0-6-centos ~]# docker exec -it tomcat01 ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
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
24: eth0@if25: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
link/ether 02:42:ac:12:00:02 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 172.18.0.2/16 brd 172.18.255.255 scope global eth0
valid_lft forever preferred_lft forever
# 可以ping通!
[root@VM-0-6-centos ~]# ping 172.18.0.2
原理
每一个安装了 Docker 的 linux 主机都有一个 docker0 的虚拟网卡。这是个桥接网卡,使用了 veth-pair 技术!
再次查看主机的
ip addr
:本来有三个网络,启动tomcat容器之后,会多了一个网络!每启动一个容器,linux主机就会多了一个虚拟网卡。
#启动一个tomcat01,主机的ip地址多了个 25: veth2b7cb71@if24
#然后我们在tomcat01容器中查看容器的ip 24: eth0@if25 #我们再启动一个tomcat02观察
[root@VM-0-6-centos ~]# docker run -d -P --name tomcat02 tomcat # 然后发现linux主机上又多了一个网卡 27: veth4d2bd95@if26
# 我们看下tomcat02的容器内ip地址是 26: eth0@if27
[root@VM-0-6-centos ~]# docker exec -it tomcat02 ip addr
可以发现:只要启动一个容器,就有一对网卡
veth-pair 就是一对的虚拟设备接口,它都是成对出现的。一端连着协议栈,一端彼此相连着。
正因为有这个特性,它常常充当着一个桥梁,连接着各种虚拟网络设备!
“Bridge、OVS 之间的连接”,“Docker 容器之间的连接” 等等,以此构建出非常复杂的虚拟网络结构,比如 OpenStack Neutron。
我们来测试下 tomcat01 和 tomcat02 容器间是否可以互相 ping 通
[root@VM-0-6-centos ~]# docker exec -it tomcat02 ping 172.18.0.2
PING 172.18.0.2 (172.18.0.2) 56(84) bytes of data.
64 bytes from 172.18.0.2: icmp_seq=1 ttl=64 time=0.095 ms
所以:容器和容器之间是可以互相访问的。
结论:tomcat1 和 tomcat2 共用一个路由器。是的,他们使用的一个,就是docker0。任何一个容器启动默认都是 docker0 网络。 docker 默认会给容器分配一个可用 ip 。
小结
Docker使用Linux桥接,在宿主机虚拟一个Docker容器网桥(docker0),Docker启动一个容器时会根据 Docker网桥的网段分配给容器一个IP地址,称为Container-IP,同时Docker网桥是每个容器的默认网 关。因为在同一宿主机内的容器都接入同一个网桥,这样容器之间就能够通过容器的Container-IP直接 通信。
Docker 容器网络就很好的利用了 Linux 虚拟网络技术,在本地主机和容器内分别创建一个虚拟接口,并让他们彼此联通(这样一对接口叫 veth pair);
Docker 中的网络接口默认都是虚拟的接口。虚拟接口的优势就是转发效率极高(因为Linux是在内核中进行数据的复制来实现虚拟接口之间的数据转发,无需通过外部的网络设备交换),对于本地系统和容器系统来说,虚拟接口跟一个正常的以太网卡相比并没有区别,只是他的速度快很多。
Link参数
思考一个场景,我们编写一个微服务,数据库连接地址原来是使用ip的,如果ip变化就不行了,那我们能不能使用服务名访问呢?
就像 jdbc:mysql://mysql:3306
,这样的话哪怕 mysql 重启,我们也不需要修改配置了!
docker提供了 --link
的操作!
# 我们使用tomcat02,直接通过容器名ping,不使用ip
[root@VM-0-6-centos ~]# docker exec -it tomcat02 ping tomcat01
# ping 不通
ping: tomcat01: Name or service not known
#我们再启动一个tomcat03,但是启动的时候连接tomcat02
[root@VM-0-6-centos ~]# docker run -d -P --name tomcat03 --link tomcat02 tomcat
80ed9c4e1f9428598a91c727ed13b7d0534d86d569855d4fb8739baabe5d6b91
#这个时候,我们就可以使用tomcat03 ping通 tomcat02 了
[root@VM-0-6-centos ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.18.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.18.0.3): icmp_seq=1 ttl=64 time=0.092 ms
# tomcat3 ping不通 tomcat1
[root@VM-0-6-centos ~]# docker exec -it tomcat03 ping tomcat01
ping: tomcat01: Name or service not known
# tomcat2 ping不通 tomcat3 反向也ping不通
[root@VM-0-6-centos ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known
这是为什么呢?
#进入tomcat03中查看下host配置文件
[root@VM-0-6-centos ~]# docker exec -it tomcat03 cat /etc/hosts
127.0.0.1 localhost
::1 localhost ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
#发现tomcat2直接被写在这里
172.18.0.3 tomcat02 cff25f666b32
172.18.0.4 80ed9c4e1f94
所以这里其实就是配置了一个 hosts 地址而已!
原因:--link
的时候,直接把需要 link 的主机的域名和 ip 直接配置到了 hosts 文件中了
--link
早都过时了,我们不推荐使用!我们可以使用自定义网络的方式
自定义网络(重要)
基本概念
指令列表
[root@VM-0-6-centos ~]# docker network --help
Usage: docker network COMMAND
Manage networks
Commands:
connect Connect a container to a network
create Create a network
disconnect Disconnect a container from a network
inspect Display detailed information on one or more networks
ls List networks
prune Remove all unused networks
rm Remove one or more networks
Run 'docker network COMMAND --help' for more information on a command.
查看所有网络
[root@VM-0-6-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
4b873066daf7 bridge bridge local
86da632adad6 elastic bridge local
64b606f257e7 host host local
34ab4fdb73c0 none null local
所有网路模式
网络模式 | 配置 | 说明 |
---|---|---|
bridge模式 | --net=bridge | 默认值,在 Docker 网桥 docker0 上为容器创建新的网络栈 |
none模式 | --net=none | 不配置网络,用户可以稍后进入容器,自行配置 |
container 模式 | -- net=container:name/id | 容器和另外一个容器共享Network namespace。 kubernetes中的pod就是多个容器共享一个Network namespace。 |
host模式 | --net=host | 容器和宿主机共享Network namespace |
用户自定义 | --net=自定义网络 | 用户自己使用network相关命令定义网络,创建容器的 时候可以指定为自己定义的网络,就像 elastic |
查看一个具体的网络的详细信息
[root@VM-0-6-centos ~]# docker network inspect 4b873066daf7
[
{
"Name": "bridge",
"Id": "4b873066daf7eca3fd7a79ce17b46dff17a89368cb7f43d01c88dd9ee08d9407",
"Created": "2021-06-11T18:42:36.937993641+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
//默认 docker0 是管理这个子网范围内的。0~16,
//也就是 255*255,去掉0个255,我们有65534可以分配的ip
//所以 docker0 网络默认可以支持创建6万多个容器ip不重复
"Subnet": "172.18.0.0/16",
"Gateway": "172.18.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"220fac5f16f3cf7f2619131502cb6bb4004f334c3b501a0ceff8804c361cf027": {
"Name": "tomcat01",
"EndpointID": "d54c9b71aff1843c3a1609de8eaa85785ebddd8a419ea5fae346fb538568946f",
"MacAddress": "02:42:ac:12:00:02",
"IPv4Address": "172.18.0.2/16",
"IPv6Address": ""
},
"80ed9c4e1f9428598a91c727ed13b7d0534d86d569855d4fb8739baabe5d6b91": {
"Name": "tomcat03",
"EndpointID": "a6dd8dd8ba2b5b341cbed8318a2463a4e28f1059cc848504a409fbf75ae21f4f",
"MacAddress": "02:42:ac:12:00:04",
"IPv4Address": "172.18.0.4/16",
"IPv6Address": ""
},
"cff25f666b32df808923a51e14f2f2686fc9aff161e07c188c28ce15d0b38401": {
"Name": "tomcat02",
"EndpointID": "b5b18a038166b64a0308cc4a506f543b92d35b9fc50f5758f8d5daccc1df87bd",
"MacAddress": "02:42:ac:12:00:03",
"IPv4Address": "172.18.0.3/16",
"IPv6Address": ""
}
},
"Options": {
"com.docker.network.bridge.default_bridge": "true",
"com.docker.network.bridge.enable_icc": "true",
"com.docker.network.bridge.enable_ip_masquerade": "true",
"com.docker.network.bridge.host_binding_ipv4": "0.0.0.0",
"com.docker.network.bridge.name": "docker0",
"com.docker.network.driver.mtu": "1500"
},
"Labels": {}
}
]
自定义网卡
1、先删除之前创建的 tomcat 镜像以及容器
2、创建容器
但是我们知道默认创建的容器都是 docker0 网卡的
#默认值 --net bridge 使用的docker0
docker run -d -P --name tomcat01 --net bridge tomcat
docker0网络的特点
- 它是默认的
- 域名访问不通
- --link 域名通了,但是删了又不行
3、我们可以让容器创建的时候使用自定义网络
自定义创建的默认default "bridge" 一个网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet
[root@VM-0-6-centos ~]# docker network ls
NETWORK ID NAME DRIVER SCOPE
4b873066daf7 bridge bridge local
64b606f257e7 host host local
7f9fbfea6931 mynet bridge local
34ab4fdb73c0 none null local
[root@VM-0-6-centos ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "7f9fbfea6931271e917c7a932c47d05f311f2fe6f1e694b95e4ef3fcf060446e",
"Created": "2021-06-16T15:56:58.841772626+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {},
"Options": {},
"Labels": {}
}
]
我们来启动两个容器测试,使用自己的 mynet
docker run -d -P --name tomcat-net-01 --net mynet tomcat
docker run -d -P --name tomcat-net-02 --net mynet tomcat
来测试ping容器名和ip试试
# 都可以ping通
[root@VM-0-6-centos ~]# docker exec -it tomcat-net-01 ping 192.168.0.3
PING 192.168.0.3 (192.168.0.3) 56(84) bytes of data.
64 bytes from 192.168.0.3: icmp_seq=1 ttl=64 time=0.118 ms
[root@VM-0-6-centos ~]# docker exec -it tomcat-net-01 ping tomcat-net-02
PING tomcat-net-02 (192.168.0.3) 56(84) bytes of data.
64 bytes from tomcat-net-02.mynet (192.168.0.3): icmp_seq=1 ttl=64 time=0.059 ms
发现,我们自定义的网络docker都已经帮我们维护好了对应的关系
所以我们平时都可以这样使用网络,不使用 --link
效果一样,所有东西实时维护好,直接域名 ping 通。
网络连通
docker0和自定义的网络使用的不是同一个网桥,肯定不通,我们使用自定义网络的好处就是网络隔离:
大公司项目部署的业务都非常多,假设我们有一个商城,我们会有订单业务(操作不同数据),会有订单业务购物车业务(操作不同缓存)。如果在一个网络下,有的程序猿的恶意代码就不能防止了,所以我们就在部署的时候网络隔离,创建两个桥接网卡,比如订单业务(里面的数据库,redis,mq,全部业务都在 order-net 网络下)其他业务在其他网络。
那关键的问题来了,如何让两个不同的网络互相访问呢,如何让 tomcat-net-01 访问 tomcat1?
# 启动默认的容器,在docker0网络下
docker run -d -P --name tomcat01 tomcat
docker run -d -P --name tomcat02 tomcat
有个命令 connect
用来连接网络
# 我们来测试一下!打通mynet-docker0
[root@VM-0-6-centos ~]# docker network connect mynet tomcat01
[root@VM-0-6-centos ~]# docker network inspect mynet
[
{
"Name": "mynet",
"Id": "7f9fbfea6931271e917c7a932c47d05f311f2fe6f1e694b95e4ef3fcf060446e",
"Created": "2021-06-16T15:56:58.841772626+08:00",
"Scope": "local",
"Driver": "bridge",
"EnableIPv6": false,
"IPAM": {
"Driver": "default",
"Options": {},
"Config": [
{
"Subnet": "192.168.0.0/16",
"Gateway": "192.168.0.1"
}
]
},
"Internal": false,
"Attachable": false,
"Ingress": false,
"ConfigFrom": {
"Network": ""
},
"ConfigOnly": false,
"Containers": {
"52395d45d1fcad0170da201db471ea6ac75c25c9f7d91d10b6260dce2739fd54": {
"Name": "tomcat-net-01",
"EndpointID": "3c1aea820c4276b0d0dbe249ebd6f43547baceb7c3e774f8ee4b61b0e4b0b11f",
"MacAddress": "02:42:c0:a8:00:02",
"IPv4Address": "192.168.0.2/16",
"IPv6Address": ""
},
//发现我们的tomcat01就进来这里了
"c159a99201d5b3f0f6be065d562c1a0e6439b316084361937f9eda9a22e997ab": {
"Name": "tomcat01",
"EndpointID": "e11948dcd704e50b8008ee41546ff7c9f506b636f41fb6e6697081fd9d398dc5",
"MacAddress": "02:42:c0:a8:00:04",
"IPv4Address": "192.168.0.4/16",
"IPv6Address": ""
},
"f2106d157b5ea6c5bdb87e04b9dc18be2b2e25a41d61e25851ea0afbf1e9ea39": {
"Name": "tomcat-net-02",
"EndpointID": "3cb8b199df4fca69e1a6428ae0536ff3291f9215f8b9d9303a2ec3402bdc704f",
"MacAddress": "02:42:c0:a8:00:03",
"IPv4Address": "192.168.0.3/16",
"IPv6Address": ""
}
},
"Options": {},
"Labels": {}
}
]
tomcat01 可以ping通了
[root@VM-0-6-centos ~]# docker exec -it tomcat01 ping tomcat-net-01
PING tomcat-net-01 (192.168.0.2) 56(84) bytes of data.
64 bytes from tomcat-net-01.mynet (192.168.0.2): icmp_seq=1 ttl=64 time=0.075 ms
tomcat02 依旧ping不通,因为之前只连接了tomcat01
[root@VM-0-6-centos ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known
结论:如果要跨网络操作别人,就需要使用
docker network connect [OPTIONS] NETWORK CONTAINER
连接
Docker进阶一:网络篇的更多相关文章
- Docker容器网络篇
Docker容器网络篇 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Docker的网络模型概述 如上图所示,Docker有四种网络模型: 封闭式网络(Closed conta ...
- 记录 Docker 的学习过程 (网络篇之跨主机互通)
下面从node3上操作node3# docker run -d -p 8500:8500 --name consul progrium/consul -server -bootstrap node3# ...
- Docker容器基础入门认知-网络篇
这篇文章中,会从 docker 中的单机中的 netns 到 veth,再到单机多个容器之间的 bridge 网络交互,最后到跨主机容器之间的 nat 和 vxlan 通信过程,让大家对 docker ...
- docker进阶——数据管理与网络
一.数据卷管理 用户在使用 Docker 的过程中,势必需要查看容器内应用产生的数据,或者 需要将容器内数据进行备份,甚至多个容器之间进行数据共享,这必然会涉及 到容器的数据管理 (1)Data Vo ...
- 【云计算】Docker云平台—Docker进阶
Docker云平台系列共三讲,此为第二讲:Docker进阶 参考资料: 五个Docker监控工具的对比:http://www.open-open.com/lib/view/open1433897177 ...
- 一文掌握 Linux 性能分析之网络篇(续)
本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 这是 Linu ...
- 两种请求方式URLHttpconnection 和Httpclient提交表单 网络篇(二)
安卓有两种发送请求的方式:URLHttpconnection 和Httpclient 下面就来讲下这两种方式,这篇是最基础的使用 进阶请看第二篇 先占位 打扫卫生去了T T 快过年了 框架就放网络篇 ...
- Docker进阶
Docker进阶 Docker容器命名与重命名 命名 docker run -it -p 80:80 --name containerName img:tag /bin/bash 重命名 docker ...
- ESP8266开发之旅 网络篇⑯ 无线更新——OTA固件更新
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
- ESP8266开发之旅 网络篇⑦ TCP Server & TCP Client
授人以鱼不如授人以渔,目的不是为了教会你具体项目开发,而是学会学习的能力.希望大家分享给你周边需要的朋友或者同学,说不定大神成长之路有博哥的奠基石... QQ技术互动交流群:ESP8266&3 ...
随机推荐
- MySQL安装指导文档
MySQL 是最流行的关系型数据库管理系统,可以在本地搭建一个mysql的环境,便于学习. windows7/windows10 5.7.26 安装mysql前环境准备工作 1) 要有Net fram ...
- Hyper-V CPU设置
前言 最近在用Hyper-V测试项目,发现在运行过程中发现项目总数崩掉,几经发现有一个共性,CPU占用率100%,分析问题发现问题出在Hyper-V CPU设置上,Hyper-V装系统就不赘述了,网上 ...
- State Space Model Content
State Space Model 状态空间模型及其卡尔曼滤波技术 混合正态分布下的状态空间模型及其滤波
- PHP的SPL扩展库(一)数据结构
SPL 库也叫做 PHP 标准库,主要就是用于解决典型问题的一组接口或类的集合.这些典型问题包括什么呢?比如我们今天要讲的数据结构,还有一些设计模式的实现,就像我们之前讲过的观察者模式相关的接口在 S ...
- Spring Boot中使用PostgreSQL数据库
在如今的关系型数据库中,有两个开源产品是你必须知道的.其中一个是MySQL,相信关注我的小伙伴们一定都不陌生,因为之前的Spring Boot关于关系型数据库的所有例子都是对MySQL来介绍的.而今天 ...
- oracle dg failover灾难切换
oracle dg failover灾难切换SQL> alter database recover managed standby database finish force;SQL> a ...
- python 包(package)和模块(module)的创建和引入(import)
python 包(package)和模块(module)的创建和引入(import) 名词解释 实际上,Python中的函数(Function).类(Class).模块(Module).包库(Pack ...
- 记一次Kafka服务器宕机的真实经历!!
大家好,我是冰河~~ 估计节前前祭拜服务器不灵了,年后服务器总是或多或少的出现点问题.不知是人的问题,还是风水问题.昨天下班时,跟运维小伙伴交代了好几遍:如果使用Docker安装Kafka集群的话,也 ...
- 从零入门 Serverless | 一文讲透 Serverless Kubernetes 容器服务
作者 | 张维(贤维) 阿里云函数计算开发工程师 导读:Serverless Kubernetes 是以容器和 kubernetes 为基础的 Serverless 服务,它提供了一种简单易用.极致弹 ...
- HC(Histogram-based Contrast) 基于直方图对比度的显著性
HC(Histogram-based Contrast) 基于直方图对比度的显著性 来源于: 2011, Global contrast based salient region detection, ...