Docker 学习笔记(九):Docker 网络原理,理解 docker0,虚拟网卡,容器互联,以及跨网络连通

一、前言

记录时间 [2024-4-16]

系列文章简摘:
Docker 学习笔记(六):挑战容器数据卷技术一文通,实战多个 MySQL 数据同步,能懂会用,初学必备
Docker 学习笔记(七):介绍 Dockerfile 相关知识,使用 Dockerfile 构建自己的 centos 镜像
Docker 学习笔记(八):Dockerfile实战篇,制作 Tomcat 镜像,发布镜像到 DockerHub 和阿里云

更多 Docker 相关文章请参考上面专栏哦,入门篇 1~5 已完结6 开始是精髓篇:容器数据卷、Dockerfile、Docker 网络

本文介绍了 Docker 网络原理,介绍了 docker0,Veth-pair 技术,以及 Docker 给容器分配虚拟网卡的方式。同时讲述了两种容器互联的方式,分别是 Link 和 自定义网络。还有容器之间跨网络连通的方式。


二、划重点

当我们在 Linux 宿主机中安装了 Docker:

  • 宿主机中就会配置 docker0 网卡,docker0 使用的是 Linux 桥接模式,使用的技术是 Veth-pair 技术。
  • 每启动一个 Docker 容器,Docker 就会给该容器分配一个 ip,一对虚拟网卡。

关于 Docker0 的结论:

  • Docker 容器 tomcat01 和 tomcat02,二者共用一个路由器,即 docker0;
  • 所有容器在不指定网络的情况下,都使用 docker0 路由,Docker 会给它们默认分配一个可用的 IP 地址;
  • Docker 中所有的网络接口都是虚拟的,因为虚拟网卡转发效率高,传输文件快。
  • 移除容器之后,分配给它的虚拟网卡自动消失,对应的网桥就没了。

关于自定义网络:

  • Docker 中的自定义网络,修复了 docker0 不能使用名字 ping 连接的问题;
  • 给不同的集群使用不同的自定义网络,可以保证集群的安全和健康。

关于跨网络连通:

  • 假设容器之间要跨网络通信,其中一个容器需要拥有多个 IP 地址。

三、清空 Docker 环境

在之前的 Docker 学习中,我们下载 / 提交 / 构建了很多镜像,运行了各种不同的容器,真是不错的收获!现在我们将进入 Docker 网络的学习,为了便于学习和理解 Docker 网络的内部原理,我们先清空一下 Docker 环境,把里面的镜像和容器通通删除。

当然啦,如果有特别想要保留的镜像,就把它们发布到阿里云镜像仓库吧。发布镜像,请参考这篇文章

不清空也没有关系,就是会看着有亿点点乱罢了。

删除镜像 / 容器命令:

# 删除所有 docker 容器
docker rm -f $(docker ps -aq)# 删除所有 docker 镜像
docker rmi -f $(docker images -aq)# 查看是否删除成功
docker images		# 查看所有 docker 镜像
docker ps -a		# 查看所有 docker 容器

四、介绍 Docker0

1. 理解网络 Docker0

删除完成后,我们来查看 Linux 宿主机网络

[root@localhost ~]# ip addr
1: lo: 本机回环地址
2: eth0: 阿里云内网地址
3: docker0: docker0 地址
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
# 172.17.0.1 相当于一个路由器 网关

通过查询发现,Linux 宿主机中一共有 3 个网络,除却本机回环地址 127.0.0.1,以及本机内网地址,剩下的 docker0 便与 Docker 网络相关了。

当我们在 Linux 宿主机中安装了 Docker:

  • 宿主机中就会配置 docker0 网卡,docker0 使用的是 Linux 桥接模式,使用的技术是 Veth-pair 技术。
  • 每启动一个 Docker 容器,Docker 就会给该容器分配一个 ip,一对虚拟网卡。

2. 提前解决报错

由于远程仓库中的 tomcat 镜像是精简版的,镜像内部缺少 iproute2 和 iputils-ping 依赖,直接使用此镜像来运行是无法使用 ip 命令的,会报出如下错误:

OCI runtime exec failed: exec failed: unable to start container process: exec: "ip": executable file not found in $PATH: unknown
OCI runtime exec failed: exec failed: unable to start container process: exec: "ping": executable file not found in $PATH: unknown

不要慌,解决办法也很简单,就是自己安装一下 iproute2 和 iputils-ping 依赖

因为后面我们要运行好多容器,手动给每个容器都去安装一遍的话就显得累赘,所以我们把这个容器 commit 为本地镜像

安装 iproute2 和 iputils-ping 方法:

# 1. 用基础镜像 tomcat 运行一个容器 tomcat01
docker run -d -P --name tomcat01 tomcat# 2. 进入容器
docker exec -it tomcat01 /bin/bash# 3. 更新 apt,安装 iproute2,安装 iputils-ping
apt-get update
apt install -y iproute2
apt install -y iputils-ping# 4. 安装完以后退出 exit
# 5. 提交 容器 tomcat01 为本地镜像
docker commit -a="yuanyuan" -m="add apt ip and ping" tomcat01 yuanyuan/tomcat

3. 一对虚拟网卡

那么,Docker 如何处理网络访问?或者说,两个 Docker 容器之间如何通信?

我们在 Docker0 网络下运行两个 tomcat 容器,来进行测试。

查看容器 tomcat01 内部的网络地址:

  • 追加命令:ip addr
docker exec -it 容器名 ip addr# tomcat01 的 ip 172.17.0.2
[root@localhost ~]# docker exec -it tomcat01 ip addr
144: eth0@if145: inet 172.17.0.2/16 brd 172.17.255.255 scope global eth0

每启动一个 Docker 容器,Docker 就会给该容器分配一个 ip,一对虚拟网卡。

我们发现,容器 tomcat01 启动时,得到了 Docker 分配的 ip 地址和虚拟网卡。

  • ip 地址:172.17.0.2
  • 一对虚拟网卡:144: eth0@if145

思考:Linux 宿主机可以同 容器 tomcat01 通信吗?

通过宿主机 ping 容器 ip 的方式,我们来测试一下:发现可以 ping 通,因为它们在同一网段。

[root@localhost ~]# ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.124 ms

此时,我们再来查看 Linux 宿主机网络

# Linux 多了一对虚拟网卡
[root@localhost ~]# ip addr
3: docker0: docker0 inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
145: veth57938f5@if144: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc

发现 Linux 多了一对虚拟网卡,这对虚拟网卡和 tomcat01 有很大的联系。


再创启动一个 tomcat02 容器试试:

# 镜像 yuanyuan/tomcat 是我们刚刚提交的那一个
docker run -d -P --name tomcat02 yuanyuan/tomcat

然后查看一下 Linux 的网络:Linux 又多了一对虚拟网卡。

# Linux 又多了一对虚拟网卡
[root@localhost ~]# ip addr
3: docker0: docker0 inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
145: veth57938f5@if144: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc 
149: veth31fb2d8@if148: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc

查看下 tomcat02 容器的网络配置:

# tomcat02 ip 172.17.0.3; 虚拟网卡 148: eth0@if149
[root@localhost ~]# docker exec -it tomcat02 ip addr
148: eth0@if149: inet 172.17.0.3/16 brd 172.17.255.255 scope global eth0

容器的虚拟网卡和宿主机的虚拟网卡是相对应的!

随着容器带来的虚拟网卡,都是一对一对的,这便是 Veth-pair 技术。

Veth-pair 是一对虚拟设备接口,它们都是成对出现的,一端连接协议,一端彼此相连。正因为有这个特性,Veth-pair 能充当桥梁,来连接各种虚拟网络设备。


4. 使用 Docker0

由于容器 tomcat01 和 tomcat02 都是通过 Docker0 方式桥接的,所以它们之间能够通信,但是,只能通过 ip 地址,不能用名字。

我们测试一下上述容器 tomcat01 和 tomcat02 之间能否 ping 通。

用 tomcat02 ping tomcat01:(反之亦然)

[root@localhost ~]# docker exec -it tomcat02 ping 172.17.0.2
PING 172.17.0.2 (172.17.0.2) 56(84) bytes of data.
64 bytes from 172.17.0.2: icmp_seq=1 ttl=64 time=0.076 ms

不难发现,容器和容器之间是可以互相 ping 通的。

绘制一个网络模型图来加深理解:tomcat01 想要和 tomcat02 通信,得借助 docker0 这个路由器

在这里插入图片描述


现在,我们把 tomcat01 容器删除:

docker rm -f tomcat01

再次查看 Linux 的网络配置:发现 tomcat01 容器对应的网桥被一同移除了。

# 删掉容器,少了一对虚拟网卡,对应的网桥就没了
[root@localhost ~]# ip addr
3: docker0: inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
149: veth31fb2d8@if148: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc

关于局域网的知识补充:

每个 IP 地址由二进制的四段组成:00000000.00000000.00000000.00000000,每一段的范围是 0~255。

比如有这样一个子网掩码 255.255.0.0/16,这里转换成十进制表示,

16 表示 IP 的前 16 位用来固定网段 255.255,后 16 位用来给局域网内设备分配 IP,255.255.0.1 一般是路由器网关。

那么 IP 为 255.255.xxx.xxx 这样的设备都在这个局域网中,可以互相 ping 通。


关于 Docker0 的结论:

  • Docker 容器 tomcat01 和 tomcat02,二者共用一个路由器,即 docker0;
  • 所有容器在不指定网络的情况下,都使用 docker0 路由,Docker 会给它们默认分配一个可用的 IP 地址;
  • Docker 中所有的网络接口都是虚拟的,因为虚拟网卡转发效率高,传输文件快。
  • 移除容器之后,分配给它的虚拟网卡自动消失,对应的网桥就没了。

如图所示,Docker 使用 Veth-pair 技术实现容器间的通信。

在这里插入图片描述


5. 查看网络模式

我们来查看一下 Docker 中的几种网络模式:

  • bridge:桥接模式,默认的 docker0 用的就是这种;
  • host:和宿主机共享网络;
  • none:不配置网络;
  • container:容器网络连通(这种用得少,局限性很大)
[root@localhost ~]# docker network ls
NETWORK ID     NAME      DRIVER    SCOPE
949536a4c28c   bridge    bridge    local
03fb5b594ce1   host      host      local
1e8dd7dab9b3   none      null      local

然后具体查看一下桥接模式 bridge:

  • Subnet:子网掩码
  • Gateway:网关
  • Containers:给容器分配的默认 IP 信息
[root@localhost ~]# docker network inspect 949536a4c28c
{"Subnet": "172.17.0.0/16","Gateway": "172.17.0.1"
}# 如果容器没有指定 IP,docker0 会随机分配
"Containers": {"Name": "tomcat01",        "IPv4Address": "172.17.0.2/16",
}

五、容器互联

1. Link 方式

思考一个场景:假如我们编写了一个微服务,需要连接数据库,但数据库每次启动 ip 都会发生变化,为了使得微服务不受数据库 ip 变化的影响,我们希望通过名字来进行数据库访问,实现微服务的高可用。

在默认的 docker0 中,添加 --link 参数,可以达到这个要求。

重新运行一个 tomcat01 容器吧:

docker run -d -P --name tomcat01 yuanyuan/tomcat

默认 docker0 情况下,容器之间只能通过 ip 来 ping,名字是 ping 不通的。

试一下吧,用 tomcat02 ping tomcat01,直接 ping 容器名字。

[root@localhost ~]# docker exec -it tomcat02 ping tomcat01
ping: tomcat01: Name or service not known

名字 ping 不通,怎么解决呢?添加 --link 参数。

我们再运行一个新的容器 tomcat03 测试下,把 tomcat03 link 到 tomcat02

docker run -d -P --name tomcat03 --link tomcat02 yuanyuan/tomcat

测试 tomcat02 和 tomcat03 之间用名字 ping 一下:tomcat03 可以 ping tomcat02,但 tomcat02 不可以 ping tomcat03。

# tomcat03 ping tomcat02 可以
[root@localhost ~]# docker exec -it tomcat03 ping tomcat02
PING tomcat02 (172.17.0.3) 56(84) bytes of data.
64 bytes from tomcat02 (172.17.0.3): icmp_seq=1 ttl=64 time=0.202 ms# tomcat02 ping tomcat03 不可以
[root@localhost ~]# docker exec -it tomcat02 ping tomcat03
ping: tomcat03: Name or service not known

为什么呢?inspect 探究一下吧。可以在 tomcat03 容器中找到 Link 配置,而 tomcat02 容器中没有配置。

[root@localhost ~]# docker inspect tomcat03
"Links": ["/tomcat02:/tomcat03/tomcat02"]

也可以通过查看 hosts 配置来发现原理。tomcat03 在本地配置了 tomcat02 的配置,它把 tomcat02 直接写入了 hosts 文件,ping tomcat02 / b71a0a6566a3 就相当于 ping 对应的 ip 172.17.0.3。

tomcat02 的 hosts 文件里就没有写 tomcat03,大家可以查看验证一下。

# --link 就是在 tomcat03 的 hosts 里绑定了 172.17.0.3  tomcat02 b71a0a6566a3[root@localhost ~]# docker exec -it tomcat03 cat /etc/hosts
172.17.0.3      tomcat02 b71a0a6566a3

这就是为什么 tomcat03 可以 ping tomcat02,但 tomcat02 不可以 ping tomcat03 的原因啦。


2. 自定义网络

创建自定义网络

之前是使用的是默认网络 docker0:

# 我们直接启动命令 --net bridge,就是 docker0
# 以下两条命令是等同的,--net bridge 默认情况下可以省略。
docker run -d -P --name tomcat01 yuanyuan/tomcat
docker run -d -P --name tomcat01 --net bridge yuanyuan/tomcat

先清空一下容器:

docker rm -f $(docker ps -aq)

接下来我们自定义一个桥接网络 mynet,配置两个容器到 mynet 网络中。

创建一个自定义网络:

  • --driver:设置网络模式;
  • --subnet:设置子网掩码;
  • --gateway:设置网关;
  • mynet:自定义网络的名字。
# 创建一个自定义网络
docker network create --driver bridge --subnet 192.168.0.0/16 --gateway 192.168.0.1 mynet# 查看网络模式
docker network ls# 查看自定义网络 mynet 的详细信息
docker network inspect mynet

启动两个容器 tomcat-net-01 和 tomcat-net-02,把 tomcat 发布到自定义网络中。

# 运行容器
docker run -d -P --name tomcat-net-01 --net mynet yuanyuan/tomcat
docker run -d -P --name tomcat-net-02 --net mynet yuanyuan/tomcat# 查看 mynet 给容器们分配的 ip
docker network inspect mynet

测试 ping 连接

接下来,我们测试一下 tomcat-net-01 (192.168.0.2)tomcat-net-02 (192.168.0.3) 之间的 ping 连接。

  • tomcat-net-01 ping 192.168.0.3:成功
  • tomcat-net-01 ping tomcat-net-02:成功
  • tomcat-net-02 ping tomcat-net-01:成功
# 现在不使用 --link 也可以 ping 名字了!# tomcat-net-01 ping 192.168.0.3
[root@localhost ~]# 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.092 ms# tomcat-net-01 ping tomcat-net-02
[root@localhost ~]# 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.135 ms# tomcat-net-02 ping tomcat-net-01
[root@localhost ~]# docker exec -it tomcat-net-02 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.046 ms

关于自定义网络:

  • Docker 中的自定义网络,修复了 docker0 不能使用名字 ping 连接的问题;
  • 给不同的集群使用不同的自定义网络,可以保证集群的安全和健康。

六、跨网络连通

1. 连通方式

当前,在 Linux 宿主机中,有两个 Docker 网络,分别是 docker0 和 mynet,两个都是桥接模式,网段不同。

如图所示,在 docker0 局域网中,运行了 container01 和 container02 两个容器;在 mynet 局域网中,运行了 container03 和 container04 两个容器。

在不经过多余配置的情况下,container01 和 container03 是无法通信的,就是 ping 不通的。

那如果,container01 就非常想和 container03 通信,有啥办法嘛?

首先,docker0 和 mynet 这两个网段肯定是不能打通的,否则就违背了我们给不同的集群使用不同的自定义网络的初衷。

那么,container01 就只能取得 mynet 的联系了。

container01 先联络上 mynet,再通过 mynet 联络上 container03。

在这里插入图片描述


2. 操作实现

在 docker0 中运行两个容器 tomcat01,tomcat02,之前的被删了。

不死心,tomcat01 先去 ping 一下 mynet 中的 tomcat-net-01:

docker run -d -P --name tomcat01 yuanyuan/tomcat
docker run -d -P --name tomcat02 yuanyuan/tomcat# tomcat01 ping tomcat-net-01
[root@localhost ~]# docker exec -it tomcat01 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

显然,tomcat01 ping tomcat-net-01,失败咯。


那么,tomcat01 要怎么联络上 mynet 呢?我们来研究一下 docker 中 network 的使用方法。

docker network --help# 发现了 connect 方法,连接一个容器到一个网络
[root@localhost ~]# docker network --help
Usage:  docker network COMMAND
Commands:connect     Connect a container to a network

测试连接 tomcat01 容器和 mynet 网络:

# 测试打通 tomcat01--mynet
docker network connect mynet tomcat01

现在再尝试 tomcat01 ping tomcat-net-01,会发现:成功了!

而且, tomcat01 不仅可以通信 tomcat-net-01,也可以通信 tomcat-net-02,tomcat01 可以和 mynet 中任何一个容器通信

但是,和 tomcat01 一起的 tomcat02 就依然不行。

# tomcat01 ping tomcat-net-01 可以
[root@localhost ~]# 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.115 ms# tomcat01 ping tomcat-net-02 可以
[root@localhost ~]# docker exec -it tomcat01 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.081 ms# tomcat02 ping tomcat-net-01 不行哦
[root@localhost ~]# docker exec -it tomcat02 ping tomcat-net-01
ping: tomcat-net-01: Name or service not known

3. 一个容器,两个 IP

这是怎么实现的呀?就是给 tomcat01 加了一个 IP,这个容器现在有两个 IP 地址了,一个在原来的 docker0 下,另一个在 mynet 下。

这就好比阿里云服务器,它有一个公网 IP 和一个私网 IP。

可以在 mynet 配置中查看 tomcat01 的配置信息:

docker network inspect mynet"Name": "tomcat01",
"IPv4Address": "192.168.0.4/16"

七、总结

本文介绍了 Docker 网络原理,介绍了 docker0,Veth-pair 技术,以及 Docker 给容器分配虚拟网卡的方式。同时讲述了两种容器互联的方式,分别是 Link 和 自定义网络。还有容器之间跨网络连通的方式。

一些参考资料

狂神说系列 Docker 教程:https://www.bilibili.com/video/BV1og4y1q7M4/
Docker 官方文档:https://docs.docker.com/engine/install/centos/
Docker 远程仓库:https://hub.docker.com/
FinalShell 下载:http://www.hostbuf.com/t/988.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/822247.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Unity HDRP 2023 Release-Notes

&#x1f308;Unity HDRP 2023 Release-Notes 本文信息收集来自自动搜集工具&#x1f448; 版本更新内容2023.2.17HDRP: Fixed game view flicker while on HDR and Reflection probe.(UUM-64343)2023.2.17HDRP: HDRP: Fixed invalid AABB error in the console when using th…

C# 截图并保存为图片

在winform开发中&#xff0c;有时会用到截图并保存为图片的时候&#xff0c;这里列了三种保存图片的可能情况。 将窗体截图保存成图片的方式是&#xff1a; Bitmap bit new Bitmap(this.Width, this.Height);//实例化一个和窗体一样大的bitmap Graphics g Graphics.FromImag…

Redis 核心知识点常考面试题(持续更新中)

Redis 核心知识点常考面试题&#xff08;持续更新中&#xff09; Redis单线程IO多路复用原理Redis缓存穿透、缓存雪崩、缓存击穿问题Redis与数据库双写不一致问题基于Redis实现分布式锁的的应用场景Redis持久化方式Redis内存淘汰机制Redis删除策略Redis主从复制、哨兵、集群Red…

AI时代的教育革命:智能教育的未来展望

人工智能技术正在以前所未有的速度和规模改变着我们的世界&#xff0c;而教育领域也不例外。本文将探讨人工智能在教育领域的应用现状和未来发展趋势&#xff0c;介绍智能教育的核心概念和关键技术&#xff0c;并通过案例分析和实践指南&#xff0c;展望智能教育的未来&#xf…

速盾:jquery可以用cdn加速吗?

CDN&#xff08;Content Delivery Network&#xff09;是一种优化网络传输的技术&#xff0c;通过将网站的相关静态资源缓存到全球各地的服务器节点上&#xff0c;可以加速网站的访问速度。jQuery是一款非常流行的JavaScript库&#xff0c;用于简化网页开发中的DOM操作、事件处…

回归损失函数

目录 1 MAE 2 MSE 3 MAPE 4 Quantile Loss分位数损失 回归损失函数也可以做为评价指标使用&#xff0c;但是有没有想过数据分布与损失函数之间的关系呢&#xff01; 使用特定损失函数的前提是我们对标签的分布进行了某种假设&#xff0c;在这种假设的前提下通过极大似然法推…

降低Altium Designer许可使用成本

在电子设计行业中&#xff0c;Altium Designer等EDA&#xff08;电子设计自动化&#xff09;软件是不可或缺的工具。然而&#xff0c;随着业务的增长&#xff0c;许可使用成本也成为企业关注的焦点。本文将探讨如何减少Altium Designer的许可使用成本&#xff0c;提高企业经济效…

GPT-3和自然语言处理的前沿:思考AI大模型的发展

引言 自然语言处理&#xff08;NLP&#xff09;是人工智能&#xff08;AI&#xff09;领域中最富有挑战性和活跃的研究领域之一。近年来&#xff0c;随着深度学习技术的发展和计算能力的提高&#xff0c;大型语言模型&#xff0c;尤其是OpenAI的GPT-3&#xff0c;已成为推动该…

基于微信小程序投票评选系统的设计与实现(论文+源码)_kaic

摘 要 社会发展日新月异&#xff0c;用计算机应用实现数据管理功能已经算是很完善的了&#xff0c;但是随着移动互联网的到来&#xff0c;处理信息不再受制于地理位置的限制&#xff0c;处理信息及时高效&#xff0c;备受人们的喜爱。所以各大互联网厂商都瞄准移动互联网这个潮…

攻防世界10-disabled_button

10-disabled_button 法1&#xff1a;修改html的标签内容 首先看题目描述提到前端知识&#xff0c;联想到HTML&#xff0c;提示是一个不能按的按钮&#xff0c;结合题目名button很明显是涉及到HTML button标签知识&#xff0c;最后通过disabled提示应该是按钮被禁用了 知识补充…

优橙内推重庆专场——5G网络优化(中高级)工程师

可加入就业QQ群&#xff1a;374637347 联系老师内推简历投递邮箱&#xff1a;hrictyc.com 内推公司1&#xff1a;北京电旗通讯技术股份有限公司 内推公司2&#xff1a;浙江明讯网络技术有限公司 内推公司3&#xff1a;杭州东信网络技术有限公司 北京电旗通讯技术股份有限公…

PySide QWebChannel实现Python与JS双向通信的前后端分离桌面应用

文章目录 一、前言二、实现方法1.前端部分2.后端部分3.依赖文件三、运行结果一、前言 以往开发桌面应用通常都是页面接口一起写,这样开发周期比较长,且页面样式不灵活,如果能把页面交给前端写的话,就可前后端并行开发桌面应用了,并且css语言灵活好用样式丰富。下面介绍一…

1990–2016年中国30米分辨率水稻种植分布数据集

本数据集为1990–2016年中国30米分辨率水稻种植分布数据集&#xff0c;覆盖范围包含中国大陆25个省级行政区。数据文件格式为GeoTIFF&#xff0c;地理参考为WGS84&#xff08;EPSG:4326&#xff09;&#xff0c;每年一个文件&#xff0c;文件名格式为 CCD-Rice-China-年份-v1.t…

嵌入式第四天:(C语言入门)

目录 什么是数组&#xff1f; 数组&#xff1a; 数组的使用&#xff1a; 数组的初始化&#xff1a; 数组名&#xff1a; 数组案例&#xff1a; 一维数组的最大值&#xff1a; 一维数组的逆置&#xff1a; 数组和指针&#xff1a; 通过指针操作数组元素&#xff1a; …

探索Python爬虫利器:Scrapy框架解析与实战

探索Python爬虫利器&#xff1a;Scrapy框架解析与实战 在当今信息时代&#xff0c;数据的价值不言而喻。而Python爬虫技术&#xff0c;作为获取网络数据的重要手段&#xff0c;已经成为了许多数据分析师、开发者和研究者必备的技能。本文将为您详细介绍Python爬虫技术中的利器—…

Opencv | 基于ndarray的基本操作

这里写目录标题 一. Opencv 基于ndarray的基本操作1. 浅拷贝2. np.copy ( ) 深拷贝3. 堆叠3.1 np.vstack ( ) 垂直方向堆叠3.2 np.hstack ( ) 水平方向堆叠 4. numpy创建图像5 np.transpose ( ) 更改维度顺序6. cv.resize ( ) 放大缩小7. np.clip ( ) 一. Opencv 基于ndarray的…

json样式对应的代码传递代码方式

对应格式&#xff1a;{“reg”:{“keyNumber”:“92100016”},“protect”:“b64”} { “reg”: { “keyNumber”: “xxxx” }, “protect”: “xxxx” } //推送接口 private void doPushKey(TbKeyManager keyManager) {TbPushkeyLog pushkeyLog new TbPushkeyLog();try {List…

30、JAVA双链表

双链表 题目描述 实现一个双链表&#xff0c;双链表初始为空&#xff0c;支持5种操作&#xff1a; (1) 在最左侧插入一个数&#xff1b; (2) 在最右侧插入一个数&#xff1b; (3) 将第k个插入的数删除&#xff1b; (4) 在第k个插入的数左侧插入一个数&#xff1b; (5) 在…

二刷大数据(二)- Spark

目录 SparkHadoop区别核心组件运行架构Master&WorkerApplication (Driver)Executor RDD概念yarn下工作原理算子依赖血缘关系阶段划分广播变量 shuffle流程SparkSQLDataSet、DataFrame、RDD相互转换 SparkStreaming Spark Spark是一种基于内存的快速、通用、可扩展的大数据…

为什么养猫圈更信赖进口生骨肉冻干?五款大卖榜单品控稳冻干首次分享

新手养猫人常常会有这样的疑问&#xff1a;为何进口生骨肉冻干价格如此昂贵&#xff0c;但仍有大量养猫达人对其推崇备至&#xff1f;与国产生骨肉冻干相比&#xff0c;进口产品的价格高出3-4倍之多&#xff0c;那么这高昂的价格背后&#xff0c;进口生骨肉冻干是否真的值得推荐…