2024-05-18
隐藏
00
请注意,本文编写于 390 天前,最后修改于 232 天前,其中某些信息可能已经过时。

目录

docker ps命令显示的Net I/O含义
AMD64 的含义
查看 Docker 容器运行的进程、镜像和相关元数据信息
一、查看容器运行的进程
二、查看容器的镜像信息
Docker 的端口映射及详细参数的作用
一、端口映射的概念
二、端口映射的方式
(一)使用 -p 或 --publish 参数
(二)在 Docker Compose 文件中配置
三、详细参数的作用
(一)指定 IP 地址
(二)协议指定
(三)范围端口映射
四、端口映射的注意事项
Docker 实现指定端口映射和随机端口映射
一、指定端口映射
二、随机端口映射
三、注意事项
Docker 实现容器数据卷挂载
一、数据卷挂载的概念
二、使用 -v 或 --volume 参数进行数据卷挂载
三、在 Docker Compose 文件中配置数据卷挂载
四、注意事项
Docker 的容器环境变量传递
一、使用 -e 或 --env 参数传递环境变量
二、在 Docker Compose 文件中配置环境变量
三、注意事项
Docker 容器的自动重启
一、使用 --restart 参数设置自动重启
二、在 Docker Compose 文件中设置自动重启
三、注意事项
容器的生命周期
一、创建阶段
二、运行阶段
三、暂停阶段
四、停止阶段
五、删除阶段
六、注意事项
容器生命周期逻辑图
Dockerfile 介绍
一、Dockerfile 规则
(一)指令格式
(二)指令顺序
(三)注释
(四)环境变量
二、构建过程
(一)读取 Dockerfile
(二)构建基础镜像(如果有 FROM 指令)
(三)执行指令
(四)生成最终镜像
三、例子
Docker 指令 FROM
一、语法
二、作用
(一)确定起点
(二)继承特性
三、例子
(一)使用官方镜像
(二)指定标签
四、注意事项
(一)选择合适的基础镜像
(二)版本管理
Docker 指令 MAINTAINER
一、语法
二、作用
三、例子
四、注意事项
Docker 指令 RUN 和 CMD
一、RUN指令
(一)语法
(二)作用
(三)例子
(四)注意事项
二、CMD指令
(一)语法
(二)作用
(三)例子
(四)注意事项
CMD 和 RUN 指令的区别
一、指令作用不同
(一)RUN指令
(二)CMD指令
二、执行时机不同
(一)RUN指令
(二)CMD指令
三、语法形式不同
(一)RUN指令
(二)CMD指令
四、数量限制不同
(一)RUN指令
(二)CMD指令
Docker 指令 EXPOSE
一、语法
二、作用
三、例子
四、注意事项
Dockerfile 中的 COPY 和 ADD
一、COPY
二、ADD
三、两者区别
(一)功能特性
(二)从 URL 下载
(三)自动解压
(四)推荐使用
Dockerfile 中的 VOLUME 和 WORKDIR
一、VOLUME
二、WORKDIR
三、两者区别
(一)功能不同
(二)作用范围不同
一、USER
二、ONBUILD
三、两者区别
(一)触发时机不同
(二)作用不同
一、LABEL
三、两者区别
(一)用途不同
(二)作用时机不同
(三)设置方式不同
一、dfimage 工具简介
二、安装 dfimage
三、使用步骤
四、注意事项
Docker 容器的数据管理
一、数据卷(Volumes)
二、绑定挂载(Bind mounts)
三、临时文件系统(Tmpfs mounts)
四、数据管理策略
五、总结
Docker 容器共享数据卷
一、数据卷共享的概念
二、共享数据卷的优势
三、创建共享数据卷
四、多个容器共享数据卷
五、注意事项
六、总结
Docker 数据备份和还原
一、数据备份的重要性
二、使用数据卷进行备份
三、还原数据
四、注意事项
五、总结
Docker NAT(bridge)模式
一、模式介绍
二、工作原理
三、优势
四、使用场景
五、注意事项
Docker None 模式
一、模式介绍
二、工作原理
三、优势
四、使用场景
五、注意事项
Docker Host 模式
一、模式介绍
二、工作原理
三、优势
四、使用场景
五、注意事项
Docker 联合网络(container)模式
一、模式介绍
二、工作原理
三、优势
四、使用场景
五、注意事项
禁止 swap 分区的含义
关闭 SELinux 的原因

docker ps命令显示的Net I/O含义

docker ps命令的输出中,Net I/O表示容器的网络输入/输出。

  • 网络输入(Network Input):指容器从网络接收的数据量。
    • 例如,如果容器正在从外部服务器下载文件,这个值会随着下载的数据量增加而增加。
  • 网络输出(Network Output):指容器向网络发送的数据量。
    • 比如,容器中的应用程序向其他服务发送请求或响应时,这个值会相应变化。

例如:

CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES NET I/O 123456789 apache "httpd -DFOREGROUND" 5 minutes ago Up 5 minutes 80/tcp myapache 100kB/50kB

这里表示该容器从启动到现在,网络输入为 100 千字节,网络输出为 50 千字节。

AMD64 的含义

AMD64 是一种 64 位的计算机处理器架构。它最初由 AMD 公司开发,现在也被广泛应用于英特尔等其他处理器厂商的产品中。

AMD64 架构具有以下特点:

  • 支持更大的内存寻址空间,可以处理更多的数据和运行更大型的程序。
  • 提供更高的性能和效率,能够更好地利用现代硬件资源。
  • 与 32 位架构相比,在处理复杂计算和大规模数据时具有明显优势。

除了 AMD64,还有其他一些常见的处理器架构:

  • x86:32 位的处理器架构,是个人电脑领域最广泛使用的架构之一。AMD64 可以兼容运行 x86 架构的程序。
  • ARM:主要用于移动设备和嵌入式系统的处理器架构。近年来,ARM 架构也在服务器和桌面电脑领域逐渐得到应用。
  • PowerPC:一种由 IBM、苹果等公司开发的处理器架构,曾经在服务器和工作站领域有广泛应用。

不同的处理器架构适用于不同的应用场景,选择合适的架构取决于具体的需求和使用环境。

查看 Docker 容器运行的进程、镜像和相关元数据信息

一、查看容器运行的进程

可以使用以下命令查看容器内运行的进程:

  • docker top <容器名称或 ID>:该命令会列出容器内正在运行的进程信息,包括进程 ID、用户、命令等。

例如:

docker top mycontainer UID PID PPID C STIME TTY TIME CMD root 1234 5678 0 Sep23 09:59 ? 00:00:00 /bin/bash

二、查看容器的镜像信息

  1. 通过 docker ps 命令:
    • docker ps 的输出中,有一列是 IMAGE,它显示了容器所使用的镜像名称。
    CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 123456789 nginx "nginx -g 'daemon off'" 5 minutes ago Up 5 minutes 80/tcp mynginx
  2. 使用 docker inspect 命令:
    • docker inspect <容器名称或 ID>可以获取容器的详细信息,其中包括镜像的详细信息。
    [ { "Id": "123456789", "Image": "nginx:latest", "ImageID": "sha256:abcdefghijklmnopqrstuvwxyz", ... } ]

三、查看容器的元数据信息

主要通过 docker inspect 命令来查看容器的元数据信息:

  • docker inspect <容器名称或 ID>:该命令会返回一个 JSON 格式的详细信息,包括容器的创建时间、网络配置、存储配置、环境变量等各种元数据。

例如:

[ { "Id": "123456789", "Created": "2024-09-23T09:30:00Z", "Path": "nginx", "Args": [ "-g", "daemon off" ], "State": { "Status": "running", "Running": true, "Paused": false, ... }, "NetworkSettings": { "Networks": { "bridge": { "IPAddress": "172.17.0.2", ... } } }, "Mounts": [], ... } ]

Docker 的端口映射及详细参数的作用

一、端口映射的概念

在 Docker 中,端口映射是将容器内运行的服务所使用的端口与宿主机的端口进行关联,使得外部可以通过访问宿主机的端口来访问容器内的服务。

二、端口映射的方式

(一)使用 -p--publish 参数

  1. 语法:docker run -p <宿主机端口>:<容器端口> <镜像名称>
    • 例如:docker run -p 8080:80 nginx,将宿主机的 8080 端口映射到容器内的 80 端口。
  2. 作用:
    • <宿主机端口>:外部可以通过访问宿主机的这个端口来访问容器内的服务。
    • <容器端口>:容器内服务实际使用的端口。

(二)在 Docker Compose 文件中配置

  1. docker-compose.yml 文件中,使用 ports 关键字进行端口映射配置。
    • 例如:
    yaml
    version: '3' services: web: image: nginx ports: - "8080:80"
  2. 作用:
    • 与使用 -p 参数类似,将指定服务的容器内端口映射到宿主机的相应端口。

三、详细参数的作用

(一)指定 IP 地址

  1. 使用 -p 参数时可以指定 IP 地址,例如:docker run -p 192.168.1.100:8080:80 nginx
  2. 作用:
    • 限制端口映射只对特定的 IP 地址生效。如果不指定 IP 地址,端口映射将对所有可用的网络接口生效。

(二)协议指定

  1. 可以在端口映射中指定协议,例如:docker run -p 8080:80/tcp nginx
  2. 作用:
    • 默认情况下,Docker 会自动检测端口的协议,但如果需要明确指定协议为 TCP 或 UDP,可以使用这种方式。

(三)范围端口映射

  1. 可以使用范围端口映射,例如:docker run -p 8080-8085:80 nginx
  2. 作用:
    • 将宿主机的连续端口范围映射到容器内的单个端口,适用于需要多个端口映射但容器内只有一个服务端口的情况。

四、端口映射的注意事项

  • 确保宿主机上的端口没有被其他进程占用,否则可能会导致端口冲突。
  • 当使用多个容器时,要注意端口的分配,避免不同容器之间的端口冲突。
  • 根据实际需求调整端口映射的配置,确保安全性和可用性。

Docker 实现指定端口映射和随机端口映射

一、指定端口映射

  1. 使用 -p--publish 参数进行指定端口映射。
    • 语法:docker run -p <宿主机端口>:<容器端口> <镜像名称>
    • 例如:docker run -p 8080:80 nginx,将宿主机的 8080 端口映射到容器内的 80 端口。
    • 作用:明确指定宿主机的一个特定端口与容器内的端口进行关联,外部可以通过访问宿主机的这个固定端口来访问容器内的服务。
  2. 在 Docker Compose 文件中配置指定端口映射。
    • docker-compose.yml 文件中,使用 ports 关键字进行指定端口映射配置。
    • 例如:
    yaml
    version: '3' services: web: image: nginx ports: - "8080:80"
    • 同样明确地将宿主机的 8080 端口映射到名为 web 服务的容器内的 80 端口。

二、随机端口映射

  1. 使用 -P 参数进行随机端口映射。
    • 语法:docker run -P <镜像名称>
    • 例如:docker run -P nginx,Docker 会随机选择一个宿主机的端口,并将容器内暴露的端口映射到这个随机端口上。
    • 作用:在某些情况下,不需要固定的端口映射,而是让 Docker 自动选择一个可用的端口进行映射。这样可以避免手动指定端口可能带来的冲突问题,同时也增加了一定的灵活性。

三、注意事项

  • 对于指定端口映射,要确保指定的宿主机端口没有被其他进程占用,否则会导致端口冲突。
  • 对于随机端口映射,需要通过 docker ps 命令或者其他方式查看实际映射的端口,以便外部能够正确访问容器内的服务。
  • 无论是指定端口映射还是随机端口映射,当使用多个容器时,都要注意容器之间的端口分配,避免不同容器之间的端口冲突。

Docker 实现容器数据卷挂载

数据卷挂载是 Docker 中非常重要的功能,它可以实现容器与宿主机之间的数据共享和持久化存储。

一、数据卷挂载的概念

将宿主机上的一个目录或文件挂载到容器中,使得容器可以访问宿主机上的文件系统,并且容器中的数据修改可以直接反映到宿主机上,反之亦然。

二、使用 -v--volume 参数进行数据卷挂载

  1. 语法:docker run -v <宿主机目录或文件>:<容器内目录或文件> <镜像名称>
    • 例如:docker run -v /host/data:/container/data nginx,将宿主机上的 /host/data 目录挂载到容器内的 /container/data 目录。
  2. 作用:
    • 实现数据共享:容器和宿主机可以通过挂载的数据卷共享数据。
    • 数据持久化:即使容器被删除,挂载的数据卷中的数据仍然存在于宿主机上,不会丢失。

三、在 Docker Compose 文件中配置数据卷挂载

  1. docker-compose.yml 文件中,使用 volumes 关键字进行数据卷挂载配置。
    • 例如:
    yaml
    version: '3' services: web: image: nginx volumes: - /host/data:/container/data
  2. 作用与使用 -v 参数类似,将宿主机上的目录或文件挂载到指定服务的容器中。

四、注意事项

  1. 确保宿主机上的目录或文件存在且具有适当的权限,以便容器可以正确访问。
  2. 当挂载目录时,容器内的目录如果已经存在,其中的内容可能会被覆盖。
  3. 如果需要在不同的容器之间共享数据卷,可以使用相同的挂载路径进行配置。
  4. 对于重要的数据,建议定期备份挂载的数据卷,以防止数据丢失。

Docker 的容器环境变量传递

在 Docker 中,可以通过环境变量向容器传递配置信息,使得容器在运行时能够根据不同的环境变量值进行相应的配置调整。

一、使用 -e--env 参数传递环境变量

  1. 语法:docker run -e <环境变量名>=<环境变量值> <镜像名称>
    • 例如:docker run -e APP_ENV=production nginx,向容器传递了一个名为 APP_ENV,值为 production 的环境变量。
  2. 作用:
    • 灵活配置:可以根据不同的需求传递不同的环境变量值,从而实现容器的灵活配置。
    • 避免硬编码:避免在容器内部硬编码配置信息,提高容器的可移植性。

二、在 Docker Compose 文件中配置环境变量

  1. docker-compose.yml 文件中,使用 environment 关键字进行环境变量配置。
    • 例如:
    yaml
    version: '3' services: web: image: nginx environment: APP_ENV: production DB_HOST: db.example.com
  2. 作用:
    • 集中管理:可以在一个地方集中管理多个环境变量,方便维护。
    • 与多个容器共享:可以在多个容器中共享相同的环境变量配置。

三、注意事项

  1. 注意环境变量的命名规范,避免使用特殊字符和保留字。
  2. 对于敏感信息,可以考虑使用 Docker 的加密环境变量或者其他安全机制来传递。
  3. 在容器内部,可以通过读取环境变量的方式获取配置信息,不同的编程语言有不同的方法来读取环境变量。例如,在 Bash 脚本中可以使用 $ENV_VARIABLE_NAME 的方式获取环境变量值,在 Python 中可以使用 os.environ['ENV_VARIABLE_NAME'] 的方式获取。

Docker 容器的自动重启

在 Docker 中,可以设置容器在退出后自动重启,以确保容器的持续运行。

一、使用 --restart 参数设置自动重启

  1. 语法:docker run --restart=<重启策略> <镜像名称>
    • 例如:docker run --restart=always nginx,设置容器在退出后始终自动重启。
  2. 重启策略有以下几种:
    • no:默认值,不自动重启容器。
    • on-failure[:max-retries]:仅在容器以非零退出码退出时自动重启。可以指定最大重试次数,例如 on-failure:5 表示在容器以非零退出码退出时最多自动重启 5 次。
    • always:无论容器以何种方式退出,都自动重启容器。

二、在 Docker Compose 文件中设置自动重启

  1. docker-compose.yml 文件中,使用 restart 关键字进行自动重启配置。
    • 例如:
    yaml
    version: '3' services: web: image: nginx restart: always
  2. 作用与使用 --restart 参数类似,设置指定服务的容器在退出后自动重启。

三、注意事项

  1. 自动重启可能会掩盖容器内部的问题,因此在设置自动重启时,应该同时监控容器的日志,以便及时发现和解决问题。
  2. 如果容器的启动需要一些外部条件(例如网络连接、数据库可用等),自动重启可能会导致容器在不满足条件时不断尝试启动,从而消耗系统资源。在这种情况下,可以考虑使用延迟启动或者依赖关系管理来确保容器在合适的时机启动。
  3. 对于重要的容器,建议设置监控和报警机制,以便在容器出现问题时及时收到通知。

容器的生命周期

容器的生命周期包括创建、运行、暂停、停止和删除等阶段。

一、创建阶段

  1. 使用 docker run 命令或者 docker-compose up 命令创建容器。
    • 在这个阶段,Docker 会根据指定的镜像创建一个新的容器,并为其分配资源。
  2. 可以通过传递参数来配置容器的各种属性,如环境变量、端口映射、数据卷挂载等。

二、运行阶段

  1. 容器创建后,进入运行状态。
    • 在这个阶段,容器中的应用程序开始执行。
  2. 可以通过 docker ps 命令查看正在运行的容器。

三、暂停阶段

  1. 使用 docker pause 命令可以暂停容器的运行。
    • 在暂停状态下,容器中的进程被挂起,不会占用 CPU 资源,但容器的内存和文件系统状态仍然保留。
  2. 可以使用 docker unpause 命令恢复容器的运行。

四、停止阶段

  1. 使用 docker stop 命令可以停止容器的运行。
    • 在停止状态下,容器中的进程被终止,容器占用的资源被释放。
  2. 可以使用 docker start 命令重新启动已停止的容器。

五、删除阶段

  1. 使用 docker rm 命令可以删除容器。
    • 删除容器后,容器的所有数据和状态都将被清除。
  2. 在删除容器之前,确保不再需要容器中的数据或者已经对重要数据进行了备份。

六、注意事项

  1. 在容器的不同生命周期阶段,需要注意数据的备份和恢复,以免数据丢失。
  2. 合理管理容器的生命周期,避免不必要的资源浪费和混乱。
  3. 对于长期运行的容器,需要定期监控和维护,确保其正常运行。

容器生命周期逻辑图

image.png

Dockerfile 介绍

一、Dockerfile 规则

(一)指令格式

  • 每条指令独占一行,指令通常由指令名称和参数组成。例如:FROM ubuntu:latest

(二)指令顺序

  • 指令的顺序很重要,因为 Docker 会按照顺序依次执行指令来构建镜像。一般来说,FROM 指令应该放在最前面,然后是其他指令。

(三)注释

  • 可以使用 # 进行注释,方便理解 Dockerfile 的内容。

(四)环境变量

  • 可以使用 ENV 指令设置环境变量,这些变量可以在后续的指令中使用。例如:ENV MY_VAR value

二、构建过程

(一)读取 Dockerfile

  • Docker 引擎读取 Dockerfile 文件,解析其中的指令。

(二)构建基础镜像(如果有 FROM 指令)

  • 根据 FROM 指令指定的基础镜像,如果本地没有该镜像,Docker 会从镜像仓库中拉取。

(三)执行指令

  • 按照顺序依次执行每条指令,如 RUNCOPYADD 等指令,每执行一条指令都会创建一个新的镜像层。

(四)生成最终镜像

  • 当所有指令执行完毕后,Docker 会生成一个最终的镜像,可以使用这个镜像来创建容器。

三、例子

以下是一个简单的 Dockerfile 例子,用于构建一个包含 Nginx 的镜像:

dockerfile
# 基础镜像为最新的 Ubuntu FROM ubuntu:latest # 安装 Nginx RUN apt-get update && apt-get install -y nginx # 将本地的 index.html 文件复制到镜像中的 Nginx 网页目录 COPY index.html /usr/share/nginx/html/ # 暴露 80 端口 EXPOSE 80 # 容器启动时运行 Nginx CMD ["nginx", "-g", "daemon off;"]

假设在与 Dockerfile 同一目录下有一个 index.html 文件,构建镜像的命令如下:

docker build -t mynginx:v1.

这个例子首先以 Ubuntu 镜像为基础,安装 Nginx,复制一个自定义的 index.html 文件到 Nginx 网页目录,暴露 80 端口,并指定容器启动时运行 Nginx。 image.png

Docker 指令 FROM

FROM 是 Dockerfile 中最重要的指令之一,它用于指定构建镜像的基础镜像。

一、语法

FROM <image>FROM <image>:<tag>

二、作用

(一)确定起点

  • 为构建新的镜像提供一个基础。基础镜像可以是官方提供的镜像,如 ubuntunginx 等,也可以是自己构建的镜像。

(二)继承特性

  • 新构建的镜像会继承基础镜像的一些特性,如操作系统、已安装的软件、环境变量等。

三、例子

(一)使用官方镜像

dockerfile
FROM ubuntu:latest

这个例子使用最新的 Ubuntu 官方镜像作为基础镜像。

(二)指定标签

dockerfile
FROM nginx:1.21.6

这里指定使用 Nginx 版本为 1.21.6 的镜像作为基础镜像。

四、注意事项

(一)选择合适的基础镜像

  • 应根据实际需求选择合适的基础镜像,考虑镜像的大小、安全性、稳定性等因素。

(二)版本管理

  • 如果基础镜像有多个版本,应明确指定版本号,以确保构建的可重复性和稳定性。避免使用 latest 标签,因为它可能会随着时间变化而指向不同的版本。

Docker 指令 MAINTAINER

MAINTAINER指令在较旧版本的 Dockerfile 中用于指定镜像的维护者信息。

一、语法

MAINTAINER <name>

二、作用

  • 标明镜像的维护人员是谁,通常包括维护者的姓名和联系方式等信息。

三、例子

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

这个例子指定镜像的维护者为“John Doe”,联系邮箱为“john.doe@example.com”。

四、注意事项

  • 从 Docker 1.13 开始,推荐使用LABEL maintainer=<name>来替代MAINTAINER指令。这样可以更好地与其他元数据标签一起管理,并且更符合标签化的规范。

Docker 指令 RUNCMD

一、RUN指令

(一)语法

RUN <command>

(二)作用

  • 在构建镜像的过程中执行命令。可以用于安装软件包、配置环境等操作。每次执行RUN指令都会创建一个新的镜像层。

(三)例子

  1. 安装软件
    dockerfile
    RUN apt-get update && apt-get install -y nginx
    这个例子在构建镜像时更新软件源并安装 Nginx。
  2. 创建目录
    dockerfile
    RUN mkdir /data
    创建一个名为/data的目录。

(四)注意事项

  • 尽量将多个命令组合在一起执行,以减少镜像的层数。例如,使用&&连接多个命令。

二、CMD指令

(一)语法

  1. CMD ["executable","param1","param2"](推荐形式,被执行的是可执行文件)
  2. CMD ["param1","param2"](设置了ENTRYPOINT时,此形式为给ENTRYPOINT传递参数)
  3. CMD command param1 param2(在 shell 中执行命令,会被 shell 解释)

(二)作用

  • 定义容器启动时默认执行的命令。如果在运行容器时指定了其他命令,将会覆盖CMD指定的命令。

(三)例子

  1. 启动 Nginx
    dockerfile
    CMD ["nginx", "-g", "daemon off;"]
    容器启动时启动 Nginx 服务。
  2. 运行脚本
    dockerfile
    CMD ["/bin/bash", "/start.sh"]
    启动容器时运行start.sh脚本。

(四)注意事项

  • 一个 Dockerfile 中只能有一个有效的CMD指令,如果有多个,只有最后一个会生效。

CMDRUN 指令的区别

一、指令作用不同

(一)RUN指令

  • RUN指令在构建镜像的过程中执行命令,用于安装软件包、配置环境等操作。每次执行RUN指令都会创建一个新的镜像层。
  • 例如:
    dockerfile
    RUN apt-get update && apt-get install -y nginx
    这个例子在构建镜像时更新软件源并安装 Nginx。

(二)CMD指令

  • CMD指令定义容器启动时默认执行的命令。如果在运行容器时指定了其他命令,将会覆盖CMD指定的命令。
  • 例如:
    dockerfile
    CMD ["nginx", "-g", "daemon off;"]
    容器启动时启动 Nginx 服务。

二、执行时机不同

(一)RUN指令

  • 在构建镜像的时候执行。

(二)CMD指令

  • 在容器启动的时候执行。

三、语法形式不同

(一)RUN指令

  • RUN <command>,通常是一个 shell 命令或者一系列用&&等连接的命令。

(二)CMD指令

  1. CMD ["executable","param1","param2"](推荐形式,被执行的是可执行文件)。
  2. CMD ["param1","param2"](设置了ENTRYPOINT时,此形式为给ENTRYPOINT传递参数)。
  3. CMD command param1 param2(在 shell 中执行命令,会被 shell 解释)。

四、数量限制不同

(一)RUN指令

  • 可以在一个 Dockerfile 中有多个RUN指令,每个RUN指令都会创建一个新的镜像层。

(二)CMD指令

  • 一个 Dockerfile 中只能有一个有效的CMD指令,如果有多个,只有最后一个会生效。

Docker 指令 EXPOSE

一、语法

EXPOSE <port>

二、作用

  • 告知 Docker 容器在运行时监听的端口。这个指令并不真正地打开端口,只是作为一种文档说明,让使用者知道容器内的应用程序打算使用哪些端口进行通信。
  • 有助于在使用 Docker 时进行端口映射和容器间的网络通信规划。

三、例子

dockerfile
EXPOSE 80

这个例子表示容器内的应用程序可能会在端口 80 上进行通信。

四、注意事项

  • EXPOSE只是一种声明,要使容器的端口能被外部访问,还需要在运行容器时使用 -p-P 参数进行端口映射。例如:docker run -p 8080:80 <image_name> 将容器的 80 端口映射到主机的 8080 端口。

Dockerfile 中的 COPYADD

一、COPY

  1. 语法COPY <src>... <dest>
  2. 作用
    • 将本地文件或目录复制到镜像中。只能从构建上下文(通常是当前目录或指定的路径)复制文件。
    • 通常用于将应用程序代码、配置文件等复制到镜像中。
  3. 例子
    dockerfile
    COPY app/ /app/
    这个例子将本地目录app中的内容复制到镜像中的/app/目录下。

二、ADD

  1. 语法ADD <src>... <dest>
  2. 作用
    • 功能类似于COPY,但ADD具有一些额外的功能:
      • 可以从 URL 下载文件并复制到镜像中。
      • 可以自动解压归档文件(如 .tar, .tar.gz等)。
  3. 例子
    • 从本地复制文件:
      dockerfile
      ADD config.txt /config/
    • 从 URL 下载文件:
      dockerfile
      ADD https://example.com/archive.tar.gz /app/
    • 自动解压归档文件:
      dockerfile
      ADD archive.tar.gz /app/
      如果archive.tar.gz是一个归档文件,它将被自动解压到/app/目录下。

三、两者区别

(一)功能特性

  • ADDCOPY功能更强大,但有时这种强大的功能可能会带来一些不确定性。如果只是简单地复制本地文件或目录,COPY是更明确和可靠的选择。

(二)从 URL 下载

  • ADD可以从 URL 下载文件,而COPY不能。但在实际使用中,从 URL 下载文件可能会带来一些风险,比如下载的文件可能不可靠或者在构建过程中可能会因为网络问题导致构建失败。

(三)自动解压

  • ADD可以自动解压归档文件,而COPY不能。同样,自动解压功能可能会在一些情况下带来意外的结果,比如不知道解压后的文件结构或者解压过程中出现错误。

(四)推荐使用

  • 一般情况下,如果只是复制本地文件或目录,建议使用COPY。只有在确实需要从 URL 下载文件或自动解压归档文件时,才考虑使用ADD

Dockerfile 中的 VOLUMEWORKDIR

一、VOLUME

  1. 语法VOLUME ["/path/to/directory"]
  2. 作用
    • 创建一个具有特定名称的挂载点,并将其标记为供容器使用的卷。这意味着容器在运行时可以将数据存储在这个卷中,并且即使容器被删除,卷中的数据也可以保留下来。
    • 通常用于存储数据库数据、日志文件或其他需要在容器之间共享或持久化的数据。
  3. 例子
    dockerfile
    VOLUME /data
    这个例子创建了一个名为/data的卷,容器可以将数据存储在这个目录中。

二、WORKDIR

  1. 语法WORKDIR /path
  2. 作用
    • 设置工作目录,即容器内命令运行的默认目录。
    • 后续的指令(如RUNCOPY等)如果没有指定绝对路径,将相对于这个工作目录执行。
  3. 例子
    dockerfile
    WORKDIR /app RUN pwd
    在这个例子中,RUN pwd命令将输出/app,因为工作目录被设置为/app

三、两者区别

(一)功能不同

  • VOLUME主要用于数据持久化和共享,为容器提供一个可挂载的存储位置。
  • WORKDIR用于设置容器内的工作目录,决定后续指令的执行路径。

(二)作用范围不同

  • VOLUME影响数据存储和容器与外部的存储交互。
  • WORKDIR只在容器内部起作用,影响指令的执行路径和文件操作的相对路径。

Dockerfile 中的 USERONBUILD

一、USER

  1. 语法USER <user>[:<group>]USER <UID>[:<GID>]
  2. 作用
    • 指定容器内运行进程的用户。可以是用户名、用户 ID 或者用户名和组名(或用户 ID 和组 ID)的组合。
    • 有助于提高容器的安全性,避免以 root 用户运行容器内的进程,减少潜在的安全风险。
  3. 例子
    dockerfile
    USER appuser
    这个例子指定容器内的进程以用户appuser运行。

二、ONBUILD

  1. 语法ONBUILD <instruction>
  2. 作用
    • ONBUILD指令在当前镜像被用作基础镜像构建新镜像时触发执行特定的指令。
    • 通常用于在基础镜像中定义一些构建步骤,这些步骤在基于该基础镜像构建新镜像时自动执行。
  3. 例子
    dockerfile
    ONBUILD COPY. /app ONBUILD RUN npm install
    在这个例子中,当以这个镜像为基础镜像构建新镜像时,首先会将构建上下文(通常是当前目录)复制到新镜像的/app目录下,然后执行npm install命令。

三、两者区别

(一)触发时机不同

  • USER在容器启动时生效,决定容器内进程的运行用户。
  • ONBUILD在当前镜像被用作基础镜像构建新镜像时触发执行特定指令。

(二)作用不同

  • USER主要用于设置容器内进程的运行用户,以提高安全性或满足特定的权限需求。
  • ONBUILD用于在基础镜像中定义一些构建步骤,为基于该基础镜像构建新镜像提供一些预设的操作。

Dockerfile 中的 LABELARG

一、LABEL

  1. 语法LABEL <key>=<value>
  2. 作用
    • 为镜像添加元数据标签。这些标签可以包含各种信息,如作者、版本、描述、维护者等。
    • 可以用于帮助组织和管理镜像,也可以被工具和系统用来识别和筛选特定的镜像。
  3. 例子
    dockerfile
    LABEL maintainer="John Doe" LABEL version="1.0" LABEL description="This is a sample image"

二、ARG

  1. 语法ARG <name>[=<default value>]
  2. 作用
    • 定义在构建过程中可以传递的参数。这些参数可以在构建镜像时通过命令行进行设置,从而允许在不同的构建场景中灵活地配置镜像的构建过程。
    • 例如,可以使用ARG来定义软件的版本号,然后在构建时根据需要传递不同的版本值。
  3. 例子
    dockerfile
    ARG version RUN echo "Building version $version"
    在这个例子中,构建镜像时可以通过--build-arg version=<value>来传递一个版本号,然后在构建过程中使用这个版本号进行一些操作。

三、两者区别

(一)用途不同

  • LABEL用于为镜像添加静态的元数据信息,这些信息在镜像构建完成后不会改变。
  • ARG用于定义在构建过程中可变的参数,允许根据不同的构建需求进行灵活配置。

(二)作用时机不同

  • LABEL在镜像构建过程中添加标签,并且这些标签在镜像的整个生命周期中都存在。
  • ARG在构建开始时定义参数,但这些参数只在构建过程中有效,一旦镜像构建完成,它们不会影响镜像的运行。

(三)设置方式不同

  • LABEL的值在 Dockerfile 中直接指定。
  • ARG的值可以在 Dockerfile 中指定一个默认值,但在构建时可以通过命令行参数进行覆盖。

使用 dfimage 工具从 Docker 镜像提取 Dockerfile

一、dfimage 工具简介

dfimage 是一个用于分析 Docker 镜像的工具。它可以提供关于镜像的详细信息,包括从镜像中提取近似的 Dockerfile。

二、安装 dfimage

通常可以通过以下方式安装 dfimage:

  1. 对于不同的操作系统和环境,可能有不同的安装方法。
  2. 可以查看 dfimage 的官方文档获取具体的安装步骤。

三、使用步骤

  1. 首先,确定要提取 Dockerfile 的镜像名称或 ID。
    • 可以使用 docker images 命令查看本地已有的镜像列表。
  2. 然后,使用 dfimage 工具提取 Dockerfile。
    • 假设镜像名为 myimage,可以运行以下命令: dfimage myimage
    • 该命令将输出关于镜像的信息,其中可能包括近似的 Dockerfile。

四、注意事项

  1. 提取的 Dockerfile 可能不是完全与原始的 Dockerfile 相同,但可以提供一个很好的近似。
  2. 某些复杂的构建步骤可能无法完全准确地提取出来。
  3. 该工具的输出应该作为参考,而不是完全替代原始的 Dockerfile。

Docker 容器的数据管理

一、数据卷(Volumes)

  1. 定义:数据卷是一个可供一个或多个容器使用的特殊目录,绕过了 Union File System,可以提供一些用于持续存储和共享数据的功能。
  2. 作用
    • 数据卷可以在容器之间共享数据,也可以在容器和主机之间共享数据。
    • 数据卷可以在容器被删除后仍然保留数据,确保数据的持久性。
  3. 创建方式
    • 在运行容器时使用 -v--mount 参数来创建数据卷。
    • 例如:docker run -v /host/path:/container/path image_name

二、绑定挂载(Bind mounts)

  1. 定义:将主机上的文件或目录挂载到容器中。
  2. 作用
    • 可以方便地在容器和主机之间共享文件或目录。
    • 可以使用主机上已有的文件或目录作为容器的数据存储。
  3. 创建方式
    • 在运行容器时使用 -v 参数指定主机路径和容器路径。
    • 例如:docker run -v /host/path:/container/path image_name

三、临时文件系统(Tmpfs mounts)

  1. 定义:将数据存储在容器的内存中,而不是磁盘上。
  2. 作用
    • 可以提高数据的读写速度,特别是对于频繁读写的临时数据。
    • 可以避免在磁盘上存储敏感数据,提高安全性。
  3. 创建方式
    • 在运行容器时使用 --tmpfs 参数指定容器路径。
    • 例如:docker run --tmpfs /container/path image_name

四、数据管理策略

  1. 选择合适的数据管理方式:
    • 根据应用的需求选择数据卷、绑定挂载或临时文件系统。
    • 如果需要数据的持久性和可共享性,数据卷是一个不错的选择。
    • 如果需要在容器和主机之间快速共享文件或目录,绑定挂载可能更适合。
    • 如果需要提高数据的读写速度或保护敏感数据,临时文件系统可以考虑。
  2. 数据备份和恢复:
    • 对于重要的数据,应该定期进行备份,以防止数据丢失。
    • 可以使用数据卷或绑定挂载将数据存储在主机上,然后使用主机的备份工具进行备份。
    • 在恢复数据时,可以将备份的数据重新挂载到容器中。
  3. 数据安全:
    • 对于敏感数据,应该采取适当的安全措施,如加密、访问控制等。
    • 可以使用数据卷或绑定挂载将数据存储在主机上,然后使用主机的安全机制来保护数据。
    • 避免在容器中存储敏感数据,以减少安全风险。

五、总结

Docker 容器的数据管理是一个重要的话题,需要根据应用的需求选择合适的数据管理方式,并采取适当的安全措施和备份策略,以确保数据的持久性、可共享性和安全性。

image.png

Docker 容器共享数据卷

一、数据卷共享的概念

在 Docker 中,数据卷可以被多个容器共享。这意味着一个数据卷可以同时被多个容器挂载,从而实现容器之间的数据共享。

二、共享数据卷的优势

  1. 数据持久性:即使容器被删除,数据卷中的数据仍然存在。当新的容器挂载该数据卷时,可以继续访问之前的数据。
  2. 数据共享:多个容器可以同时访问和修改同一个数据卷中的数据,方便容器之间的数据交换和协作。
  3. 灵活性:可以在不同的容器中使用不同的技术栈,但通过共享数据卷,它们可以共享相同的数据。

三、创建共享数据卷

  1. 使用 docker volume create 命令创建一个数据卷:
    • docker volume create shared_volume
  2. 在运行容器时,使用 -v--mount 参数将数据卷挂载到容器中:
    • docker run -v shared_volume:/container/path image_name

四、多个容器共享数据卷

  1. 运行多个容器,并将同一个数据卷挂载到不同的容器路径:
    • docker run -v shared_volume:/container1/path image_name1
    • docker run -v shared_volume:/container2/path image_name2
  2. 这样,两个容器就可以通过共享数据卷来共享数据。

五、注意事项

  1. 数据卷的权限问题:确保容器对挂载的数据卷有适当的读写权限。
  2. 数据一致性:多个容器同时修改数据卷中的数据时,需要注意数据的一致性问题。可以使用适当的同步机制来确保数据的正确性。
  3. 数据备份:由于数据卷中的数据可能被多个容器共享,因此需要定期备份数据,以防止数据丢失。

六、总结

通过共享数据卷,Docker 容器可以方便地实现数据共享和持久性存储。在使用共享数据卷时,需要注意权限、数据一致性和备份等问题,以确保数据的安全和可靠性。

Docker 数据备份和还原

一、数据备份的重要性

在使用 Docker 时,数据备份是非常重要的。它可以帮助我们在数据丢失或损坏的情况下快速恢复数据,确保业务的连续性。

二、使用数据卷进行备份

  1. 首先,确定要备份的数据卷。可以使用 docker volume ls 命令查看已有的数据卷。
  2. 使用容器将数据卷中的数据备份到主机上的文件或目录中。例如,可以使用以下命令将名为 myvolume 的数据卷备份到主机上的 /backup 目录中:
    • docker run --rm -v myvolume:/volume -v /backup:/backup ubuntu tar cvf /backup/backup.tar /volume
    • 这个命令会创建一个临时的 Ubuntu 容器,将 myvolume 数据卷挂载到容器中的 /volume 目录,将主机上的 /backup 目录挂载到容器中的 /backup 目录,然后使用 tar 命令将 /volume 中的数据打包成 /backup/backup.tar 文件。

三、还原数据

  1. 如果需要还原数据,可以使用以下步骤:
    • 首先,确保数据卷已经创建。如果数据卷不存在,可以使用 docker volume create 命令创建。
    • 然后,使用容器将备份文件中的数据还原到数据卷中。例如,可以使用以下命令将 /backup/backup.tar 文件中的数据还原到名为 myvolume 的数据卷中:
      • docker run --rm -v myvolume:/volume -v /backup:/backup ubuntu tar xvf /backup/backup.tar -C /volume
      • 这个命令会创建一个临时的 Ubuntu 容器,将 myvolume 数据卷挂载到容器中的 /volume 目录,将主机上的 /backup 目录挂载到容器中的 /backup 目录,然后使用 tar 命令将 /backup/backup.tar 文件中的数据解压到 /volume 目录中。

四、注意事项

  1. 在备份和还原数据时,确保容器有足够的权限访问数据卷和主机上的文件或目录。
  2. 定期进行数据备份,以防止数据丢失。
  3. 在还原数据之前,最好先备份当前的数据,以防还原过程中出现问题。

五、总结

通过使用数据卷和容器,我们可以方便地进行 Docker 数据的备份和还原。在进行备份和还原操作时,需要注意权限和定期备份等问题,以确保数据的安全和可靠性。

Docker NAT(bridge)模式

一、模式介绍

在 NAT(bridge)模式下,Docker 为容器创建一个独立的网络栈,并通过网络地址转换(NAT)将容器的内部 IP 地址映射到主机的 IP 地址上。容器可以通过主机的 IP 地址和映射后的端口访问外部网络,外部网络也可以通过主机的 IP 地址和映射后的端口访问容器。

二、工作原理

  1. Docker 守护进程在主机上创建一个虚拟网桥(通常名为 docker0)。
  2. 当启动一个容器时,Docker 会为容器分配一个独立的网络命名空间,并在这个命名空间内创建网络接口。
  3. 容器的网络接口连接到虚拟网桥 docker0
  4. Docker 为容器分配一个内部 IP 地址,这个 IP 地址通常在一个私有 IP 地址范围内(例如 172.17.0.0/16)。
  5. 当容器需要访问外部网络时,数据包会通过虚拟网桥 docker0 转发到主机的网络接口上,然后通过主机的网络连接进行传输。在这个过程中,Docker 会进行网络地址转换,将容器的内部 IP 地址和端口映射到主机的 IP 地址和一个可用的端口上。
  6. 外部网络的数据包通过主机的网络接口进入,然后根据端口映射关系转发到相应的容器中。

三、优势

  1. 隔离性:容器之间以及容器与主机之间在网络层面上有一定的隔离性,提高了安全性。
  2. 可扩展性:可以轻松启动多个容器,每个容器都有自己独立的网络环境,方便进行扩展和管理。
  3. 端口映射:可以通过主机的 IP 地址和端口映射来访问容器内的服务,方便外部网络与容器进行通信。

四、使用场景

  1. 开发和测试环境:在开发和测试过程中,通常需要运行多个容器来模拟不同的服务。NAT(bridge)模式可以提供独立的网络环境,方便进行开发和测试。
  2. 小型应用部署:对于小型应用,NAT(bridge)模式可以满足基本的网络需求,并且配置相对简单。

五、注意事项

  1. 端口冲突:由于多个容器可能会使用相同的端口,需要注意端口冲突的问题。可以通过在启动容器时指定不同的端口映射来避免端口冲突。
  2. 性能影响:由于网络地址转换的存在,可能会对网络性能产生一定的影响。在对网络性能要求较高的场景下,可以考虑其他网络模式。

Docker None 模式

一、模式介绍

在 None 模式下,Docker 不为容器创建任何网络栈。容器只有一个独立的进程空间,没有网络接口,也不能与外部网络或其他容器进行通信。

二、工作原理

  1. 当启动一个容器时,Docker 不会为容器创建任何网络设备或配置网络参数。
  2. 容器内部没有网络接口,无法进行网络通信。

三、优势

  1. 最大隔离性:提供了最高程度的隔离,完全隔绝了容器与外部网络以及其他容器的网络连接,确保容器的网络环境完全独立和安全。
  2. 特定场景需求:适用于一些特殊的场景,比如需要在完全没有网络连接的环境下运行容器,或者对网络安全性有极高要求的情况。

四、使用场景

  1. 安全敏感环境:在一些对网络安全要求极高的场景中,不希望容器有任何网络连接,以防止潜在的网络攻击。
  2. 离线环境:当容器在没有网络连接的环境下运行时,可以使用 None 模式。

五、注意事项

  1. 缺乏网络功能:由于没有网络连接,容器无法与外部进行通信,也无法访问外部的服务或资源。如果需要在容器内部运行需要网络连接的应用程序,这种模式就不适用了。
  2. 局限性:None 模式的使用场景相对较窄,通常只在特定的安全或离线需求下使用。在大多数情况下,其他网络模式可能更适合。

Docker Host 模式

一、模式介绍

在 Host 模式下,容器将直接使用主机的网络栈,不会为容器创建独立的网络命名空间。容器将与主机共享网络接口,拥有与主机相同的 IP 地址和网络资源。

二、工作原理

  1. 当启动一个容器时,Docker 会将容器的网络命名空间设置为与主机相同。
  2. 容器可以直接访问主机的网络接口,使用主机的 IP 地址进行通信。
  3. 容器与主机上的其他进程共享网络资源,包括端口、网络协议栈等。

三、优势

  1. 高性能:由于容器直接使用主机的网络栈,不需要进行网络地址转换或端口映射,因此可以获得较高的网络性能。
  2. 简单配置:不需要额外的网络配置,容器可以直接使用主机的网络设置,简化了部署过程。
  3. 方便访问主机资源:容器可以直接访问主机上的网络服务和资源,方便与主机上的其他应用程序进行交互。

四、使用场景

  1. 对网络性能要求较高的应用:如果应用程序对网络延迟和吞吐量有较高要求,Host 模式可以提供更好的性能。
  2. 需要与主机上的其他应用程序进行紧密集成的应用:容器可以直接与主机上的其他应用程序进行网络通信,方便进行集成和协作。

五、注意事项

  1. 隔离性降低:容器与主机共享网络栈,隔离性相对较低。容器中的应用程序可能会对主机的网络安全产生影响,同时主机上的其他进程也可能会影响容器的网络稳定性。
  2. 端口冲突:由于容器与主机共享端口,可能会出现端口冲突的情况。需要确保容器和主机上的其他应用程序不会使用相同的端口。
  3. 网络配置复杂性:如果主机的网络配置比较复杂,容器可能会受到主机网络配置的影响。在使用 Host 模式时,需要对主机的网络有一定的了解。

Docker 联合网络(container)模式

一、模式介绍

在联合网络(container)模式下,新创建的容器会复用另一个已经存在的容器的网络命名空间,从而实现两个或多个容器共享网络栈。

二、工作原理

  1. 首先选择一个已经运行的容器作为网络共享的源容器。
  2. 当启动新容器时,指定使用联合网络模式并指定源容器的 ID 或名称。
  3. 新容器将与源容器共享网络接口、IP 地址、端口等网络资源。

三、优势

  1. 资源共享:多个容器可以共享网络资源,减少网络配置的复杂性。
  2. 方便通信:容器之间可以直接通过共享的网络进行通信,无需进行额外的网络配置。
  3. 高效利用资源:避免为每个容器都创建独立的网络栈,节省系统资源。

四、使用场景

  1. 多个相关容器需要紧密通信的场景:例如一个 Web 应用和其相关的数据库容器,它们之间需要频繁通信,可以使用联合网络模式。
  2. 简化网络配置:当需要快速部署多个容器且它们的网络需求相似时,可以使用此模式简化网络配置。

五、注意事项

  1. 隔离性降低:由于多个容器共享网络栈,隔离性相对较弱。一个容器的网络问题可能会影响到其他共享网络的容器。
  2. 依赖关系:新容器依赖于源容器的网络状态,如果源容器停止或网络配置发生变化,可能会影响到共享网络的容器。
  3. 安全风险:共享网络可能会增加安全风险,需要谨慎考虑容器之间的信任关系和安全策略。

禁止 swap 分区的含义

Swap 分区是一种在内存不足时,将部分内存中的数据交换到磁盘上的特殊分区,以提供额外的虚拟内存空间。

一、禁止 swap 分区的目的

在 Kubernetes(k8s)环境中禁止 swap 分区主要有以下几个原因:

  • 资源管理的确定性:Kubernetes 期望对资源进行精确的管理和调度。如果启用了 swap 分区,系统可能会在内存压力下将一些内存页交换到磁盘,这会导致内存使用情况变得不确定,影响 Kubernetes 对容器资源需求的准确判断和调度决策。
  • 性能考虑:内存和磁盘的访问速度有巨大差异。当系统开始使用 swap 分区时,会导致性能严重下降,因为从磁盘读取交换出去的数据比从内存中读取要慢得多。这对于对性能敏感的应用在 Kubernetes 集群中运行是不利的。

二、禁止 swap 分区的方法

在上述文档中提到了临时和永久禁止 swap 分区的方法:

  • 临时禁止
    • swapoff -a:这个命令会立即关闭所有已激活的 swap 分区。但是当系统重新启动后,swap 分区可能会再次被激活。
  • 永久禁止
    • sed -ri 's/.*swap.*/#&/' /etc/fstab:这个命令通过修改系统的 /etc/fstab 文件,将其中关于 swap 分区的配置行注释掉,从而在系统重启后也不会激活 swap 分区,实现了永久禁止 swap 分区的目的。

关闭 SELinux 的原因

SELinux(Security-Enhanced Linux)是一个 Linux 内核的安全模块,它提供了强制访问控制机制,增强了系统的安全性。然而,在 Kubernetes 环境中通常会关闭 SELinux,原因如下:

一、复杂性增加

  • Kubernetes 本身有自己的一套网络和资源管理机制,而 SELinux 的存在可能会增加配置和管理的复杂性。
  • 在部署 Kubernetes 集群时,需要确保各个组件之间能够顺畅地通信和交互。SELinux 的严格访问控制规则可能会干扰这种通信,导致出现难以排查的问题。

二、兼容性问题

  • 一些容器化应用可能没有针对 SELinux 进行充分的测试和优化,在 SELinux 开启的情况下可能会出现权限不足或无法正常运行的情况。
  • Kubernetes 的一些插件和工具也可能与 SELinux 存在兼容性问题。为了确保整个集群的稳定运行,关闭 SELinux 可以减少潜在的兼容性风险。

三、灵活性和可管理性

  • 关闭 SELinux 可以使管理员在配置和管理 Kubernetes 集群时拥有更大的灵活性。可以更方便地进行网络配置、文件权限设置等操作,而不必担心 SELinux 的规则限制。
  • 在开发和测试环境中,关闭 SELinux 可以加快部署速度,减少因安全设置而导致的问题排查时间。

综上所述,为了简化 Kubernetes 集群的部署和管理,提高兼容性和灵活性,通常会选择关闭 SELinux。但在生产环境中,需要综合考虑安全需求和实际情况,权衡是否关闭 SELinux。如果决定开启 SELinux,需要进行更详细的配置和测试,以确保 Kubernetes 集群的正常运行。

本文作者:han

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!