首页 > 其他分享 >从Docker到Kubernetes

从Docker到Kubernetes

时间:2023-10-26 14:12:29浏览次数:44  
标签:kubectl Kubernetes kubernetes 容器 bootcamp 镜像 docker Docker

1 简介

1.1 什么是容器

传统的虚拟化技术,比如 VMWare, 目标是创建完整的虚拟机。为了运行应用,除了部署应用本身及其依赖(通常几十MB),还得安装整个操作系统(几十GB)。

如图所示,由于所有的容器共享同一个 Host OS,这使得容器在体积上要比虚拟机小很多。另外,启动容器不需要启动整个操作系统,所以容器部署和启动速度更快,开销更小,也更容易迁移。

1.2 为什么需要容器

简略回答是:容器使软件具备了超强的可移植能力

如今的系统在架构上较十年前已经变得非常复杂了。开发人员通常使用多种服务(比如 MQ,Cache,DB)构建和组装应用,而且应用很可能会部署到不同的环境,比如虚拟服务器,私有云和公有云。

一方面应用包含多种服务,这些服务有自己所依赖的库和软件包;另一方面存在多种部署环境,服务在运行时可能需要动态迁移到不同的环境中。这就产生了一个问题:如何让每种服务能够在所有的部署环境中顺利运行?

Docker 将集装箱思想,运用到软件打包上,为代码提供了一个基于容器的标准化运输系统。Docker 可以将任何应用及其依赖打包成一个轻量级、可移植、自包含的容器。容器可以运行在几乎所有的操作系统上。

容器意味着环境隔离和可重复性。开发人员只需为应用创建一次运行环境,然后打包成容器便可在其他机器上运行。另外,容器环境与所在的 Host 环境是隔离的,就像虚拟机一样,但更快更简单。

1.3 容器是如何工作的

Docker 的核心组件包括:

  • Docker 客户端 - Client

  • Docker 服务器 - Docker daemon

  • Docker 镜像 - Image

  • Registry 镜像仓库

  • Docker 容器 - Container

Docker 架构如下图所示:

Docker 采用的是 Client/Server 架构。客户端向服务器发送请求,服务器负责构建、运行和分发容器。客户端和服务器可以运行在同一个 Host 上,客户端也可以通过 socket 或 REST API 与远程的服务器通信。

1.4 案例:安装docker

1、windows 10+:

  • 安装Docker Desktop

  • 安装wsl_update (WSL2 Linux内核更新包)

  • 重启

2、Linux:

curl -fsSL https://get.docker.com/ | sh

# daocloud.io 国内镜像
curl -sSL https://get.daocloud.io/docker | sh

如何验证安装完成?

$ docker version
Client:
 Cloud integration: v1.0.29
 Version:           20.10.17
 API version:       1.41
 Go version:        go1.17.11
 Git commit:        100c701
 Built:             Mon Jun  6 23:09:02 2022
 OS/Arch:           windows/amd64
 Context:           default
 Experimental:      true

Server: Docker Desktop 4.12.0 (85629)
 Engine:
  Version:          20.10.17
  API version:      1.41 (minimum version 1.12)
  Go version:       go1.17.11
  Git commit:       a89b842
  Built:            Mon Jun  6 23:01:23 2022
  OS/Arch:          linux/amd64
  Experimental:     false
 containerd:
  Version:          1.6.8
  GitCommit:        9cd3357b7fd7218e4aec3eae239db1f68a5a6ec6
 runc:
  Version:          1.1.4
  GitCommit:        v1.1.4-0-g5fd4c4d
 docker-init:
  Version:          0.19.0
  GitCommit:        de40ad0

2 镜像

2.1 什么是镜像

可将 Docker 镜像视为只读模板,通过它可以创建 Docker 容器。例如某个镜像可能包含一个 Ubuntu 操作系统、一个用户开发的 Web 应用。

如何查看系统里已经存在的镜像?

$ docker images
REPOSITORY                                  TAG         IMAGE ID       CREATED        SIZE
busybox                                     latest      b18a6628e020   6 weeks ago    67.3MB
ubuntu                                      latest      08d22c0ceb15   7 weeks ago    77.8MB
centos                                      7           2661b85c5b47   9 months ago   645MB
apache/skywalking-oap-server                6.6.0-es7   60cf77fe2aee   3 years ago    194MB
apache/skywalking-ui                        6.6.0       da10535e9797   3 years ago    126MB
elasticsearch                               7.5.1       2bd69c322e98   3 years ago    779MB
hello-world                                 latest      a115c17f9b48   12 seconds ago   13.3kB
nginx                                       latest      6efc10a0510f   2 weeks ago      142MB

上图列出了本机所有的镜像列表,包含:ubuntu、elasticsearch等。

镜像有多种生成方法:

  1. 可以从无到有开始创建镜像;
  2. 也可以下载并使用别人创建好的现成的镜像;
  3. 还可以在现有镜像上创建新的镜像。

如果需要下载使用别人已经制作好的镜像,可以通过docker pull拉取:

docker pull alpine 
docker pull ubuntu 
docker pull apache/skywalking-ui 
docker pull busybox

未加域名前缀,默认从docker hub拉取。

2.2 基础镜像

base 镜像有两层含义:

  1. 不依赖其他镜像,从 scratch 构建 (scratch指的是空镜像,什么也没有)。
  2. 其他镜像可以之为基础进行扩展。

所以,能称作 base 镜像的通常都是各种 Linux 发行版的 Docker 镜像,比如 Ubuntu, Debian, CentOS 等。

我们以 Ubuntu 为例考察 base 镜像包含哪些内容。下载镜像:

$ docker pull ubuntu

查看镜像并运行:

$ docker images ubuntu
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
ubuntu       latest    08d22c0ceb15   7 weeks ago   77.8MB

$ docker run -it ubuntu /bin/bash

root@aca480369011:/# uname -r
5.10.16.3-microsoft-standard-WSL2

root@aca480369011:/# ls /
bin  boot  dev  etc  home  lib  lib32  lib64  libx32  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

我们发现ubuntu镜像只有77.8MB!这比直接安装ubuntu系统小多了。如果加上我们自己的应用程序,例如jar包及环境,大小也就几百M,对于应用程序移植来说简直是方便极了!

现在来看一下这个镜像为什么这么小。

众所周知,Linux 操作系统由内核空间和用户空间组成。如下图所示:

内核空间是 kernel,Linux 刚启动时会加载 bootfs 文件系统,之后 bootfs 会被卸载掉。用户空间的文件系统是 rootfs,包含我们熟悉的 /dev, /proc, /bin 等目录。对于 base 镜像来说,底层直接用 Host 的 kernel,自己只需要提供 rootfs 就行了。

而对于一个精简的 OS,rootfs 可以很小,只需要包括最基本的命令、工具和程序库就可以了。相比其他 Linux 发行版,CentOS 的 rootfs 已经算臃肿的了,alpine 还不到 10MB。

不同 Linux 发行版的区别主要就是 rootfs。所以 Docker 可以同时支持多种 Linux 镜像,模拟出多种操作系统环境。

2.3 常用镜像命令

# 搜索镜像 docker search [-s] IMAGE
docker search ubuntu 

# 下载镜像 docker pull [OPTIONS] NAME[:TAG|@DIGEST]
docker pull ubuntu:16.04

# 查看已下载镜像列表 docker images [-a]
docker images 

# 给镜像添加标签 docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
docker tag ubuntu:16.04 ubuntu

# 删除镜像 docker rmi [OPTIONS] IMAGE [IMAGE...]
docker rmi ubuntu:latest
docker rmi 12543ced0f6f

# 导出镜像 docker save [OPTIONS] IMAGE [IMAGE...]
docker save -o ubuntu_latest.tar ubuntu:latest

# 导入镜像
docker load --input ubuntu_latest.tar
docker load < ubuntu_latest.tar

# 从容器生成镜像
docker commit -m "create images" -a "yujc33"  2c74d574293f  yujc33/test:v1

3 容器

3.1 运行容器

Docker 容器就是 Docker 镜像的运行实例。(可以理解为java里的对象与Class的关系)

用户可以通过 CLI(docker)或是 API 启动、停止、移动或删除容器。可以这么认为,对于应用软件,镜像是软件生命周期的构建和打包阶段,而容器则是启动和运行阶段。

docker run -d --name getting-started -p 80:80 docker/getting-started

这里面我们运行了一个 Docker 容器,使用了 docker/getting-started 镜像。

-d 参数让容器以后台运行(detached 模式)。

--name 参数将容器命名为getting-started。省略该参数将随机命名。

-p 参数将主机的 80 端口与容器的 80 端口进行映射,允许通过主机的 IP 地址访问容器的 HTTP 服务。

因此,该命令会启动容器并将其连接到主机的端口80。容器的HTTP服务可以通过主机的 IP地址 访问, 例如 http://127.0.0.1

下面的命令可以查看所有的容器状态:

$ docker ps -a
CONTAINER ID   IMAGE                    COMMAND                  CREATED              STATUS                       PORTS                NAMES
a9f67b3f2b7f   docker/getting-started   "/docker-entrypoint.…"   About a minute ago   Up About a minute            0.0.0.0:80->80/tcp   compassionate_kare
2c1da9b06896   docker/getting-started   "/docker-entrypoint.…"   10 days ago          Exited (255) 3 minutes ago   0.0.0.0:80->80/tcp   exciting_blackwell

-a代表查看所有状态容器,去掉该参数则是表示仅查看运行中容器。STATUS是容器状态。

docker logs a9f67b3f2b7f

该命令用于查看容器内的标准输出。a9f67b3f2b7f是容器ID。

docker exec -it a9f67b3f2b7f /bin/sh         

该命令是在已经在运行的容器中执行一个交互式的 shell。-it 标志为执行一个交互式的终端操作,可以通过 shell 和命令行接口进行交互,/bin/sh 是要在容器中执行的命令行 shell。如果需要从容器中退出,则输入exit即可。

docker exec  a9f67b3f2b7f /bin/ls / 

该命令是在容器中执行/bin/ls / 命令。这也说明了我们不用进入shell交互界面也可以执行命令。

3.2 常用容器命令

create      创建容器  
run         运行容器(相当于create+start)  
pause       暂停容器  
unpause     取消暂停继续运行容器  
stop        发送 SIGTERM 停止容器  
kill        发送 SIGKILL 快速停止容器  
start       启动容器  
restart     重启容器  
attach      attach 到容器启动进程的终端  
exec        在容器中启动新进程,通常使用 "-it" 参数  
logs        显示容器启动进程的控制台输出,用 "-f" 持续打印  
rm          从磁盘中删除容器

3.3 容器资源限额

下面是对容器进行限额的一些示例:

# 允许该容器最多使用 200M 的内存和 100M 的 swap
docker run -m 200M --memory-swap=300M docker/getting-started

# 设置容器使用 CPU 的权重。如果不指定,默认值为 1024
# container_A 的 cpu share 1024,是 container_B 的两倍。当两个容器都需要 CPU 资源时,container_A 可以得到的 CPU 是 container_B 的两倍。这种按权重分配 CPU 只会发生在 CPU 资源紧张的情况下
docker run --name "container_A" -c 1024 docker/getting-started
docker run --name "container_B" -c 512 docker/getting-started

3.4 容器实现底层技术

容器底层是通过cgroup实现资源限额的,通过 namespace 实现资源隔离。

前面我们看到的 -m-c 实际上就是在配置 cgroup。我们可以在宿主机 /sys/fs/cgroup 中找到它。在 /sys/fs/cgroup/cpu/docker 目录中,Linux 会为每个容器创建一个 cgroup 目录,以容器长ID 命名:

图片

目录中包含所有与 cpu 相关的 cgroup 配置,文件 cpu.shares 保存的就是 --cpu-shares 的配置,值为 512。

同样的,/sys/fs/cgroup/memory/docker/sys/fs/cgroup/blkio/docker 中保存的是内存以及 Block IO 的 cgroup 配置。

在每个容器中,我们都可以看到文件系统,网卡等资源,这些资源看上去是容器自己的。Linux 实现这种方式的技术是 namespace。namespace 管理着 host 中全局唯一的资源,并可以让每个容器都觉得只有自己在使用它。换句话说,namespace 实现了容器间资源的隔离

Linux 使用了六种 namespace,分别对应六种资源:Mount、UTS、IPC、PID、Network 和 User。

  • Mount: 让容器看上去拥有整个文件系统。
  • UTS: 让容器有自己的 hostname。
  • IPC: 让容器拥有自己的共享内存和信号量(semaphore)来实现进程间通信,而不会与 host 和其他容器的 IPC 混在一起。
  • PID: 容器在 host 中以进程的形式运行。
  • Network: 让容器拥有自己独立的网卡、IP、路由等资源。
  • User: 让容器能够管理自己的用户,host 不能看到容器中创建的用户。

4 再探镜像

上文了解了镜像的基本操作,本节进一步了解镜像相关内容。

4.1 Dockerfile

我们可以将镜像的内容和创建步骤描述在一个文本文件中,这个文件被称作 Dockerfile,通过执行 docker build <docker-file> 命令可以构建出 Docker 镜像。

以官方的hello-world 镜像为例,它的Dockerfile文件内容:

# 此镜像是从白手起家,从 0 开始构建。
FROM scratch
# 将文件“hello”二进制文件复制到镜像的根目录。不依赖任何环境
COPY hello /
# 容器启动时,执行 /hello
CMD ["/hello"]

执行docker build -t hello-world ./ 就会构建出一个镜像,大小仅为13kb。

需要注意的是,Docker 会缓存已有镜像的镜像层,构建新镜像时,如果某镜像层已经存在,就直接使用,无需重新创建。如果我们希望在构建镜像时不使用缓存,可以在 docker build 命令中加上 --no-cache 参数。

Dockerfile 中每一个指令都会创建一个镜像层,上层是依赖于下层的。无论什么时候,只要某一层发生变化,其上面所有层的缓存都会失效。

下面列出了 Dockerfile 中最常用的指令,完整列表和说明可参看官方文档。

FROM
指定 base 镜像。

MAINTAINER
设置镜像的作者,可以是任意字符串。可选。

COPY
将文件从 build context 复制到镜像。
COPY 支持两种形式:

  1. COPY src dest
  2. COPY ["src", "dest"]

注意:src 只能指定 build context 中的文件或目录。

ADD
与 COPY 类似,从 build context 复制文件到镜像。不同的是,如果 src 是归档文件(tar, zip, tgz, xz 等),文件会被自动解压到 dest。

ENV
设置环境变量,环境变量可被后面的指令使用。例如:

...
ENV MY_VERSION 1.3
RUN apt-get install -y mypackage=$MY_VERSION
...

EXPOSE
指定容器中的进程会监听某个端口,Docker 可以将该端口暴露出来。

VOLUME
将文件或目录声明为 volume。

WORKDIR
为后面的 RUN, CMD, ENTRYPOINT, ADD 或 COPY 指令设置镜像中的当前工作目录。

RUN
在容器中运行指定的命令。

CMD
容器启动时运行指定的命令。
Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效。CMD 可以被 docker run 之后的参数替换。

ENTRYPOINT
设置容器启动时运行的命令。
Dockerfile 中可以有多个 ENTRYPOINT 指令,但只有最后一个生效。CMD 或 docker run 之后的参数会被当做参数传递给 ENTRYPOINT。

RUNCMDENTRYPOINT 这三个 Dockerfile 指令看上去很类似,很容易混淆。简单的说:

  1. RUN 执行命令并创建新的镜像层,RUN 经常用于安装软件包。
  2. CMD 设置容器启动后默认执行的命令及其参数,但 CMD 能够被 docker run 后面跟的命令行参数替换。
  3. ENTRYPOINT 配置容器启动时运行的命令。ENTRYPOINT 看上去与 CMD 很像,它们都可以指定要执行的命令及其参数。不同的地方在于 ENTRYPOINT 不会被忽略,一定会被执行,即使运行 docker run 时指定了其他命令。

比如下面的 Dockerfile 片段:

ENTRYPOINT ["/bin/echo", "Hello"]  
CMD ["world"]

当容器通过 docker run -it [image] 启动时,输出为:

Hello world

而如果通过 docker run -it [image] Docker启动,则输出为:

Hello Docker

最佳实践:

  1. 使用 RUN 指令安装应用和软件包,构建镜像。
  2. 如果 Docker 镜像的用途是运行应用程序或服务,比如运行一个 MySQL,应该优先使用 Exec 格式的 ENTRYPOINT 指令。CMD 可为 ENTRYPOINT 提供额外的默认参数,同时可利用 docker run 命令行替换默认参数。
  3. 如果想为容器设置默认的启动命令,可使用 CMD 指令。用户可在 docker run 命令行中替换此默认命令。

4.2 Dockerfile 多阶段构建

Docker 17.05版本以后,新增了Dockerfile多阶段构建。所谓多阶段构建,实际上是允许一个Dockerfile 中出现多个 FROM 指令。这样做有什么意义呢?

每一条 FROM 指令都是一个构建阶段,多条 FROM 就是多阶段构建,虽然最后生成的镜像只能是最后一个阶段的结果,但是,能够将前置阶段中的文件拷贝到后边的阶段中,这就是多阶段构建的最大意义。

最大的使用场景是将编译环境和运行环境分离,比如,之前我们需要构建一个Go语言程序,那么就需要用到go命令等编译环境,我们的Dockerfile可能是这样的:

FROM golang:1.10.3
COPY server.go /build/
WORKDIR /build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server
ENTRYPOINT ["/build/server"]

基础镜像 golang:1.10.3 是非常庞大的,因为其中包含了所有的Go语言编译工具和库,而运行时候我们仅仅需要编译后的 server 程序就行了,不需要编译时的编译工具,最后生成的大体积镜像就是一种浪费。

最后将编译接口拷贝到镜像中就行了,那么Dockerfile的基础镜像并不需要包含Go编译环境:

# 编译阶段
FROM golang:1.10.3
COPY server.go /build/
WORKDIR /build
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOARM=6 go build -ldflags '-w -s' -o server

# 运行阶段
FROM scratch
# 从编译阶段的中拷贝编译结果到当前镜像中
COPY --from=0 /build/server /
ENTRYPOINT ["/server"]

这个 Dockerfile 的玄妙之处就在于 COPY 指令的 --from=0 参数,从前边的阶段中拷贝文件到当前阶段中,多个FROM语句时,0代表第一个阶段。除了使用数字,我们还可以给阶段命名,比如:

# 编译阶段 命名为 builder
FROM golang:1.10.3 as builder

# ... 省略

# 运行阶段
FROM scratch

# 从编译阶段的中拷贝编译结果到当前镜像中
COPY --from=builder /build/server /

4.3 Registry

Registry 是存放 Docker 镜像的仓库,Registry 分私有和公有两种。

Docker Hub(https://hub.docker.com/) 是默认的 Registry,由 Docker 公司维护,上面有数以万计的镜像,用户可以自由下载和使用。

出于对速度或安全的考虑,我们也可以创建自己的私有 Registry。

  • docker pull 命令可以从 Registry 下载镜像。
  • docker run 命令则是先下载镜像(如果本地没有),然后再启动容器。
  • docker push 将镜像上传到 Registry。需要登录才能使用。
  • docker login 登录Registry。

5 容器平台技术:Kubernetes

5.1 Kubernetes是什么

Kubernetes (K8s) 是 Google 在 2014 年发布的一个开源项目。最初,Google 开发了一个叫 Borg 的系统(现在命令为 Omega)来调度如此庞大数量的容器和工作负载。在积累了这么多年的经验后,Google 决定重写这个容器管理系统,并将其贡献到开源社区,让全世界都能受益。这个项目就是 Kubernetes。简单的讲,Kubernetes 是 Google Omega 的开源版本。

目前 Kubernetes 已经成为发展最快、市场占有率最高的容器编排引擎产品。

与Docker的关系?

Kubernetes与Docker之间的关系可以说是相辅相成的。 Docker为Kubernetes提供了强大的容器运行时环境,而Kubernetes则为Docker容器提供了自动化管理和编排的能力。 简而言之,Docker解决了应用程序的打包和运行问题,而Kubernetes解决了应用程序的分布式管理和扩展问题。

5.2 创建 k8s 集群

这里创建的平台只是单机版的,仅用于学习测试,不适用生产环境。

方法一:启用Docker Desktop里的Kubernetes

  1. 打开 Docker Desktop,并在设置中启用 Kubernetes。

  2. 等待 Kubernetes 启动完成后,打开命令行工具(例如 PowerShell 或者 CMD),使用 kubectl 命令行工具连接到 Kubernetes 集群。可以使用以下命令检查 Kubernetes 是否已经启动:

kubectl cluster-info

如果输出类似于以下内容,则表示 Kubernetes 已经启动:

Kubernetes control plane is running at https://localhost:6443
KubeDNS is running at https://localhost:6443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy

方法二:安装minikube

https://github.com/kubernetes/minikube/releases/latest/download/minikube-windows-amd64.exe

minikube下载下来后,重命名为minikube,添加环境变量,无需安装,然后命令行执行minikube start,等待自动安装完成:

> minikube start --image-mirror-country='cn'

标签:kubectl,Kubernetes,kubernetes,容器,bootcamp,镜像,docker,Docker
From: https://www.cnblogs.com/52fhy/p/17789260.html

相关文章

  • Docker
    第一章初识Docker1.1符合标准1.0待补充的部分[root@master~]#yuminstallwgetnet-toolsvimyum-utils-yyum--config-manager--add-repohttps://download.docker.com/linux/centos/docker-ce.repo1.2安装docker删除系统可能存在的docker[root@master~]#y......
  • Kubernetes 100个常用命令
    转载https://mp.weixin.qq.com/s/pWj-ni5fuHLaK2AR-4gqqQ100个Kubectl命令,这些命令对于诊断Kubernetes集群中的问题非常有用。这些问题包括但不限于:• 集群信息• Pod诊断• 服务诊断• 部署诊断• 网络诊断• 持久卷和持久卷声明诊断• 资源......
  • 如何传递环境变量给Docker容器
    在Linux命令行中,可以使用-e选项来传递环境变量给Docker容器。这样,我们可以在运行容器的同时设置特定的环境变量,以满足应用程序的需求。下面将详细介绍如何使用Linux命令行传递环境变量给Docker容器。1、DockerRun命令:最常用的方法是在使用dockerrun命令时,通过-e选项传递环......
  • docker 日志处理
    手动清理cat/dev/null>*-json.log启动时添加配置dockerrun--log-driver=json-file--log-optmax-size=10mmy-container脚本#!/bin/shecho"====================startcleandockercontainerslogs=========================="logs=$(find/var/lib/docker/cont......
  • docker-compose部署SASL认证的kafka
    前言测试服务器:10.255.60.149一.编写docker-compose文件1.docker-compose.ymlversion:'3.8'services:zookeeper:image:wurstmeister/zookeepervolumes:-/data/zookeeper/data:/data-/home/docker-compose/kafka/config:/opt/zookeeper-......
  • docker buildx https
    :443:connect:connectionrefuseddockerbuildx指定了配置文件,使用http,但却未生效,它还是使用httpsloadmetadata源数据。目前解决方案:升级目标网址的证书为https解决。ps:猜测是因为镜像moby/buildkit:buildx-stable-1的原因,但是目前还没有证据。......
  • docker常用命令总结
    docker常用命令总结:#查看本地docker镜像dockerimages#拉取远程镜像到本地dockerpullpig4cloud/java:8-jre#删除本地docker镜像dockerrmi镜像ID#根据dockerfile构建docker容器dockerbuild-tmes-md:0.3.#运行docker容器dockerrun-d-p8090:8090--ne......
  • 基于CentOS的Docker安装教程
    安装Docker详细步骤1.更新yum源sudoyumupdate2.卸载旧版本的Dockersudoyumremovedocker\docker-client\docker-client-latest\docker-common\docker-latest\docker-latest-......
  • docker相关命令
    一、概述主要记录一下常用的docker命令。参考博客二、命令说明1.docker相关命令1.启动dockersystemctlstartdocker2.停止dockersystemctlstopdocker3.重启dockersystemctlrestartdocker4.查看docker的状态systemctlstatusdocker5.开机启动docker......
  • CentOS_7安装docker
    CentOS_7安装dockerInstallDockerEngineonCentOS官网文档:https://docs.docker.com/engine/install/centos/#1更新依赖sudoyumupdate#2卸载旧docker及其依赖(如果有就执行)并删除资源sudoyumremovedocker\docker-client\......