【Docker】Docker镜像结构及自定义镜像,镜像上传仓库使用

一、引言

        Docker镜像是一个只读的Docker容器模板,含有启动Docker容器所需的文件系统结构及其内容,因此是启动一个Docker容器的基础。镜像的结构原理图大致分为四层:共享的内核层、基础镜像层、定制镜像层、可写容器层。

  1. 共享的内核层:每个Docker容器运行时都共享宿主机的内核,这样可以大大减少内存的开销。
  2. 基础镜像层:base镜像提供的是最小的linux发行版,其实就是linux的根/文件系统。
  3. 定制镜像层:基于基础镜像进行定制化,添加或删除某些内容,形成新的镜像。
  4. 可写容器层:当一个容器被运行时,实际上会在这最后一层上运行,因此这一层是可以写的,能对容器进行动态的改变。

采用分层结构的最大好处是“共享资源”,不同的镜像使用同一个镜像层的时候,文件系统便可以实现资源共享,只需要备份一次,节省空间。

二、镜像结构

自定义 Docker 镜像有很多用途,以下是一些主要的应用场景:

  1. 一致性环境:通过自定义镜像,您可以确保您的应用在不同的环境中(开发、测试、生产等)运行在完全一致的环境中。这可以避免"在我机器上可以运行"的问题。

  2. 快速部署:自定义镜像包含了运行应用所需的所有依赖,这使得部署过程变得非常快速和简单。只需运行一个命令,就可以在任何安装了 Docker 的机器上启动应用。

  3. 版本控制和回滚:每个 Docker 镜像都有一个唯一的标签,这使得版本控制变得非常简单。如果新版本的应用有问题,您可以很容易地回滚到旧版本的镜像。

  4. 微服务架构:在微服务架构中,每个服务都可以有自己的 Docker 镜像。这使得每个服务可以独立地更新和扩展,而不会影响其他服务。

  5. 持续集成/持续部署(CI/CD):在 CI/CD 管道中,自定义镜像可以用于构建、测试和部署应用。这使得整个开发过程更加自动化,提高了开发效率。

Ⅰ. 基本结构

Dockerfile 是一个文本文件,它包含了一组用户可以调用来创建镜像的指令。以下是 Dockerfile 的基本结构:

  1. FROM:指定基础镜像,所有操作都基于这个基础镜像。例如:FROM ubuntu:18.04

  2. LABEL:为镜像添加元数据及声明镜像的作者或者维护者的信息。

  3. RUN:在镜像中运行命令,这些命令会在新的层上创建新的镜像。例如:RUN apt-get update

  4. CMD:提供容器默认的可执行程序,可以包含可执行程序,也可以省略,如果省略,则必须在运行时通过命令行指定。例如:CMD ["executable","param1","param2"]

  5. EXPOSE:声明运行时容器提供服务的网络端口。例如:EXPOSE 8080

  6. ENV:设置环境变量。例如:ENV myName="John Doe" myDog=Rex\ The\ Dog

  7. ADD 和 COPY:将文件从 Docker 主机复制到 Docker 镜像中。ADD 有自动解压缩功能,COPY 则更为直接明了。

  8. ENTRYPOINT:配置容器启动后执行的命令,并且不会被 docker run 提供的参数覆盖。

  9. VOLUME:创建一个可以从本地主机或其他容器挂载的挂载点,一般用来存放数据库和需要保存的数据等。

  10. WORKDIR:设置工作目录,所有后续的操作(CMD、ENTRYPOINT、COPY 和 ADD)都会在这个目录下进行。

  11. USER:设置运行容器时的用户名或 UID。

  12. ONBUILD:当构建一个被继承的 Dockerfile 时运行命令,该指令添加到镜像中,稍后触发。

  13. MAINTAINER :用于声明镜像的作者或者维护者的信息,它可以为使用者提供一种联系镜像创建者的方式。

【注意i】MAINTAINER 从 Docker 1.13.0 开始,这个指令已经被标记为已废弃,推荐使用 LABEL 指令来替代。

如:

MAINTAINER John Doe <john.doe@example.com>

 如:

LABEL maintainer="John Doe <john.doe@example.com>"

LABEL 指令可以用于添加更多的元数据到镜像中,比如版本号、构建日期等等。

这些指令在 Dockerfile 中按照从上到下的顺序执行。每个指令都会在镜像上创建一个新的层,然后提交。

案例:

# 基于官方的 JDK 镜像
FROM openjdk:8-jdk
# 设置环境变量
ENV CATALINA_HOME /usr/local/tomcat
ENV PATH $CATALINA_HOME/bin:$PATH
# 安装 MySQL
RUN apt-get update && apt-get install -y mysql-server
# 安装 Tomcat
RUN mkdir -p "$CATALINA_HOME"
WORKDIR $CATALINA_HOME
RUN curl -O https://downloads.apache.org/tomcat/tomcat-8/v8.5.61/bin/apache-tomcat-8.5.61.tar.gz \
&& tar -xvf apache-tomcat-8.5.61.tar.gz \
&& rm apache-tomcat-8.5.61.tar.gz
# 暴露端口
EXPOSE 8080
# 启动 Tomcat
CMD ["catalina.sh", "run"]

这个 Dockerfile 会创建一个包含 JDK、MySQL 和 Tomcat 的 Docker 镜像。在构建镜像时,它会先从 Docker Hub 下载官方的 JDK 镜像作为基础镜像,然后安装 MySQL,接着下载并安装 Tomcat,最后设置启动命令为启动 Tomcat。

请注意,这只是一个基础示例,实际使用时可能需要根据具体需求进行修改和优化。例如,可能需要添加更多的环境变量,或者调整安装命令以适应特定的应用需求。

Ⅱ. 常用命令

以下是您提到的 Dockerfile 指令的详细解释:

  1. RUN:用于执行后面跟着的命令行命令。有两种格式:RUN <command>(shell 格式)和 RUN ["executable", "param1", "param2"](exec 格式)。

  2. ENV:用于设置环境变量。这些变量以 <key>=<value> 的形式存在,可以在容器中被脚本或程序调用。

  3. COPY:将来自 Dockerfile 所在目录的文件或目录复制到容器中的一个新位置。

  4. ADD:与 COPY 类似,但是 ADD 允许后面的源参数是一个 URL,或者在源文件是一个 tar 文件的情况下,可以自动解压缩这个 tar 文件。

  5. EXPOSE:用于声明容器运行时监听的网络端口。

  6. WORKDIR:用于设置 RUN、CMD、ENTRYPOINT、COPY 和 ADD 指令的工作目录。

  7. ONBUILD:当镜像被用作其他 Dockerfile 的基础镜像时,ONBUILD 指令将会被触发执行。

  8. USER:用于设置接下来的 RUN、CMD 和 ENTRYPOINT 指令运行时的 UID。

  9. VOLUME:用于在容器中创建一个挂载点,用于连接 Docker 主机和容器的文件系统。

容器启动时自动执行指令:

CMD 和 ENTRYPOINT 都是 Dockerfile 中用于指定容器启动时运行的命令的指令,但它们的用法和目的有所不同。

  1. CMD:CMD 指令用于提供容器运行时的默认命令及其参数。在启动容器时,我们可以覆盖这些默认的参数。CMD 在 Dockerfile 中只应被定义一次,如果定义了多次,只有最后一次的定义会生效。CMD 有两种格式:

    如果 Dockerfile 中同时存在 CMD 和 ENTRYPOINT,CMD 中的参数会被添加到 ENTRYPOINT 中,作为其参数。

    • CMD ["executable","param1","param2"](exec 格式,推荐)
    • CMD command param1 param2(shell 格式)
  2. ENTRYPOINT:ENTRYPOINT 的目的也是让容器以应用程序或服务的形式运行。与 CMD 不同,我们在启动容器时不能覆盖 ENTRYPOINT 指令提供的命令,但可以添加额外的参数。ENTRYPOINT 有两种格式:

    如果我们既想让容器以应用程序或服务的形式运行,又想让这些应用或服务接受参数,那么最好的做法是使用 ENTRYPOINT 和 CMD 一起使用,让 ENTRYPOINT 指定应用程序,而让 CMD 指定默认参数。

    • ENTRYPOINT ["executable", "param1", "param2"](exec 格式,推荐)
    • ENTRYPOINT command param1 param2(shell 格式)

三、自定义镜像

Ⅰ. 基本镜像

首先进入虚拟机并且用MobaXterm这个工具连接,进入后先查看docker的服务/进程有没有开:

输入命令:systemctl status docker   (查看docker的服务/进程)

以下是没有开启状态:

 以下是开启状态:

创建一个文件夹,来存放创建后的镜像,并且创建并编写 Dockerfile 文件。

创建文件夹:mkdir soft      (名称soft,可以自己修改)

进入文件夹:cd soft/

创建并编辑Dockerfile文件:vim Dockerfile    (文件名称不用改)

进入文件后,按 i 进入编辑模式,然后将以下粘贴上,在按Esc退出编辑模式,输入 :wq 

保存编写内容并且退出文件。 

Dockerfile文件中编写:

#1.指定基础镜像,并且必须是第一条指令
FROM  centos
#2.指明该镜像的作者和其电子邮件
MAINTAINER  CloudJun  "jun737x@163.com"
#3.在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录
WORKDIR  /test
#4.将文件从Docker主机复制到Docker镜像中
COPY spring.jar /test

创建编写完成后,通过 docker build 命令来创建镜像。

命令:

docker build -t spring:v1

创建语句 docker build -t ,创建后这个镜像的名称spring,这个镜像的版本为 v1 ( 版本可以自己定义,如:0.1,1.0,v1,v2都可以),其中的  . 表示在当前目录创建

再查看镜像:docker images 

进入:docker run -it spring:v1 (spring为镜像名称,后面的:v1是需要进入镜像的哪个版本)

之后看看当前目录是不是自己在Dockerfile文件中所设置的,及带进来的jar包是否存在

查看当前路径:pwd 

查看文件:ls 

Ⅱ. 进阶镜像

以上的镜像是不可以jar包中的项目运行的,因为镜像中没有jdk配置。

首先,需将本地的属于Linux的jdk和jre的压缩包拖到创建的文件夹中

如图:

以下我们来进行完善以上的缺陷: 

以下配置jdk,可以运行jar包项目

输入命令,编辑Dockerfile文件:vim Dockerfile   ,将原来的编写全部删除。

删除:进入后先将输入键到第一行,再输入数字(输入的数字是看不到的如:12),再按两下 d ,就会删除12行已编写的内容,当然输入13或者14就删除13或者14行,可以根据自己想删除多少行来进行输入

将以下编写的内容粘贴到Dockerfile文件中,按Esc退出编辑模式,输入 :wq 保存编写内容并且退出文件。 

#1.指定基础镜像,并且必须是第一条指令
FROM  centos
#2.指明该镜像的作者和其电子邮件
MAINTAINER  CloudJun  "jun737x@163.com"
#3.在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录
WORKDIR  /test
#4.将文件从Docker主机将jdk及jar包复制到Docker镜像中,自动将jdk的压缩包进行解压
COPY  spring.jar /test
ADD  jdk-8u221-linux-x64.tar.gz  /test
#5.将jdk解压后配置环境变量
ENV JAVA_HOME=/test/jdk1.8.0_221
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH
#6.容器启动时,需要执行的命令(执行jar包)
CMD java -jar spring.jar

如图(粘贴进去后全部注释了,可以手动删除前面的#解除注释): 

创建镜像:

docker build -t spring:v2

  

再查看镜像:

docker images

进入容器:

docker run -it spring:v2

      (这里会自动启动jar包)

已可以通过:

docker run -itd spring:v2

   (在后台运行)

再进入:docker exec -it 24696887b11eeb7ea229221e94f7b0cac03526551854319db80aef21b2d12ca4 bash

( 其中bash前面是运行后的编号,根据运行后的编号进入到该容器中)

查看jar及解压后的jdk,还可以输入命令查看jdk环境:echo $JAVA_HOME

以下配置jre,可以运行jar包项目及优化储存

输入命令,编辑Dockerfile文件:vim Dockerfile   ,将原来的编写全部删除。

将以下编写的内容粘贴到Dockerfile文件中,按Esc退出编辑模式,输入 :wq 保存编写内容并且退出文件。 

#1.指定基础镜像,并且必须是第一条指令
FROM  centos
#2.指明该镜像的作者和其电子邮件
MAINTAINER  CloudJun  "jun737x@163.com"
#3.在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录
WORKDIR  /test
#4.将文件从Docker主机jre包复制到Docker镜像中,自动将jdk的压缩包进行解压
COPY  spring.jar /test
ADD  jre-8u391-linux-x64.tar.gz  /test
#5.将jre解压后配置环境变量
ENV JAVA_HOME=/test/jre1.8.0_391
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH
#6.容器启动时,需要执行的命令(执行jar包)
CMD java -jar spring.jar

创建镜像:

docker build -t spring:v3

再查看镜像:

docker images

运行:

docker run -itd spring:v3

虽然储存的减少可能很小,但是当需要量上来是时候也是节省了大量的储存空间的。

Ⅲ. 完善镜像

需要将储存控制到很少可以使用这个镜像jeanblanchard/alpine-glibc,这个镜像所需的储存很少,而通过这个镜像自定义出来的镜像也会少很多。

首先需要下载这个镜像:

docker pull jeanblanchard/alpine-glibc

再查看镜像的信息:

docker images

可以看到所需的储存空间很少。

然后我们将指定的镜像修改为这个镜像将Dockerfile文件,再次镜像编辑为以下内容。

#1.指定基础镜像,并且必须是第一条指令
FROM  jeanblanchard/alpine-glibc
#2.指明该镜像的作者和其电子邮件
MAINTAINER  CloudJun  "jun737x@163.com"
#3.在构建镜像时,指定镜像的工作目录,之后的命令都是基于此工作目录,如果不存在,则会创建目录
WORKDIR  /test
#4.将文件从Docker主机jre包复制到Docker镜像中,自动将jdk的压缩包进行解压
COPY  spring.jar /test
ADD  jre-8u391-linux-x64.tar.gz  /test
#5.将jre解压后配置环境变量
ENV JAVA_HOME=/test/jre1.8.0_391
ENV CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
ENV PATH=$JAVA_HOME/bin:$PATH
#6.容器启动时,需要执行的命令(执行jar包)
CMD java -jar spring.jar

创建镜像:

docker build -t spring:v4

再查看镜像:

docker images

现在这样的需要的储存空间就相对少了一半,更加的节省了资源空间。

现在映射端口运行:

docker run -itd --name s1 -p 8080:8080 spring:v4

之后在主机浏览器中访问虚拟机IP的访问路径:IP地址:8080 

四、镜像上传仓库

首先需要在我们的阿里云账号中开启镜像仓库,点击用户左边的控制器,点击容器镜像服务ACR,点击实例列表,在其中点击创建个人版本的,企业版要米,创建后需要设置密码。

容器镜像服务 (aliyun.com)

之后将以上的登入凭证复制粘贴到虚拟机中执行命令,前面的$不用复制进去,之后会镜像密码的输入,是自己设置的容器镜像服务密码,以下说明登入成功:

创建仓库:在实例列表中点击命名空间——>之后创建命名空间即可

如图:

之后创建一个仓库,仓库名称可以自己取

有其中的之后也可以绑定到账号中去,这里没有就可以选择本地仓库 

之后将需要上传推送到仓库的镜像取个别名,在将这个镜像绑定为阿里云的仓库,阿里云仓库在镜像仓库的第三部的将镜像推送到Registry中有命令。

第一个命令为登入,第二个命令为绑定阿里云仓库,第三个命令为上传推送到仓库

现在我们将虚拟机中共的镜像删除,删除后可以在次重阿里仓库中拉取下来。

删除:

docker rmi

镜像名:v1   (v1版本号)

拉取下载命令:

docker pull

仓库中的创建名称:v1    

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

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

相关文章

【GAMES101】Lecture 08 图形管线(实时渲染管线)与纹理映射

目录 图形管线 纹理映射 图形管线 给我一个三维模型&#xff0c;给我一个光照条件&#xff0c;我就能够得出渲染的结果&#xff0c;这些东西合起来就是Graphics Pipeline&#xff0c;图形管线&#xff0c;闫神愿称之为实时渲染管线&#xff0c;那下面这个流程图就是这个渲染…

redisson的延时队列机制简述

概述 业务中经常会遇到一些延迟执行的需求&#xff1b;通常想到的都是rabbitmq或者rocketmq的延迟消息&#xff1b; 但是系统中不一定集成了mq&#xff0c;但为了控制分布式下的并发&#xff0c;一般redis都是有集成的&#xff1b; redis的key过期监听那个时间不准确&#xff…

GIS复试Tips(特别是南师大)

注&#xff1a;本文仅个人观点&#xff0c;仅供参考 在这提前㊗️24年考南师大GISer成功上岸&#xff01; 当然&#xff0c;考研是个考试&#xff0c;总有人顺利上岸&#xff0c;稳上岸或逆袭上岸&#xff0c;但可能也有人被刷&#xff0c;这是常态。 所以&#xff0c;㊗️你…

idea设置编辑器背景颜色

文章目录 一、Ided常用工具栏显示二、更改idea主题设置三、设置代码编辑器背景颜色为豆沙绿四、设置新项目 默认Jdk配置、maven配置1、settings for new projects2、structre for new projects 五、修改代码中注释的字体颜色六、设置编辑器字体大小七、文件编码的设置(可以设置…

DC-1靶机刷题记录

靶机下载地址&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1GX7qOamdNx01622EYUBSow?pwd9nyo 提取码&#xff1a;9nyo 参考答案&#xff1a; https://c3ting.com/archives/kai-qi-vulnhnbshua-tiDC-1.pdf【【基础向】超详解vulnhub靶场DC-1】 https://www.bilibi…

禅道:从安装到使用,一篇文章带你全面了解

博客前言&#xff1a; 在这个充满竞争和快节奏的世界里&#xff0c;项目管理已经成为了许多行业的关键环节。禅道作为一种功能强大、易用的项目管理工具&#xff0c;正在被越来越多的企业和团队所采用。它不仅能帮助我们高效地管理项目&#xff0c;还能提升团队协作和沟通的效…

为什么JavaScript中0.1 + 0.2 ≠ 0.3

JavaScript中的浮点数运算有时候会出现一点偏差。下面解释为什么0.1 0.2 ≠ 0.3,以及如果你需要精确运算应该怎么做。 如果1 2 3,那么为什么在JavaScript中0.1 0.2 ≠ 0.3?这个原因与计算机科学和浮点数运算有关。 我建议你打开浏览器的控制台,输入0.1 0.2来查看结果。…

带你学C语言-指针(4)

目录 ​编辑 ⚾0.前言 &#x1f3c0;1.回调函数 ⚽2.qsort &#x1f3c9;2.1 qsort函数的模拟实现 &#x1f3be;3.sizeof与strlen对比 &#x1f3be;4.结束语 ⚾0.前言 言C之言&#xff0c;聊C之识&#xff0c;以C会友&#xff0c;共向远方。各位CSDN的各位你们好啊&…

【JS逆向学习】36kr登陆逆向案例(webpack)

在开始讲解实际案例之前&#xff0c;大家先了解下webpack的相关知识 WebPack打包 webpack是一个基于模块化的打包&#xff08;构建&#xff09;工具, 它把一切都视作模块 webpack数组形式&#xff0c;通过下标取值 !function(e) {var t {};// 加载器 所有的模块都是从这个…

【RocketMQ每日一问】RocketMQ nameserver的作用是什么?

Name Server 在 Apache RocketMQ 集群中扮演着以下几个重要作用&#xff1a; 服务注册与发现&#xff1a; Name Server 负责管理和协调整个集群&#xff0c;维护集群中所有 Broker 的信息&#xff0c;包括 Broker 的 IP 地址、端口号、存储容量等。当 Producer 和 Consumer 需…

【消息队列】RocketMQ 生产和消费中的集群模式和广播模式

在消息队列系统中&#xff0c;生产者和消费者的模式通常包括集群模式和广播模式。这两种模式分别用于不同的场景&#xff0c;具有不同的特点和优势。 1. 集群模式&#xff08;Cluster Mode&#xff09;&#xff1a; 在集群模式下&#xff0c;多个相同角色的实例组成一个集群&…

太帅了 soeasy两行命令创建一个文件系统

看三遍 看三遍 看三遍 A file list program that supports multiple storage, powered by Gin and Solidjs. 翻译:一个支持多个存储的文件列表程序&#xff0c;由Gin和Solidjs提供支持。 1.安装 命令1:创建目录 mkdir -p /opt/alist 命令2:创建容器 docker run -d \ --res…

一天吃透Redis面试八股文

目录&#xff1a; Redis是什么&#xff1f;Redis优缺点&#xff1f;Redis为什么这么快&#xff1f;讲讲Redis的线程模型&#xff1f;Redis应用场景有哪些&#xff1f;Memcached和Redis的区别&#xff1f;为什么要用 Redis 而不用 map/guava 做缓存?Redis 数据类型有哪些&…

UE5 C++ 基础变量类型,关于框架的初级练习

一.创建自己的MyGameModed。并在其中设置好GamePlay框架。 1.创建MyGameState,MyGameState,MyHUD,MyPawn&#xff0c;MyPawn&#xff0c;MyPlayerController,MyPlayerState。 2.并在MyGameMode的头文件里面&#xff0c;把GmaeMode里的框架需要的框架类都包含进去。 3.写一个构…

用微服务快速开发框架实现流程化办公!

实现流程化办公&#xff0c;可以助力企业提升市场竞争力&#xff0c;从而实现数字化转型升级。微服务快速开发框架是提升办公协作效率的得力助手&#xff0c;流辰信息以市场为导向&#xff0c;坚持自主研发与创新&#xff0c;始终为行业的进步和发展贡献应有的力量。 1、流程化…

【EI会议征稿通知】2024年通信技术与软件工程国际学术会议 (CTSE 2024)

2024年通信技术与软件工程国际学术会议 (CTSE 2024) 2024 International Conference on Communication Technology and Software Engineering (CTSE 2024) 2024年通信技术与软件工程国际学术会议 (CTSE 2024)将于2024年03月15-17日在中国长沙举行。会议专注于通信技术与软件工…

LLaVA-Plus:多模态大模型的新突破

前言 随着AIGC技术的不断进步&#xff0c;各类多模态大模型&#xff08;MLM&#xff09;开始蓬勃发展。在这一领域中&#xff0c;LLaVA-Plus的推出无疑是一次重大突破。作为LLaVA团队的最新工作&#xff0c;LLaVA-Plus不仅继承了LLaVA的优秀特性&#xff0c;还在此基础上进行了…

ChatGPT提示词保姆级教程

现在越来越多提示词教程&#xff0c;本文列个清单&#xff0c;方便以后整理&#xff0c;不定期更新&#xff0c;欢迎关注留言&#xff01; 后续更新欢迎关注 提示词&#xff08;prompt&#xff09;出来后&#xff0c;被称为一个新的岗位诞生&#xff0c;面向提示词工程师。 …

dns正反解析配置

1.配置正向解析baidu.com 1、下载bind包 [rootlocalhost ~]# yum install bind -y 2、对配置文件修改 [rootlocalhost ~]# vim /etc/named.conf 3、对数据文件修改 [rootlocalhost ~]# vim /var/named/baidu 4、重启服务 [rootlocalhost ~]# systemctl restart named.service 5…

hash应用

目录 一、位图 1.1、引出位图 1.2、位图的概念 1.3、位图的应用 1.4、位图模拟实现 二、布隆过滤器 2.1、什么是布隆过滤器 2.2、布隆过滤器应用的场景 2.3、布隆过滤器的原理 2.4、布隆过滤器的查找 2.5、布隆过滤器的插入 2.6、布隆过滤器的删除 2.7、布隆过滤器…