docker学习和进阶2023

文末有下载地址。如有侵权请联系作者谢谢!

docker学习和进阶2023

参考引用

docker学习笔记:https://blog.csdn.net/m0_46188681/article/details/128993319
Docker容器配置和资源限制:https://www.cnblogs.com/xiugeng/p/16254087.html
容器的监控和日志管理:https://www.cnblogs.com/xiugeng/p/16285637.html

1. docker简介

学习docker的前提:熟悉linux基本命令和熟悉git命令。

1.1 为什么会出现docker?

  1. 一款产品从开发到上线,从操作系统,到运行环境,再到应用配置。作为开发+运维之间的协作我们需要关心很多东西,这也是很多互联网公司都不得不面对的问题,特别是各种版本的迭代之后,不同版本环境的兼容,对运维人员都是考验
    Docker之所以发展如此迅速,也是因为它对此给出了一个标准化的解决方案。
    环境配置如此麻烦,换一台机器,就要重来一次,费力费时。很多人想到,能不能从根本上解决问题,软件可以带环境安装?也就是说,安装的时候,把原始环境一模一样地复制过来。开发人员利用 Docker 可以消除协作编码时“在我的机器上可正常工作”的问题。

    在这里插入图片描述

  2. 之前在服务器配置一个应用的运行环境,要安装各种软件,就拿尚硅谷电商项目的环境来说吧,Java/Tomcat/MySQL/JDBC驱动包等。安装和配置这些东西有多麻烦就不说了,它还不能跨平台。假如我们是在 Windows 上安装的这些环境,到了 Linux 又得重新装。况且就算不跨操作系统,换另一台同样操作系统的服务器,要移植应用也是非常麻烦的。

  3. 传统上认为,软件编码开发/测试结束后,所产出的成果即是程序或是能够编译执行的二进制字节码等(java为例)。而为了让这些程序可以顺利执行,开发团队也得准备完整的部署文件,让维运团队得以部署应用程式,开发需要清楚的告诉运维部署团队,用的全部配置文件+所有软件环境。不过,即便如此,仍然常常发生部署失败的状况。Docker镜像的设计,使得Docker得以打破过去「程序即应用」的观念。透过镜像(images)将作业系统核心除外,运作应用程式所需要的系统环境,由下而上打包,达到应用程式跨平台间的无缝接轨运作。

1.2 docker理念

  • Docker是基于Go语言实现的云开源项目。

  • Docker的主要目标是“Build,Ship and Run Any App,Anywhere”,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的APP(可以是一个WEB应用或数据库应用等等)及其运行环境能够做到“一次封装,到处运行”。

  • Linux 容器技术的出现就解决了这样一个问题,而 Docker 就是在它的基础上发展过来的。将应用运行在 Docker 容器上面,而 Docker 容器在任何操作系统上都是一致的,这就实现了跨平台、跨服务器。只需要一次配置好环境,换到别的机子上就可以一键部署好,大大简化了操作。

1.3 虚拟机(virtual machine)

虚拟机就是带环境安装的一种解决方案,它可以在一种操作系统里面运行另一种操作系统,比如在Windows 系统里面运行Linux 系统。应用程序对此毫无感知,因为虚拟机看上去跟真实系统一模一样,而对于底层系统来说,虚拟机就是一个普通文件,不需要了就删掉,对其他部分毫无影响。这类虚拟机完美的运行了另一套系统,能够使应用程序,操作系统和硬件三者之间的逻辑不变。

虚拟机的缺点:

  • 资源占用多
  • 冗余步骤多
  • 启动慢

1.4 容器虚拟化技术

  • 由于前面虚拟机存在这些缺点,Linux 发展出了另一种虚拟化技术:Linux 容器(Linux Containers,缩写为 LXC)。
  • Linux 容器不是模拟一个完整的操作系统,而是对进程进行隔离。有了容器,就可以将软件运行所需的所有资源打包到一个隔离的容器中。容器与虚拟机不同,不需要捆绑一整套操作系统,只需要软件工作所需的库资源和设置。系统因此而变得高效轻量并保证部署在任何环境中的软件都能始终如一地运行。
  • 比较了 Docker 和传统虚拟化方式的不同之处:
    传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;
  • 而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
  • 每个容器之间互相隔离,每个容器有自己的文件系统 ,容器之间进程不会相互影响,能区分计算资源。

1.5 一次构建到处运行

在这里插入图片描述

  • 更快速的应用交付和部署: 传统的应用开发完成后,需要提供一堆安装程序和配置说明文档,安装部署后需根据配置文档进行繁杂的配置才能正常运行。Docker化之后只需要交付少量容器镜像文件,在正式生产环境加载镜像并运行即可,应用安装配置在镜像里已经内置好,大大节省部署配置和测试验证时间。

  • 更便捷的升级和扩缩容: 随着微服务架构和Docker的发展,大量的应用会通过微服务方式架构,应用的开发构建将变成搭乐高积木一样,每个Docker容器将变成一块“积木”,应用的升级将变得非常容易。当现有的容器不足以支撑业务处理时,可通过镜像运行新的容器进行快速扩容,使应用系统的扩容从原先的天级变成分钟级甚至秒级。

  • 更简单的系统运维: 应用容器化运行后,生产环境运行的应用可与开发、测试环境的应用高度一致,容器会将应用程序相关的环境和状态完全封装起来,不会因为底层基础架构和操作系统的不一致性给应用带来影响,产生新的BUG。当出现程序异常时,也可以通过测试环境的相同容器进行快速定位和修复。

  • 更高效的计算资源利用: Docker是内核级虚拟化,其不像传统的虚拟化技术一样需要额外的Hypervisor支持,所以在一台物理机上可以运行很多个容器实例,可大大提升物理服务器的CPU和内存的利用率。

2. docker安装

2.1 前提条件

  • 目前,CentOS 仅发行版本中的内核支持 Docker。
  • Docker 运行在 CentOS 7 上,要求系统为64位、系统内核版本为 3.10 以上。
  • Docker 运行在 CentOS-6.5 或更高的版本的 CentOS 上,要求系统为64位、系统内核版本为 2.6.32-431 或者更高版本。
  • docker官网:docker https://www.docker.com/
#查看自己的内核 uname命令用于打印当前系统相关信息(内核版本号、硬件架构、主机名称和操作系统类型等)
uname -r
#查看已安装的CentOS版本信息
cat /etc/redhat-release

2.2 docker基本构成

在这里插入图片描述

  • Docker 镜像:(Image)就是一个只读的模板。镜像可以用来创建 Docker 容器,一个镜像可以创建很多容器。
  • Docker 容器:(Container)独立运行的一个或一组应用。容器是用镜像创建的运行实例。
    它可以被启动、开始、停止、删除。每个容器都是相互隔离的、保证安全的平台。
    可以把容器看做是一个简易版的 Linux 环境(包括root用户权限、进程空间、用户空间和网络空间等)和运行在其中的应用程序。
    容器的定义和镜像几乎一模一样,也是一堆层的统一视角,唯一区别在于容器的最上面那一层是可读可写的。
  • 仓库:(Repository)是集中存放镜像文件的场所。
    仓库(Repository)和仓库注册服务器(Registry)是有区别的。仓库注册服务器上往往存放着多个仓库,每个仓库中又包含了多个镜像,每个镜像有不同的标签(tag)。
    仓库分为公开仓库(Public)和私有仓库(Private)两种形式。
    最大的公开仓库是 Docker Hub(https://hub.docker.com/),
    存放了数量庞大的镜像供用户下载。国内的公开仓库包括阿里云 、网易云 等

小总结:
需要正确的理解仓储/镜像/容器这几个概念:

  • Docker 本身是一个容器运行载体或称之为管理引擎。我们把应用程序和配置依赖打包好形成一个可交付的运行环境,这个打包好的运行环境就似乎 image镜像文件。只有通过这个镜像文件才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根据 image 文件生成容器的实例。同一个 image 文件,可以生成多个同时运行的容器实例。
  • image 文件生成的容器实例,本身也是一个文件,称为镜像文件。
  • 一个容器运行一种服务,当我们需要的时候,就可以通过docker客户端创建一个对应的运行实例,也就是我们的容器
  • 至于仓储,就是放了一堆镜像的地方,我们可以把镜像发布到仓储中,需要的时候从仓储中拉下来就可以了。

2.3 docker安装步骤

ce社区版 | ee企业版

#查看本机是否安装 gcc:
yum list installed | grep gcc
#如果没有 执行以下命令
yum -y install gcc gcc-c++
#卸载以前的docker旧版本
yum -y remove docker docker-common docker-selinux docker-engine
#安装需要的软件包
yum install -y yum-utils device-mapper-persistent-data lvm2
#设置stable镜像仓库
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#更新软件包索引
yum makecache fast

#安装docker-ce、docker-ce-cli、containerd
yum install -y docker-ce-24.0.4 docker-ce-cli-24.0.4 containerd.io
#启动docker
systemctl start docker
#测试是否安装成功
docker version
docker run hello word

#配置镜像加速
#阿里云镜像地址: https://promotion.aliyun.com/ntms/act/kubernetes.html
#登录进去找到 镜像加速器
vim /etc/docker/daemon.json
 #网易云
{
	"registry-mirrors": ["http://hub-mirror.c.163.com"] 
}
#或者阿里云
{
  "registry-mirrors": ["https://{自已的编码}.mirror.aliyuncs.com"]
}

#刷新配置并重启docker
systemctl daemon-reload
systemctl restart docker
#将docker设为开机启动
systemctl enable docker

#卸载docker
systemctl stop docker
yum -y remove docker-ce
rm -rf /var/lib/docker
在这里插入图片描述

2.4 测试镜像

  1. 查看docker镜像是否配置成功 docker info

在这里插入图片描述

  1. 运行 :docker run hello-world 测试docker是否安装成功

  2. docker run hello-world 都做了什么?(和maven的概念差不多)

在这里插入图片描述
  1. docker底层原理
  • docker是怎么工作的?
    Docker是一个Client-Server结构的系统,Docker守护进程运行在主机上, 然后通过Socket连接从客户端访问,守护进程从客户端接受命令并管理运行在主机上的容器。 容器,是一个运行时环境,就是我们前面说到的集装箱。

  • 为什么docker比vm快?

    1. docker有着比虚拟机更少的抽象层。由于docker不需要Hypervisor实现硬件资源虚拟化,运行在docker容器上的程序直接使用的都是实际物理机的硬件资源。因此在CPU、内存利用率上docker将会在效率上有明显优势。
    2. docker利用的是宿主机的内核,而不需要Guest OS。因此当新建一个容器时,docker不需要和虚拟机一样重新加载一个操作系统内核,因而避免引寻、加载操作系统内核这个比较费时费资源的过程;当新建一个虚拟机时,虚拟机软件需要加载Guest OS,这个新建过程是分钟级别的。而docker由于直接利用宿主机的操作系统,则省略了返个过程,因此新建一个docker容器只需要几秒钟。

3. docker启动命令

#查看docker帮助文档: docker 具体命令 --help
docker --help
docker -h
#启动docker
systemctl start docker
#停止docker
systemctl stop docker
#重启docker
systemctl restart docker
#查看docker状态
systemctl status docker
#开机启动docker
systemctl enable docker
#查看docker概要信息
docker info

4. docker镜像命令

4.1 搜索镜像

#命令 docker search,例如查询mysql
docker search mysql

NAME               DESCRIPTION            STARS       OFFICIAL       AUTOMATED
镜像名称            镜像说明               点赞数量     是否官方认证     是否自动认证     

#详细参数
Options:
	-f, --filter string   过滤掉输出结果
	#docker search --filter=STARS=9000 mysql [搜索 STARS >9000的 mysql 镜像]
			--format string   标准格式输出
			#格式化输出   docker search --format "{{.Name}}: {{.StarCount}}" nginx
				-.Description   镜像描述  
				-.StarCount     star数量   
				-.IsOfficial    “OK” 表示官方镜像   
				- IsAutomated   “OK” 表示自动构建  
			--limit int       最大搜索结果数(默认为25)
			#docker search --limit 20 mysql [搜索 mysql 镜像 只显示前20条]
			--no-trunc        不用截断输出

4.2 列出本地镜像

#命令:
docker images  [Options]
#详细参数
Options:
  -a, --all             显示所有镜像(默认隐藏中间镜像)
      --digests         显示摘要
  -f, --filter filter   根据提供的条件过滤输出
      --format string   使用 Go 模板打印漂亮的图像
      --no-trunc        使用 Go 模板打印漂亮的图像
  -q, --quiet           只显示镜像id

#展示信息说明
REPOSITORY: 来自于哪个仓库,比如phpswoole/swoole表示swoole官网的镜像
TAG	: 镜像的标签信息,比如18.04、latest表示不同的版本信息。标签只是标记,并不能标识镜像内容,latest标识最新的版本
IMAGE ID: 镜像的ID(唯一标识镜像),如果两个镜像的ID相同,说明它们实际上指向了同一个镜像,只是具有不同标签名称而已
CREATED: 创建时间,说明镜像最后的更新时间
SIZE: 镜像大小,优秀的镜像往往体积都较小

#--format 模板说明
.ID	          镜像id
.Repository	  镜像名称
.Tag	        镜像标签
.Digest	      镜像简介
.CreatedSince	自创以来经过的时间
.CreatedAt	  创建图像的时间
.Size	        镜像大小

4.3 拉取镜像

#命令: 
docker pull [Options] 镜像名称:tag
#详细参数
Options:
  -a, --all-tags                下载镜像仓库中所有的指定镜像
      --disable-content-trust   跳过镜像验证(默认值是true)
      --platform string         如果服务具有多平台功能,则设置平台
  -q, --quiet                   一直详细输出

#没有TAG就是最新版 等价于 docker pull 镜像名称:latest

4.4 查看镜像/容器/数据卷所占的空间

#命令:
docker system [Options]
#详细参数
Options:
  df         整体磁盘的使用情况
  events     获取docker系统实时事件,不包括容器内的
  info       查看整个docker系统的信息
  prune      清理资源,此操作尤其需要注意 # 清理停止的容器,清理没有使用的网络,清理废弃的镜像

4.5 删除镜像

#命令
docker rmi [Options] 镜像名称|镜像ID
#详细参数
Options:
	-f : 通过 SIGKILL 信号强制删除一个运行中的容器。
 	–no-prune : 不移除该镜像的过程镜像,默认移除

#删除全部镜像,谨慎使用
docker rmi -f $(docker images -qa)

#谈谈docker虚悬镜像是什么?
#仓库名、标签都是<none>的镜像,俗称虚悬镜像dangling image

4.6 查看镜像构建过程

#命令:
docker history [Options] 镜像名称|镜像ID
#详细参数
Options:
  -H, --human          以可读的格式打印镜像大小和日期,默认为true
      --no-trunc       显示完整的提交记录
  -q, --quiet          仅列出提交记录ID

4.7 将指定镜像保存成 tar 归档文件

#命令
docker save [OPTIONS] IMAGE [IMAGE...]
参数
-o : 输出到的文件

#示例:将镜像jb51/ubuntu:v3 生成my_ubuntu_v3.tar文档
docker save -o my_ubuntu_v3.tar jb51/ubuntu:v3
ll my_ubuntu_v3.tar
-rw------- 1 jb51 jb51 142102016 Jul 11 01:37 my_ubuntu_v3.tar

4.8 使用 Dockerfile 创建镜像

#命令
docker build [OPTIONS] PATH | URL | 
#详细参数
Options:
–build-arg=[] : 设置镜像创建时的变量;
–cpu-shares : 设置 cpu 使用权重;
–cpu-period : 限制 CPU CFS周期;
–cpu-quota : 限制 CPU CFS配额;
–cpuset-cpus : 指定使用的CPU id;
–cpuset-mems : 指定使用的内存 id;
–disable-content-trust : 忽略校验,默认开启;
-f : 指定要使用的Dockerfile路径;
–force-rm : 设置镜像过程中删除中间容器;
–isolation : 使用容器隔离技术;
–label=[] : 设置镜像使用的元数据;
-m : 设置内存最大值;
–memory-swap : 设置Swap的最大值为内存+swap,"-1"表示不限swap;
–no-cache : 创建镜像的过程不使用缓存;
–pull : 尝试去更新镜像的新版本;
–quiet, -q : 安静模式,成功后只输出镜像 ID;
–rm : 设置镜像成功后删除中间容器;
–shm-size : 设置/dev/shm的大小,默认值是64M;
–ulimit : Ulimit配置。
–squash : 将 Dockerfile 中所有的操作压缩为一层。
–tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
–network: 默认 default。在构建期间设置RUN指令的网络模式

4.9 标记本地镜像

#标记本地镜像将其归入某一仓库
docker tag [OPTIONS] IMAGE[:TAG] [REGISTRYHOST/][USERNAME/]NAME[:TAG]
#示例将本地myapp:1.0镜像归入aim下
docker tag myapp:1.0 aim/myapp:1.0

4.10 登陆到一个Docker镜像仓库

#如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker login [OPTIONS] [SERVER]
    -u : 登陆的用户名
    -p : 登陆的密码

4.11 登出一个Docker镜像仓库

#如果未指定镜像仓库地址,默认为官方仓库 Docker Hub
docker logout [OPTIONS] [SERVER]

4.12 将本地的镜像上传到镜像仓库

#要先登陆到镜像仓库
docker push [OPTIONS] 镜像名称:[镜像标签]

4.13 查看虚悬镜像

#-f 根据提供的条件过滤输出;-q 只显示镜像id
docker images -f "dangling=true" -q
#删除虚悬镜像
docker rmi $(docker images -f "dangling=true" -q)
#这个命令会删除所有未使用到的镜像,即使并不是没有仓库名或没有标签。
docker image prune -a -f
#-a 显示所有镜像(默认隐藏中间镜像);-f 根据提供的条件过滤输出;-q 只显示镜像id
docker images -a -f "dangling=true" -q

5. docker容器

docker容器的使用和操作:https://www.cnblogs.com/xiugeng/p/16008671.html

容器(Container):在docker中指的是从镜像创建的应用程序运行实例。
可以将容器看作将一个 应用程序及其依赖环境打包 而成的集装箱。
容器的实质是进程,与直接在主机执行不同,容器进程在属于自己的独立的命名空间内运行。这种特性使得容器封装的应用程序比直接在主机上运行的应用程序更加安全。

5.1 配置并启动容器 run

#命令
docker run [OPTIONS] IMAGE [COMMAND] [ARG...]
#docker run -it IMAGE_ID /bin/bash 常用

#详细参数
Options:
--add-host	添加自定义主机到IP的映射(host:ip)
--attach-a	登录容器
--blkio-weight	block io (相对权重),介于10到1000之间,或者为0禁用(默认为0)
--blkio-weight-device	block IO 设备权重(相对设备权重)
--cap-add	添加 Linux 容量
--cap-drop	删除 Linux 容量
--cgroup-parent	容器的可选父cgroup
--cgroupns	在其自己的私有cgroup命名空间中运行容器
--cidfile	将容器ID写入文件
--cpu-count	CPU数量(仅windows)
--cpu-percent	CPU百分比(仅Windows)
--cpu-period	限制CPU CFS(完全公平的调度程序)期限
--cpu-quota	限制CPU CFS(完全公平的调度程序)配额
--cpu-rt-period	限制CPU实时时间(以微秒为单位)
--cpu-rt-runtime	限制CPU实时运行时间(以微秒为单位)
--cpu-shares , -c	CPU份额(相对)
--cpus	CPU数量
--cpuset-cpus	允许执行的CPU数量(0-3,0,1)
--cpuset-mems	允许执行的MEM数量(0-3,0,1)
--detach-d	在后台运行容器并打印容器ID
--detach-keys	覆盖后台容器的键序列
--device	将主机设备添加到容器
--device-cgroup-rule	将规则添加到“允许cgroup的设备”列表中
--device-read-bps	限制从设备读取的速率(每秒字节数)
--device-read-iops	限制从设备读取的速率(每秒IO)
--device-write-bps	限制对设备的写入速率(每秒字节数)
--device-write-iops	限制对设备的写入速率(每秒IO)
--disable-content-trust true	跳过图像验证
--dns	设置自定义DNS服务器
--dns-opt	设定DNS选项
--dns-option	设定DNS选项
--dns-search	设置自定义DNS搜索域
--domainname	容器NIS域名
--entrypoint	覆盖图像的默认ENTRYPOINT
--env-e	设置环境变量
--env-file	读入环境变量文件
--expose	公开一个或多个端口
--gpus	添加GPU设备到容器
--group-add	添加其他群组加入
--health-cmd	运行命令以检查运行状况
--health-interval	运行检查间隔时间(ms
--health-retries	连续故障,报告不健康
--health-start-period	开始运行状况重试倒计时之前,容器初始化的开始时间(ms
--health-timeout	允许执行一次检查的最长时间(ms
--help	打印用法,获取帮助
--hostname , -h	容器的主机名
--init	在容器内运行一个初始化程序,以转发信号并获取进程
--interactive-i	
--io-maxbandwidth	系统驱动器的最大IO带宽限制(仅Windows)
--io-maxiops	系统驱动器的最大IOps限制(仅Windows)
--ip	IPV4地址
--ip6	IPV6地址
--isolation	
--kernel-memory	内核内存限制
--label , -l	在容器上设置元数据
--label-file	读入行分隔的标签文件
--link	指定容器间的关联,使用其他容器的IP、env等信息
--link-local-ip	容器IPv4 / IPv6链接本地地址
--log-driver	容器的日志记录驱动程序
--log-opt	日志驱动程序选项
--mac-address	容器MAC地址
--memory-m	内存限制
--memory-reservation	内存软限制
--memory-swap	交换限制等于内存加交换:“-1”以启用无限交换
--memory-swappiness	调音容器内存交换(0到100)
--mount	将文件系统挂载附加到容器
--name	为容器分配一个名称
--net	将容器连接到网络
--net-alias	为容器添加网络范围的别名
--network	将容器连接到网络
--network-alias	为容器添加网络范围的别名
--no-healthcheck	禁用任何容器指定的健康检查
--oom-kill-disable	禁用OOM Killer
--oom-score-adj	主机OOM首选项
--pid	使用PID命名空间
--privileged	赋予此容器扩展的特权
--publish , -p(小写)	将容器的端口发布到主机
--publish-all , -P(大写)	将所有公开的端口发布到随机端口
--read-only	将容器的根文件系统挂载为只读
--restart	容器退出时重新启动策略以应用:no-容器退出时不重启,默认设置/on-failure[:max-retries]-容器以非0状态退出时重启,max-retries指定重启的次数/always-不管退出状态始终重启,无限次/unless-stopped-不管退出状态始终重启,(Docker守护进程启动时,容器处于运行状态才生效)
--rm	退出时自动删除容器
--runtime	
--tmpfs	挂载tmpfs目录
--tty-t	分配伪TTY
--user-u	用户名或UID(格式:<名称
--volume-v	绑定挂载卷
--volume-driver	容器的可选卷驱动器
--volumes-from	从指定的容器挂载卷
--workdir-w	容器内的工作目录

5.2 容器配置进阶

5.2.1 容器的重启策略
  1. 开机启动docker
#查看已启动的服务
systemctl list-units --type=service
#查看已启动的服务
systemctl list-unit-files | grep enable
#设置开机启动
systemctl enable docker.service
#关闭开机启动 
systemctl disable docker.service
  1. docker容器的重启策略

    • Docker提供重启策略控制容器退出时或Docker重启时是否自动启动该容器。

      容器默认不支持自动重启,要使用 --restart 选项指定重启策略。

    • 作用:容器自动重启;重启策略能够确保关联的多个容器按照正确的顺序启动。

    • 容器重启策略选项值:

      选项值功能
      no容器退出时不重启,默认设置
      on-failure[:max-retries]容器以非0状态退出时重启,max-retries指定重启的次数
      always不管退出状态始终重启,无限次
      unless-stopped不管退出状态始终重启,(Docker守护进程启动时,容器处于运行状态才生效)
    • 使用重启策略时的注意事项:

      1. 重启策略只在容器成功启动后才会生效。(容器运行后生效)
      2. 如果手动停止一个容器,那么它的重启策略会被忽略,直到Docker守护进程重启或容器手动重启。(手动停止,暂停重启策略)
      3. Docker Swarm服务的重启策略采用不同的配置方式。(集群采用不同的重启策略)
      4. 重启策略不同于dockerd命令的--live-restore选项,这个选项可使Docker升级中,即使网络和用户输入都终端,容器依然保持运行。
      5. Docker建议使用重启策略,并避免使用进程管理器启动容器:(1)同时使用两者会产生冲突;(2)进程管理器依赖于操作系统,Docker无法监控。
#1.开启自启,在docker启动容器时可以增加参数
docker run –-restart=always
#容器已经启动,通过update命令进行修改
docker update –-restart=always <CONTAINER ID>
#重启在运行的所有容器
docker restart $(docker ps -q)

#2.关闭自启,容器关闭自启动:
docker update --restart=no <CONTAINER ID>
#取消所有容器自启动
docker update --restart=no $(docker ps -q)
  1. docker-compose配置容器的重启策略

    配置启动容器时添加下述配置项,docker-compose 关机或者重启docker时就会生效

    img

5.2.2 在Docker停止时保持容器继续运行

默认情况下,Docker守护进程终止时,正在运行的容器会关闭。
实时恢复(Live Restore):管理员配置守护进程,让容器在守护进程不可用时依然运行。
实时恢复的作用:减少因Docker守护进程崩溃、计划停机或升级导致的容器停机时间。

  1. 启用实时恢复功能

    第一种方式是在Docker守护进程配置文件中设置:

    • sighup(挂断)信号在控制终端或者控制进程死亡时向关联会话中的进程发出,默认进程对SIGHUP信号的处理时终止程序,所以我们在shell下建立的程序,在登录退出连接断开之后,会一并退出。

    • nohup 故名思议就是忽略SIGHUP信号,一般搭配& 一起使用,&表示将此程序提交为后台作业或者说后台进程组。

    [root@localhost ~]# vi /etc/docker/daemon.json 
    {
      "live-restore":true
    }
    
    # 配置生效方法一:
    # 修改配置后重启守护进程生效
    [root@localhost ~]# systemctl daemon-reload
    [root@localhost ~]# systemctl restart docker
    
    # 配置生效方法二:
    # 重新加载Docker守护进程,避免容器停止
    [root@localhost ~]# systemctl reload docker
    
    # 案例1:
    # 1.启动两个容器
    [root@localhost ~]# docker ps 
    CONTAINER ID   IMAGE              COMMAND                  CREATED       STATUS          PORTS     NAMES
    1dd65fa55b80   top                "/bin/sh -c 'exec to…"   5 weeks ago   Up 38 seconds             test_exec_entry
    52a7de98ccc7   test_shell_entry   "/bin/sh -c 'top -b'"    5 weeks ago   Up 52 seconds             test:
    # 2.停止docker守护进程
    [root@localhost ~]# systemctl stop docker
    Warning: Stopping docker.service, but it can still be activated by:
      docker.socket
    [root@localhost ~]# systemctl status docker
    ● docker.service - Docker Application Container Engine
       Loaded: loaded (/usr/lib/systemd/system/docker.service; enabled; vendor preset: disabled)
       Active: inactive (dead) since Wed 2022-05-11 00:23:16 CST; 8s ago
         Docs: https://docs.docker.com
      Process: 1697 ExecReload=/bin/kill -s HUP $MAINPID (code=exited, status=0/SUCCESS)
      Process: 1853 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock (code=exited, status=0/SUCCESS)
     Main PID: 1853 (code=exited, status=0/SUCCESS)
    # 3.查看容器是否依然运行
    [root@localhost ~]# docker ps 
    CONTAINER ID   IMAGE              COMMAND                  CREATED       STATUS              PORTS     NAMES
    1dd65fa55b80   top                "/bin/sh -c 'exec to…"   5 weeks ago   Up About a minute             test_exec_entry
    52a7de98ccc7   test_shell_entry   "/bin/sh -c 'top -b'"    5 weeks ago   Up 2 minutes                  test
    
    # 案例2:apache容器测试实时恢复
    # 1.修改守护进程配置文件,启动实时恢复
    [root@localhost ~]# vi /etc/docker/daemon.json 
    {
      "registry-mirrors": ["https://nxwgbmaq.mirror.aliyuncs.com"],
      "live-restore":true
    }
    # 2.重启守护进程
    [root@localhost ~]# systemctl restart docker
    # 3.运行一个apache容器
    [root@localhost ~]# docker pull httpd
    [root@localhost ~]# docker run --rm -d -p 8080:80 httpd
    27c266f2fbc9bb5dd67e442a99b82db440d135506b9d912d624331baae675ca9
    # 4.重新加载Docker守护进程
    [root@localhost ~]# systemctl reload docker
    # 5.查看当前容器
    [root@localhost ~]# docker ps
    CONTAINER ID   IMAGE     COMMAND              CREATED              STATUS              PORTS                                   NAMES
    27c266f2fbc9   httpd     "httpd-foreground"   About a minute ago   Up About a minute   0.0.0.0:8080->80/tcp, :::8080->80/tcp   inspiring_robinson    《————容器依然运行
    # 6.kill结束进程
    [root@localhost ~]# ps -e | grep dockerd     
      5052 ?        00:00:01 dockerd              《————查看获取进程号
    [root@localhost ~]# kill -SIGHUP 5052         《————向进程发送sighup信号
    [root@localhost ~]# docker ps                  
    CONTAINER ID   IMAGE     COMMAND              CREATED         STATUS         PORTS                                   NAMES
    27c266f2fbc9   httpd     "httpd-foreground"   2 minutes ago   Up 2 minutes   0.0.0.0:8080->80/tcp, :::8080->80/tcp   inspiring_robinson      《————容器依然运行
    # 7.访问apache验证服务是否正常
    [root@localhost ~]# curl 127.0.0.1:8080
    <html><body><h1>It works!</h1></body></html>
    

    另一种恢复方式:在手动启动dockerd进程时指定–live-restore选项。
    不建议使用这种方式,因为不会设置systemd或其他进程管理器的环境,会导致意外发生。

  2. 升级期间的实时恢复

    实时恢复功能支持Docker守护进程在升级期间保持容器的运行。

    存在的问题:

    1. 只支持Docker 补丁版本升级,不支持主要版本和次要版本的升级。

    2. 升级过程中跳过版本,守护进程可能无法恢复其与容器的连接。

  3. 重启时的实时恢复

    限定条件:只有Docker守护进程选项未发生变化,实时恢复才能恢复容器。

  4. 实时恢复功能对运行容器的影响

    守护进程停止,正在运行的容器可能会填满守护进程通常读取的FIFO日志,阻止容器记录更多日志数据。

    缓冲区填满,必须重新启动Docker守护进程来刷新。
    可以更改/proc/sys/fs/pipe-max=size来修改内核的缓冲区大小。

    [root@localhost ~]# cat /proc/sys/fs/pipe-max-size 
    1048576
    
  5. dockerd启动失败排错
    # 执行该命令显示最后200行linux系统日志信息,并滚动刷新
    [root@localhost home]# tail -200f /var/log/messages
    
    # 再开一个session,执行命令
    [root@localhost /]# systemctl daemon-reload   
    [root@localhost /]# systemctl restart docker
    
    # 可以看到日志刷新的信息,即可根据信息提示完成修复
    Apr 23 19:32:45 localhost dockerd: unable to configure the Docker daemon with file /etc/docker/daemon.json: invalid character '}' looking for beginning of object key string
    
5.2.3 一个容器中运行多个服务

注意:一个容器可以有多个进程,但为了高效利用Docker,不要让一个容器负责整个应用程序的多个方面,而要通过用户定义网络和共享卷连接多个容器来实现应用程序的多个方面。

容器的主进程负责管理它启动的所有进程。
解决子进程回收:--init选项可以将一个精简的初始化进程作为主进程插入容器,并在容器退出时回收所有的进程。
解决多进程启停最好方式:设置一个上层的进程统一处理这些进程的生命周期(sysinit\upstart\systemd)

在一个容器运行多个服务的方式:

  • 将所有命令放入包装器脚本中,并提供测试和调试信息,使用CMD指令运行包装器脚本。
  • 如果有一个主进程需要首先启动并保持运行,但是临时需要运行一些其他进程(可能与主进程交互),可以使用bash脚本的作业控制实现。
  • 在容器中使用supervisord等进程管理器。

Supervisor 是 Linux/UNIX系统下的一个进程管理工具,守护进程名为supervisord,可以方便地监听、启动、停止、重启一个或多个进程。
该工具管理进程时,如遇到进程被意外杀死,守护进程监听到后,会自动重启。

1. php:7.3-fpm案例
# 1.创建项目目录
[root@localhost ~]# mkdir php-nginx-supervisord && cd php-nginx-supervisord/

# 2.创建nginx子目录和supervisor子目录,并准备配置文件
[root@localhost php-nginx-supervisord]# mkdir nginx
[root@localhost php-nginx-supervisord]# mkdir supervisor
[root@localhost php-nginx-supervisord]# touch nginx/nginx.conf
[root@localhost php-nginx-supervisord]# mkdir nginx/conf.g
[root@localhost php-nginx-supervisord]# touch nginx/conf.g/site.conf
[root@localhost php-nginx-supervisord]# mkdir supervisor/conf.d/
[root@localhost php-nginx-supervisord]# touch supervisor/conf.d/supervisord.conf
# 查看目录结构
[root@localhost php-nginx-supervisord]# tree
.
├── nginx
│   ├── conf.g
│   │   └── site.conf
│   └── nginx.conf
└── supervisor
    └── conf.d
        └── supervisord.conf
4 directories, 3 files

# 3.编写supervisord.conf文件内容
[root@localhost php-nginx-supervisord]# vi supervisor/conf.d/supervisord.conf 
[supervisord]
gfile=/tmp/supervisord.log ; # 日志
logfile_maxbytes=50MB ; # 最大50M日志
logfile_backups=10 ; # 轮循日志备份10个
loglevel=info ; # 日志等级记录info的
pidfile=/tmp/supervisord.pid ;pid
nodaemon=true ; # 在前台启动
minfds=102400 ; # 文件描述符限制
minprocs=2000 ; # 进程数

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket

[program:nginx]
command=/usr/sbin/nginx -g 'daemon off';  # 前台启动nginx
autostart=true ; # 随着supervisor自动启动
startsecs=10 ; # 启动10s后算正常启动
autorestart=true ; # 程序退出后自动重启
startretries=3 ; # 启动失败自动重试次数
stdout_logfile_maxbytes=20MB ;stdout   # 日志文件大小最大20Mb
stdout_logfile=/var/log/nginx/out.log

[program:php7-fpm]
command=/usr/local/sbin/php-fpm
autostart=true ; # 随着supervisor自动启动
startsecs=10 ; # 启动10s后算正常启动
autorestart=true ; #程序退出后自动重启
startretries=3 ; # 启动失败自动重试次数
stdout_logfile_maxbytes=20MB ;stdout 日志文件大小最大20Mb

# 4.尝试登录这个php容器,判断系统版本
[root@localhost php-nginx-supervisord]# docker run -ti php:7.3-fpm /bin/bash
# 进入容器检查信息
root@16fddccbb4ce:/var/www/html# cat /etc/issue
Debian GNU/Linux 11 \n \l
root@16fddccbb4ce:/var/www/html# cat /etc/os-release 
PRETTY_NAME="Debian GNU/Linux 11 (bullseye)"
NAME="Debian GNU/Linux"
VERSION_ID="11"
VERSION="11 (bullseye)"
VERSION_CODENAME=bullseye
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"
# 由此得知为debian 11版本的系统

# 5.准备debian11换源文件sources.list
[root@localhost php-nginx-supervisord]# touch sources.list
[root@localhost php-nginx-supervisord]# vi sources.list 
deb http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye main non-free contrib
deb http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb-src http://mirrors.aliyun.com/debian-security/ bullseye-security main
deb http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-updates main non-free contrib
deb http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib
deb-src http://mirrors.aliyun.com/debian/ bullseye-backports main non-free contrib

# 6.准备nginx.conf文件
[root@localhost php-nginx-supervisord]# vi nginx/nginx.conf 
#一个主进程和多个工作进程
worker_processes  1;
events {
    #每个工作进程最大的并发数(一个工作进程可以有多少个线程)
    worker_connections  1024;
}
#http服务器设置
http {
    #设定mime类型,类型由mime.type文件定义
    include       mime.types;
    #长连接超时时间
    keepalive_timeout  65;
    #配置虚拟主机
    server {
        #虚拟主机使用的端口
        listen       80;
        #虚拟主机域名
        server_name  localhost;
        #定义web根路径
        location / {
            #根目录路径
            root   html;
            #索引页
            index  index.html index.htm;
        }
    }
}   

# 6.编写Dockerfile文件内容
[root@localhost php-nginx-supervisord]# vi Dockerfile
FROM php:7.3-fpm
COPY sources.list /etc/apt/
RUN apt-get clean && apt-get update && apt-get -y install nginx supervisor procps net-tools && mkdir -p /var/log/supervisor
COPY nginx /etc/nginx
COPY supervisor /etc/supervisor
WORKDIR /var/www
RUN usermod -u 1000 www-data
EXPOSE 80
CMD ["/usr/bin/supervisord"]

# 7.基于Dockerfile构建镜像
[root@localhost php-nginx-supervisord]# docker build -t php-nginx-supervisord .
[+] Building 134.0s (14/14) FINISHED                                               
 => [internal] load build definition from Dockerfile                          0.0s
 => => transferring dockerfile: 350B                                          0.0s
 => [internal] load .dockerignore                                             0.0s
 => => transferring context: 2B                                               0.0s
 => [internal] load metadata for docker.io/library/php:7.3-fpm                0.0s
 => CACHED [1/9] FROM docker.io/library/php:7.3-fpm                           0.0s
 => [internal] load build context                                             0.0s
 => => transferring context: 902B                                             0.0s
 => [2/9] COPY sources.list /etc/apt/                                         0.0s
 => [3/9] RUN apt-get clean && apt-get update                                34.9s
 => [4/9] RUN apt-get -y install nginx supervisor procps net-tools           85.5s
 => [5/9] RUN mkdir -p /var/log/supervisor                                    0.3s 
 => [6/9] COPY nginx /etc/nginx                                               0.0s 
 => [7/9] COPY supervisor /etc/supervisor                                     0.0s 
 => [8/9] WORKDIR /var/www                                                    0.0s 
 => [9/9] RUN usermod -u 1000 www-data                                        0.3s 
 => exporting to image                                                       12.9s 
 => => exporting layers                                                      12.9s
 => => writing image sha256:801d960db6395bde049fe7f3ffcec0de1a8e3b918a219b27  0.0s
 => => naming to docker.io/library/php-nginx-supervisord                      0.0s

# 8.基于该镜像启动容器
[root@localhost php-nginx-supervisord]# docker images
REPOSITORY              TAG       IMAGE ID       CREATED              SIZE
php-nginx-supervisord   latest    62a3c736e277   About a minute ago   516MB
[root@localhost php-nginx-supervisord]# docker run -tid -p 8080:80 php-nginx-supervisord
44e42a4ae258ebe1f37a0b940afda5462f79260686477c89270cd8103ac61adf

# 9.测试web服务
访问:http://192.168.200.103:8080/
登录容器查看进程:
[root@localhost php-nginx-supervisord]# docker exec -ti 5b6d610e032e /bin/bash
root@5b6d610e032e:/var/www# ps auxf        
USER        PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         41  0.0  0.1   4100  3456 pts/1    Ss   08:57   0:00 /bin/bash
root         51  0.0  0.1   6700  2816 pts/1    R+   08:58   0:00  \_ ps auxf
root          1  0.3  1.2  29492 24156 pts/0    Ss+  08:57   0:00 /usr/bin/python3 /usr/bin/supervi
root          7  0.4  1.1  73228 22332 pts/0    S    08:57   0:00 php-fpm: master process (/usr/loc
www-data     15  0.0  0.4  73228  8784 pts/0    S    08:57   0:00  \_ php-fpm: pool www
www-data     16  0.0  0.4  73228  8784 pts/0    S    08:57   0:00  \_ php-fpm: pool www
root         49  0.0  0.0   8532  1424 ?        Ss   08:58   0:00 nginx: master process /usr/sbin/n
nobody       50  0.0  0.1   8988  2576 ?        S    08:58   0:00  \_ nginx: worker process
2. centos镜像案例
# 案例:将supervisord和配置和要管理的应用程序(nginx和tomcat)打包到一个镜像中,一个容器运行多个服务
# 1.创建dockerfile目录
[root@hecs-hqs-01 ~]# mkdir web-supervisord
[root@hecs-hqs-01 web-supervisord]# cd web-supervisord/

# 2.编写Dockerfile
[root@hecs-hqs-01 web-supervisord]#  vi Dockerfile            《————dockerfile目录
FROM centos:7
MAINTAINER hqs@163.com
COPY CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo
COPY nginx_install.sh /tmp/nginx_install.sh
RUN sh /tmp/nginx_install.sh; \rm -rf /usr/local/src/*
RUN sed -i -e '/worker_processes/a daemon off;' /usr/local/nginx/conf/nginx.conf;
COPY jdk-8u162-linux-x64.tar.gz /usr/local/src/jdk-8u162-linux-x64.tar.gz
COPY tomcat_install.sh /tmp/tomcat_install.sh
RUN sh /tmp/tomcat_install.sh; \rm -rf /usr/local/src/*
COPY supervisor_install.sh /tmp/supervisor_install.sh
COPY supervisord.conf /etc/supervisord.conf
COPY start_tomcat.sh /usr/local/tomcat/bin/mystart.sh
RUN sh /tmp/supervisor_install.sh; \rm -rf /tmp/*.sh
CMD ["supervisord", "-c", "/etc/supervisord.conf"]

# 3.默认源下载慢且总有问题,更换为163的yum源
[root@hecs-hqs-01 web-supervisord]# vi CentOS-Base.repo 
[base]
name=CentOS-$releasever - Base
baseurl=http://mirrors.163.com/centos/$releasever/os/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#released updates
[updates]
name=CentOS-$releasever - Updates
baseurl=http://mirrors.163.com/centos/$releasever/updates/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7

#additional packages that may be useful
[extras]
name=CentOS-$releasever - Extras
baseurl=http://mirrors.163.com/centos/$releasever/extras/$basearch/
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7
 
#additional packages that extend functionality of existing packages
[centosplus]
name=CentOS-$releasever - Plus
baseurl=http://mirrors.163.com/centos/$releasever/centosplus/$basearch/
gpgcheck=1
enabled=0
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-CentOS-7 

# 4.准备nginx安装脚本
[root@hecs-hqs-01 web-supervisord]# vi nginx_install.sh
yum install -y wget tar gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel
cd /usr/local/src
wget 'http://nginx.org/download/nginx-1.12.2.tar.gz'
tar -zxvf nginx-1.12.2.tar.gz
cd nginx-1.12.2
./configure --prefix=/usr/local/nginx --with-http_ssl_module --with-stream --with-stream_ssl_module
make
make install
exit 0

# 5.准备tomcat安装脚本
[root@hecs-hqs-01 web-supervisord]# vi tomcat_install.sh
yum install -y wget tar
cd /usr/local/src/
tar -zxvf jdk-8u162-linux-x64.tar.gz
mv jdk1.8.0_162 /usr/local/
#/usr/local/jdk1.8.0_162/bin/java -version
#配置java环境变量
echo 'JAVA_HOME=/usr/local/jdk1.8.0_162/' >>/etc/profile
echo 'PATH=$PATH:$JAVA_HOME/bin' >>/etc/profile
echo 'CLASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar:$CLASSPATH' >>/etc/profile
source /etc/profile
wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-8/v8.5.78/bin/apache-tomcat-8.5.78.tar.gz
tar -zxvf apache-tomcat-8.5.78.tar.gz
mv apache-tomcat-8.5.78 /usr/local/tomcat

# 6.下载jdk
# 官网下载地址:https://www.oracle.com/java/technologies/javase/javase8-archive-downloads.html 需要注册才能下载
[root@hecs-hqs-01 web-supervisord]# ls

# 7.准备supervisor安装脚本
[root@hecs-hqs-01 web-supervisord]# vi supervisor_install.sh 
yum -y install epel-release
yum -y install python2-pip
pip install supervisor

# 8.准备supervisor配置文件
[root@hecs-hqs-01 web-supervisord]# vi supervisord.conf 
[unix_http_server]
file=/tmp/supervisor.sock ; the path to the socket file

[supervisord]
logfile=/tmp/supervisord.log ; # 日志
logfile_maxbytes=50MB ; # 最大50M日志
logfile_backups=10 ; # 轮循日志备份10个
loglevel=info ; # 日志等级记录info的
pidfile=/tmp/supervisord.pid ;pid
nodaemon=true ; # 在前台启动
minfds=102400 ; # 文件描述符限制
minprocs=2000 ; # 进程数
 
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix:///tmp/supervisor.sock ; use a unix:// URL for a unix socket

[program:nginx]
command=/usr/local/nginx/sbin/nginx ; # 前台启动nginx
autostart=true ; # 随着supervisor自动启动
startsecs=10 ; # 启动10s后算正常启动
autorestart=true ; # 程序退出后自动重启
startretries=3 ; # 启动失败自动重试次数
stdout_logfile_maxbytes=20MB ;stdout # 日志文件大小最大20Mb
stdout_logfile=/usr/local/nginx/logs/out.log

[program:tomcat]
command=sh /usr/local/tomcat/bin/mystart.sh ; # 前台启动tomcat
autostart=true ; # 随着supervisor自动启动
startsecs=10 ; # 启动10s后算正常启动
autorestart=true ; #程序退出后自动重启
startretries=3 ; # 启动失败自动重试次数
stdout_logfile_maxbytes=20MB ;stdout 日志文件大小最大20Mb
stdout_logfile=/usr/local/tomcat/logs/catalina.out

# 9.tomcat启动脚本准备
# 由于supervisor无法使用source,需要编写个脚本来启动
[root@hecs-hqs-01 web-supervisord]# vi start_tomcat.sh
source /etc/profile
/usr/local/tomcat/bin/catalina.sh run

# 10.构建镜像
[root@hecs-hqs-01 web-supervisord]# docker build -t web-supervisor .
[root@localhost web-supervisord]# docker images
REPOSITORY         TAG       IMAGE ID       CREATED         SIZE
web-supervisor     latest    5198c5737571   7 minutes ago   1.44GB

# 11.启动容器测试
[root@localhost web-supervisord]# docker run -d web-supervisor /bin/bash -c 'supervisord -c /etc/supervisord.conf'
a326e2589794c4b2a19c23d177f2c418d0583c87605342fd7445694dc40e2219

# 6.基于镜像启动容器和测试web服务
docker exec -it 76782ab /bin/bash
ifconfig

curl 127.0.0.1
curl 127.0.0.1:8080
5.2.4 容器健康检查机制

进程级的健康检查:最简单的,检验进程是否运行。重启策略可以根据检查情况重启已停止的容器。这个检查不足:无法发现应用程序问题。
Docker提供了健康检查机制,可以通过Dockerfile文件在镜像中注入,也可以在启动容器时通过相应选项实现。

1. 在Dockerfile中使用HEALTHCHECK指令

可以在Dockerfile中使用HEALTHCHECK指令声明健康检测配置,用于判断容器主进程的服务状态是否正常,反映容器的实际健康状态。
Dockerfile构建镜像时,加入了HEALTHCHECK指令,基于这样镜像启动的容器,就具备了健康状态检查能力,能自动进行健康检查。
Dockerfile中,只能出现一次HEALTHCHECK指令,出现多次,仅最后一次生效。

一旦有一次健康检查成功,Docker就会确认容器为健康状态。
HEALTHCHECK指令格式:

  1. 设置检查容器健康状况的命令

    HEALTHCHECK [选项] CMD <命令> 
    
    # 选项:
        --interval:设置容器运行后开始健康检查的时间间隔,默认30s。
        --timeout:设置允许健康检查命令允许的最长时间,默认30s。超时即失败。
        --start-period:设置容器启动的初始化时间。(启动过程中的健康检查失败不报错)
        --retries:设置允许连续重试的次数,默认3次。(连续检查失败后视为不健康)
    
    # CMD指令后的命令:指定执行健康检查的具体命令。可以使用shell格式或exec格式。
    
    # 返回值:CMD指令后面的“命令” 执行完毕返回值表示容器的运行状况。
        0:成功。容器是健康且可用的。
        1:失败。容器不健康,不能正常工作。
        2:保留值。暂时不要使用。
    
    # 示例:每5分钟健康检查一次,访问web服务器主页,每次检查3秒以内
    # || 表示上一条命令执行失败后,才执行下一条命令,退出返回值为1,告诉docker健康检查失败
    HEALTHCHECK --interval=5m --timeout=3s CMD curl -f http://localhost/ || exit 1
    
  2. 表示禁止从基础镜像继承HEALTHCHECK指令设置

    HEALTHCHECK NONE
    
2. 启动容器时通过相应选项实现健康检查

可以在执行 docker rundocker create 命令启动创建容器时指定容器的健康检查策略。

[root@localhost ~]# docker run --help
# 指定和运行健康检查
--health-cmd string              Command to run to check health           
# 设置容器运行后开始健康检查的时间间隔(单位:ms/s/m/h),默认是0s
--health-interval duration       Time between running the check (ms|s|m|h) (default 0s)       
# 设置连续失败需要报告的次数
--health-retries int             Consecutive failures needed to report unhealthy            
# 设置容器启动的初始化时间(单位:ms/s/m/h),默认是0s
--health-start-period duration   Start period for the container to initialize before starting        
                                 health-retries countdown (ms|s|m|h) (default 0s)
# 设置允许健康检查命令允许的最长时间(单位:ms/s/m/h),默认是0s
--health-timeout duration        Maximum time to allow one check to run (ms|s|m|h) (default 0s)    
# 禁用容器健康检查指令
--no-healthcheck                 Disable any container-specified HEALTHCHECK                         
3. 案例:测试容器的健康检查功能

容器启动,开始执行健康检查命令,并周期执行,如果返回0,容器处于健康状态。如果返回非0值,容器不健康。

案例1:dockerfile中实现健康检查案例

# 改写上面的php-nginx-supervisord案例
[root@localhost php-nginx-supervisord]# vi Dockerfile
FROM php:7.3-fpm
COPY sources.list /etc/apt/
RUN apt-get clean && apt-get update
RUN apt-get -y install nginx supervisor procps net-tools
RUN mkdir -p /var/log/supervisor
COPY nginx /etc/nginx
COPY supervisor /etc/supervisor
WORKDIR /var/www
RUN usermod -u 1000 www-data
EXPOSE 80
HEALTHCHECK --interval=1m --timeout=3s CMD curl -f http://localhost/ || exit 1
CMD ["/usr/bin/supervisord"]
# 构建镜像、启动容器
[root@localhost php-nginx-supervisord]# docker build -t php-nginx-supervisord . 
[root@localhost php-nginx-supervisord]# docker run -tid -p 8080:80 php-nginx-supervisord
# 查看容器状态
[root@localhost php-nginx-supervisord]# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS                            PORTS                                             NAMES
7bcf645de0ee   php-nginx-supervisord   "docker-php-entrypoi…"   2 seconds ago   Up 2 seconds (health: starting)   9000/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp   nervous_bartik
[root@localhost php-nginx-supervisord]# docker ps
CONTAINER ID   IMAGE                   COMMAND                  CREATED         STATUS                   PORTS                                             NAMES
7bcf645de0ee   php-nginx-supervisord   "docker-php-entrypoi…"   3 minutes ago   Up 3 minutes (healthy)   9000/tcp, 0.0.0.0:8080->80/tcp, :::8080->80/tcp   nervous_bartik

案例2:启动容器时设置选项实现健康检查

# 1.下载busybox镜像
[root@localhost ~]# docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
5cc84ad355aa: Pull complete 
Digest: sha256:5acba83a746c7608ed544dc1533b87c737a0b0fb730301639a0179f9344b1678
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest

# 2.创建容器设置健康检查,检查间隔20s,失败重复1次;并立即查看容器的健康检查状态
[root@localhost ~]#  docker run --rm --name test-health -d \
> --health-cmd 'stat /etc/passwd || exit 1' \
> --health-interval 20s --health-retries 1 \
> busybox sleep 1d; 

[root@localhost ~]#  docker inspect  --format '{{.State.Health.Status}}' test-health
d8fa5965abc02ec8d01722f98257ba2b8f76d50af05890dc8c6e1a18573ee6a3
starting       《————容器启动后的健康状态为Starting

# 3.延迟20s时间,再次查看容器的健康检查状态
[root@localhost ~]# sleep 20s;docker inspect  --format '{{.State.Health.Status}}' test-health
healthy        《————容器处于健康状态

# 4.删除容器的/etc/passwd文件,模拟健康问题
[root@localhost ~]# docker exec test-health rm /etc/passwd

# 5.延迟20s时间,再次查看容器的健康检查状态
[root@localhost ~]# sleep 20s;docker inspect  --format '{{.State.Health.Status}}' test-health
unhealthy     《————容器处于不健康状态
# 进一步查看容器的详情
[root@localhost ~]# docker inspect  --format '{{json .State.Health}}' test-health
{"Status":"unhealthy","FailingStreak":6,"Log":[{"Start":"2022-05-12T04:06:13.855633253+08:00","End":"2022-05-12T04:06:13.899152317+08:00","ExitCode":1,"Output":"stat: can't stat '/etc/passwd': No such file or directory\n"},{"Start":"2022-05-12T04:06:33.910019299+08:00","End":"2022-05-12T04:06:33.953470925+08:00","ExitCode":1,"Output":"stat: can't stat '/etc/passwd': No such file or directory\n"},{"Start":"2022-05-12T04:06:53.956520997+08:00","End":"2022-05-12T04:06:53.998897439+08:00","ExitCode":1,"Output":"stat: can't stat '/etc/passwd': No such file or directory\n"},{"Start":"2022-05-12T04:07:14.002929368+08:00","End":"2022-05-12T04:07:14.045233889+08:00","ExitCode":1,"Output":"stat: can't stat '/etc/passwd': No such file or directory\n"},{"Start":"2022-05-12T04:07:34.050748795+08:00","End":"2022-05-12T04:07:34.090015044+08:00","ExitCode":1,"Output":"stat: can't stat '/etc/passwd': No such file or directory\n"}]}
# 上述信息中报错:stat: can't stat '/etc/passwd': No such file or directory\n,符合前面模拟的健康问题

# 6.查看容器的当前状态
[root@localhost ~]# docker ps
CONTAINER ID   IMAGE     COMMAND      CREATED         STATUS                     PORTS     NAMES
d8fa5965abc0   busybox   "sleep 1d"   5 minutes ago   Up 5 minutes (unhealthy)             test-health
5.2.5 运行时选项覆盖Dockerfile指令

Dockerfile中的FROMMAINTAINERRUNADD这四个指令在运行时是不能被覆盖的,其他的指令在执行docker run(或docker create)命令时都会被相应地覆盖。
从镜像运行一个容器时,可以指定一个新的命令来覆盖Dockerfile的CMD指令。
如果镜像的Dockerfile还声明了ENTRYPOINT指令,则Dockerfile的CMD指令或容器运行时指定的命令均作为参数追加到ENTRYPOINT指令中。

1. 覆盖CMD指令

从镜像运行一个容器的时候,可以指定一个新命令来覆盖Dockerfile中的CMD指令。

[root@localhost ~]# docker history ubuntu
IMAGE          CREATED       CREATED BY                                      SIZE      COMMENT
ff0fea8310f3   7 weeks ago   /bin/sh -c #(nop)  CMD ["bash"]                 0B           《——————默认命令
<missing>      7 weeks ago   /bin/sh -c #(nop) ADD file:1d3b09cf9e041d608…   72.8MB  

# 语法
[root@localhost ~]# docker run --help
Usage:  docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

# 不覆盖的案例:使用CMD的默认命令
[root@localhost ~]# docker run -tid ubuntu 
d6adcb9ca10de89dcb1a1f8ab49b33a715b502e4aa4f1ec240774a7f4d2aa9f5

# 覆盖案例
[root@localhost ~]# docker run -tid ubuntu top            《————top替换默认的bash
0485fee218e64e858ca5b2214b9349b523a3bd41d1ad86c08877240635fa0d32
2. 覆盖ENTRYPOINT指令

使用 --entrypoint选项可以覆盖定义镜像的 Dockerfile 中的 ENTRYPOINT 指令设置。
镜像的 ENTRYPOINT 指令定义容器启动时要执行的命令,在启动容器时不容易被覆盖。
注意:运行时使用--entrypoint 选项将清除镜像任何默认命令。

# 语法
[root@localhost ~]# docker run --help
      --entrypoint string              Overwrite the default ENTRYPOINT of the image

# 案例
[root@localhost ~]# docker pull redis
[root@localhost ~]# docker history redis
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
7614ae9453d1   4 months ago   /bin/sh -c #(nop)  CMD ["redis-server"]         0B        
<missing>      4 months ago   /bin/sh -c #(nop)  EXPOSE 6379                  0B        
<missing>      4 months ago   /bin/sh -c #(nop)  ENTRYPOINT ["docker-entry…   0B        
<missing>      4 months ago   /bin/sh -c #(nop) COPY file:df205a0ef6e6df89…   374B      
<missing>      4 months ago   /bin/sh -c #(nop) WORKDIR /data                 0B        
<missing>      4 months ago   /bin/sh -c #(nop)  VOLUME [/data]               0B        
<missing>      4 months ago   /bin/sh -c mkdir /data && chown redis:redis …   0B        
...省略

# 默认自动运行redis-server的容器中,再运行一个shell
[root@localhost ~]# docker run -ti --entrypoint /bin/bash redis
root@484cb9c42858:/usr/local/bin# ls
docker-entrypoint.sh  redis-benchmark  redis-check-rdb	redis-sentinel
gosu		      redis-check-aof  redis-cli	redis-server
root@bd7640ba7206:/data# exit
exit

# 传递更多参数给ENTRYPOINT
# 默认传递--help给redis-server
[root@localhost ~]# docker run -ti  redis --help
Usage: ./redis-server [/path/to/redis.conf] [options] [-]
       ./redis-server - (read config from stdin)
       ./redis-server -v or --version
       ./redis-server -h or --help
...省略
# 传递--help给redis-cli
[root@localhost ~]# docker run -ti --entrypoint redis-cli redis --help
redis-cli 6.2.6
Usage: redis-cli [OPTIONS] [cmd [arg [arg ...]]]
  -h <hostname>      Server hostname (default: 127.0.0.1).
  -p <port>          Server port (default: 6379).
  -s <socket>        Server socket (overrides hostname and port).
...省略

# 传递空字符串重置容器的入口命令
[root@localhost ~]# docker run -ti --entrypoint="" redis bash
root@5cb647f12d63:/data# exit
exit
3. 覆盖EXPOSE传入端口指令

EXPOSE指令定义对外提供服务的初始传入端口,这些端口可用于容器中的进程。

[root@localhost ~]# docker run --help
      --expose list                    Expose a port or a          # 对外暴露容器的一个端口或一个端口范围
                                       range of ports
      --link list                      Add link to another         # 添加到其他容器的连接
                                       container
  -p, --publish list                   Publish a container s       # 将容器的一个端口或端口范围发布到主机
                                       port(s) to the host
  -P, --publish-all                    Publish all exposed         # 将所有的端口发布到主机随机端口
                                       ports to random ports
									   
# 案例:
[root@localhost ~]# mkdir expose-test  && cd expose-test/
[root@localhost expose-test]# vi default.conf
server {
    listen       81;
    listen  [::]:81;
    server_name  localhost;

    #access_log  /var/log/nginx/host.access.log  main;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    # redirect server error pages to the static page /50x.html
    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }
}
[root@localhost expose-test]# vi Dockerfile
FROM nginx
ADD default.conf /etc/nginx/conf.d/
# 构建镜像
[root@localhost expose-test]# docker build -t expose-test .

# 运行容器
[root@localhost expose-test]# docker run -tid --expose 81 -P expose-test
[root@localhost expose-test]# docker ps
CONTAINER ID   IMAGE         COMMAND                  CREATED              STATUS              PORTS                                                                              NAMES
cfd19ef475fd   expose-test   "/docker-entrypoint.…"   2 seconds ago        Up 2 seconds        0.0.0.0:49155->80/tcp, :::49155->80/tcp, 0.0.0.0:49154->81/tcp, :::49154->81/tcp   determined_allen
# 访问网页发现49154端口才可以访问到网页
4. 覆盖ENV指令

linux中的容器,Docker自动设置了如下环境变量(默认值):

  • HOME (用户主目录):根据USER值设置
  • HOSTNAME (主机名):默认为容器名
  • PATH (执行文件的默认路径):常用目录
  • TERM (终端):若容器分配了伪TTY,则为xterm。

可以使用若干 -e 选项设置任何环境变量,并可以覆盖上述默认环境变量或Dockerfile中ENV指令定义的环境变量。

# 语法
[root@localhost ~]# docker run --help
  -e, --env list                       Set environment variables             # 设置环境变量
      --env-file list                  Read in a file of                     # 读取文件中环境变量
                                       environment variables

# 案例
[root@localhost ~]# export today=Sunday
[root@localhost ~]# echo $today
Sunday
[root@localhost ~]# docker run -t -e "deep=purple" \
> -e today \
> --rm alpine env
# 输出如下信息
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=40951973766d
TERM=xterm
deep=purple
today=Sunday
HOME=/root
5. HEALTHCHECK和WORDDIR指令

覆盖HEALTHCHECK的相关选项:

[root@localhost ~]# docker run --help
# 指定和运行健康检查
--health-cmd string              Command to run to check health           
# 设置容器运行后开始健康检查的时间间隔(单位:ms/s/m/h),默认是0s
--health-interval duration       Time between running the check (ms|s|m|h) (default 0s)       
# 设置连续失败需要报告的次数
--health-retries int             Consecutive failures needed to report unhealthy            
# 设置容器启动的初始化时间(单位:ms/s/m/h),默认是0s
--health-start-period duration   Start period for the container to initialize before starting        
                                 health-retries countdown (ms|s|m|h) (default 0s)
# 设置允许健康检查命令允许的最长时间(单位:ms/s/m/h),默认是0s
--health-timeout duration        Maximum time to allow one check to run (ms|s|m|h) (default 0s)    
# 禁用容器健康检查指令
--no-healthcheck                 Disable any container-specified HEALTHCHECK     

容器中运行二进制文件的默认工作目录是根目录(/),Dockerfile中可以使用WORDDIR指令自定义工作目录。还可以使用 -w选项覆盖WORKDIR指令设置。

[root@localhost ~]# docker run --help
  -w, --workdir string                 Working directory              # 修改容器的工作目录
                                       inside the container

# 案例:
[root@localhost expose-test]# docker run -tid -e "NGINX_VERSION=2.20.1" -e "HOME=/usr" -e today=Sunday \
> nginx
[root@localhost expose-test]# docker exec -ti 4399b3795e13 /bin/bash
root@4399b3795e13:/# pwd
/                        《————工作目录为根目录
[root@localhost expose-test]# docker run -tid -w /usr/local nginx
[root@localhost expose-test]# docker exec -ti 59362a6f79d4 /bin/bash
root@59362a6f79d4:/usr/local# pwd
/usr/local                《————工作目录为/usr/local
6. USER

容器默认用户是root(UID=0),Dockerfile的USER指令可以指定容器运行第一个进程时的默认用户。
启动容器的时候,可以使用 -u(--user)选项指定新的默认用户覆盖镜像的USER指令。

# 语法
[root@localhost ~]# docker run --help
  -u, --user string                    Username or UID            # 指定容器运行第一个进程的默认用户,可以使用用户名、UID、组名、GID参数
                                       (format:
                                       <name|uid>[:<group|gid>])

# 案例
[root@localhost expose-test]# docker run -ti -u daemon ubuntu 
daemon@8aeca4a93520:/$
[root@localhost expose-test]# docker run -ti -u mail  ubuntu
mail@137b5fdfa150:/$ 
7.VOLUME指令

Dockerfile中可以使用 VOLUME 指令定义一个或多个与镜像关联的卷。
容器启动时可以使用 -v--mount--volume-from选项来指定挂载卷。详见:Docker存储管理 https://www.cnblogs.com/xiugeng/p/16194410.html

5.3 限制容器资源使用

5.3.1 容器内存资源限制

容器可使用的内容包括:物理内存、交换空间(SWAP)。
Docker 默认没有设置内存限制的,容器进程可以根据需要尽可能多地使用内存和交换空间。
硬限制:仅允许容器使用不超过给定值的用户内存或系统内存。
软限制:允许容器按需使用内存,但不能影响到内存使用或与占用主机内存。

1. 用户内存限制

同时设置内存和交换空间时,交换空间限制必须大于物理内存限制。

[root@localhost ~]# docker run --help
  -m, --memory bytes                   Memory limit                 # 容器可用内存限制,最低是4MB
      --memory-swap bytes              Swap limit equal to memory plus swap: '-1' to enable     # 容器可以使用的交换空间,-1为无限
                                       unlimited swap

# 案例1:对容器内存使用不限制
[root@localhost ~]# docker run -ti ubuntu /bin/bash

# 案例2:设置内存限制并取消交换空间的限制
[root@localhost ~]# docker run -ti -m 300M --memory-swap -1  ubuntu /bin/bash

# 案例3:只设置内存限制
[root@localhost ~]# docker run -ti -m 300M  ubuntu /bin/bash
[root@localhost ~]# docker inspect --format='{{.HostConfig.Memory}}' a84ca902dbab
314572800      《————314572800/1024/1024=300

# 案例4:同时设置内存和交换空间
[root@localhost ~]# docker run -ti -m 300M --memory-swap 1G  ubuntu /bin/bash
2. 内核内存限制

内核内存不能使用交换空间,消耗过多的内核内存会导致系统服务被阻塞。
内核内存不独立于用户内存,一般在用户内存限制的基础上限制内核内存。
限制内核内存的效果:当内核内存太多时,系统会阻止新进程创建。

[root@localhost ~]# docker run --help
      --kernel-memory bytes            Kernel memory limit         # 容器内核内存限制

# 案例1:同时设置用户内存和内核内存
[root@localhost ~]# docker run -ti -m 200M --kernel-memory 50M ubuntu /bin/bash

# 案例2:只设置内核内存,内存不限制
[root@localhost ~]# docker run -ti --kernel-memory 50M ubuntu /bin/bash
3. 设置内存预留实现软限制

作为一个软限制功能,内存预留并不能保证不会超过限制。主要目的是确保当内存争用严重时,内存就按预留设置进行分配。
内存软限制设置效能:确保容器不会长时间消耗过多内存,每次内存回收将容器内存消耗缩减到软限制之下。

软限制设置规则:

  1. 内存预留值应当始终低于硬限制,否则硬限制会优先触发。
  2. 将内存预留值设置为0表示不作限制。
[root@localhost ~]# docker run --help
    --memory-reservation bytes       Memory soft limit    # 设置内存预留。0表示无限制

# 示例1:限制内存为500MB,内存预留值(软限制)为200MB
[root@localhost ~]# docker run -ti -m 500M --memory-reservation 200M ubuntu /bin/bash

# 示例2:设置内存软限制为1GB,没有设置内存硬限制
[root@localhost ~]# docker run -ti --memory-reservation 1G ubuntu /bin/bash
5.3.2 容器所用CPU资源限制

默认设置是所有容器都可以平等地使用主机CPU资源而不受限制。

1. CPU份额限制

默认情况,所有容器得到相同比例的CPU周期。
通过设置CPU份额权重,分配容器可以使用的CPU周期。

[root@localhost ~]# docker run --help
  -c, --cpu-shares int                 CPU shares (relative weight)   # 设置CPU份额权重,默认值1024

# 案例
[root@localhost ~]# docker run -tid -c 1024 ubuntu /bin/bash
17ea3842fe624a9719817255dba50ba809f3f30c0ffbd1b50e1fd42172e032f0

[root@localhost ~]# docker run -tid -c 512 ubuntu /bin/bash
5c51e13530879ab7ed56bc42c1f71de0b6a2bff9cadbac6fb1364fa4c11c529a
2. CPU周期限制

默认的CFS(完全公平调度器)周期为100ms(100000us)。
设置CPU周期限制容器CPU资源使用。

[root@localhost ~]# docker run --help
	  # --cpu-period 和 --cpu-quota 选项都是以1个CPU为基准。
      --cpu-period int                 Limit CPU CFS (Completely Fair Scheduler) period    # 限制容器CPU CFS周期
      --cpu-quota int                  Limit CPU CFS (Completely Fair Scheduler) quota     # 限制容器CPU CFS配额
	    --cpus decimal                   Number of CPUs         # 指定容器可用CPU资源,浮点数,默认0.000(不受限)
	  
# 案例:若只有一个cpu,容器可以每50ms获得50%的CPU运行时间
[root@localhost ~]# docker run -ti --cpu-period=50000 --cpu-quota=25000 ubuntu /bin/bash

# 案例2:效果同上
[root@localhost web-supervisord]# docker run -ti --cpus=0.5 ubuntu /bin/bash
3. CPU放置限制

限制容器进程运行在什么CPU上。

[root@localhost web-supervisord]# docker run --help
      --cpuset-cpus string             CPUs in which to allow execution (0-3, 0,1)
	  
# 案例:
# 容器的进程允许运行在cpu1\cpu2\cpu3
[root@localhost ~]# docker run -ti --cpuset-cpus='1-3' ubuntu /bin/bash
# 容器的进程允许运行在cpu0
[root@localhost ~]# docker run -ti --cpuset-cpus='0' ubuntu /bin/bash
# 容器的进程允许运行在cpu0\cpu4
[root@localhost ~]# docker run -ti --cpuset-cpus='0,4' ubuntu /bin/bash
4. CPU配额限制

--cpu-quota限制容器进程的CPU配额。
默认值0 表示容器占用一个CPU 100%的CPU资源。
设为 50000 表示容器至多使用CPU50%的资源。

# 容器每100ms(100000us)占用50%
[root@localhost ~]# docker run -tid --cpu-quota=50000 ubuntu

# 容器占用CPU 100%的资源
[root@localhost ~]# docker run -tid --cpu-quota=0 ubuntu
5.3.3 容器所用块I/O带宽的限制

块I/O带宽(Block I/O Bandwith,Blkio):磁盘读写带宽。
Docker 可设置权重,限制容器读写磁盘的带宽。

1. 设置块I/O权重

使用--blkio-weight选项设置一个容器相对于所有其他正在运行的容器的块I/O带宽权重。
可设置的块I/O带宽权重范围是10-1000。
默认所有的容器的权重值为500。0表示被禁用。

[root@localhost ~]# docker run --help
      --blkio-weight uint16            Block IO (relative       
                                       weight), between 10
                                       and 1000, or 0 to
                                       disable (default 0)

案例:
[root@localhost ~]# docker run -tid --blkio-weight 300 ubuntu /bin/bash

[root@localhost ~]# docker run -tid --blkio-weight 0 ubuntu /bin/bash
2. 限制设备读写效率

Docker 按照两种指标限制容器的设备读写速率:每秒字节数、每秒I/O次数。

1)每秒字节数
使用--device-read-bps选项限制指定设备的读取速率,即每秒读取的字节数。
使用--device-write-bps选项限制指定设备的写入速率

单位可以是kb,mb或gb中的一个。

[root@localhost ~]# docker run --help
      --device-read-bps list           Limit read rate (bytes
                                       per second) from a
                                       device (default [])
      --device-write-bps list          Limit write rate
                                       (bytes per second) to
                                       a device (default [])
# 案例:限制/dev/sda的读取速率为1kb/s
[root@localhost ~]# docker run -ti --device-read-bps /dev/sda:1kb ubuntu   # /dev/sda1和/dev/sda2会报错,只能控制磁盘IO不能控制分区IO
[root@localhost ~]# docker inspect --format="{{json .HostConfig.BlkioDeviceReadBps}}" 5d377a47bfe4
[{"Path":"/dev/sda","Rate":1024}]        《——————1024byte即1kb
# 限制/dev/sda的写入速率为1mb/s
[root@localhost ~]# docker run -tid --device-write-bps /dev/sda:1mb ubuntu
[root@localhost ~]# docker inspect --format="{{json .HostConfig.BlkioDeviceWriteBps}}" 37cd8b0da954
[{"Path":"/dev/sda","Rate":1048576}]     《——————1048576byte即1mb

2)每秒I/O次数
限制指定设备的读取和写入速率,用每秒I/O次数表示。

[root@localhost ~]# docker run --help
      --device-read-iops list          Limit read rate (IO
                                       per second) from a
                                       device (default [])
      --device-write-iops list         Limit write rate (IO
                                       per second) to a
                                       device (default [])

# 案例:限制/dev/sda设备的读取速率为每秒1000次
[root@localhost ~]# docker run -ti --device-read-iops /dev/sda:1000 ubuntu
[root@localhost ~]# docker inspect --format="{{json .HostConfig.BlkioDeviceReadIOps}}" 1a9e1fb4c8fc
[{"Path":"/dev/sda","Rate":1000}]

# 限制 /dev/sda 设置的写入速率为每秒15次
[root@localhost ~]# docker run -ti --device-write-iops /dev/sda:15 ubuntu
[root@localhost ~]# docker inspect d5440f301bc5 --format="{{json .HostConfig.BlkioDeviceWriteIOps}}"
[{"Path":"/dev/sda","Rate":15}]
5.3.4 资源限制的实现机制

对容器使用的内存、CPU和块I/O带宽资源的限制具体是由控制组的相应子系统来实现的。

  1. memory子系统设置控制组中的任务所使用的内存限制。
  2. cpu子系统通过调度程序提供对CPU的控制组任务的访问。
  3. blkio子系统为块设备(如磁盘、固态硬盘、USB等)设置输入和输出限制。

注意:在docker run命令中使用–cpu-shares、–memory、–device-read-bps等选项实际上就是在配置控制组,相关的配置文件保存在/sys/fs/cgroup目录中。

# 1.创建容器内存限额300M,CPU权重512
[root@localhost docker]# docker run -tid -p 8080:80 -m 300M --cpu-shares=512 httpd
3cdbdafe0398d40daa8bf334413dc748a3a707cfac96c8ff0ee22a87e5d85e60

# 2.查看/sys/fs/cgroup目录中容器CPU的配置信息
[root@localhost ~]# cd /sys/fs/cgroup/cpu/docker
# 里面有容器ID命名的目录,包含容器CPU相关配置
[root@localhost 3cdbdafe0398d40daa8bf334413dc748a3a707cfac96c8ff0ee22a87e5d85e60]# cat cpu.shares 
512

# 3.查看容器内存限制信息
[root@localhost ~]# cd /sys/fs/cgroup/memory/docker/3cdbdafe0398d40daa8bf334413dc748a3a707cfac96c8ff0ee22a87e5d85e60/
[root@localhost 3cdbdafe0398d40daa8bf334413dc748a3a707cfac96c8ff0ee22a87e5d85e60]# cat memory.limit_in_bytes 
314572800      《——————换算为300M
5.3.5 动态更改容器的资源限制

docker update 命令可以动态地更新容器配置,防止容器在主机上使用太多的资源。
除了kernel-memory选项,其他选项都是立即生效。
kernel-memory选项只能应用于停止的容器,在下一次重启时生效。

[root@localhost ~]# docker update --help
Usage:  docker update [OPTIONS] CONTAINER [CONTAINER...]
Update configuration of one or more containers
Options:
      --blkio-weight uint16        Block IO (relative weight), between 10 and 1000, or 0 to disable (default 0)
      --cpu-period int             Limit CPU CFS (Completely Fair Scheduler) period
      --cpu-quota int              Limit CPU CFS (Completely Fair Scheduler) quota
      --cpu-rt-period int          Limit the CPU real-time period in microseconds
      --cpu-rt-runtime int         Limit the CPU real-time runtime in microseconds
  -c, --cpu-shares int             CPU shares (relative weight)
      --cpus decimal               Number of CPUs
      --cpuset-cpus string         CPUs in which to allow execution (0-3, 0,1)
      --cpuset-mems string         MEMs in which to allow execution (0-3, 0,1)
      --kernel-memory bytes        Kernel memory limit
  -m, --memory bytes               Memory limit
      --memory-reservation bytes   Memory soft limit
      --memory-swap bytes          Swap limit equal to memory plus swap: '-1' to enable unlimited swap
      --pids-limit int             Tune container pids limit (set -1 for unlimited)
      --restart string             Restart policy to apply when a container exits

# 案例:
[root@localhost docker]# docker run -tid -p 8080:80 -m 300M --cpu-shares=512 httpd
[root@localhost ~]# docker inspect e2b4e487a27f --format="{{.HostConfig.CpuShares}}-{{.HostConfig.Memory}}-{{.HostConfig.MemorySwap}}"
512-314572800-629145600

[root@localhost ~]# docker update -m 500M --cpu-shares=400 --memory-swap 800M e2b4e487a27f
[root@localhost ~]# docker inspect e2b4e487a27f --format="{{.HostConfig.CpuShares}}-{{.HostConfig.Memory}}-{{.HostConfig.MemorySwap}}"
400-524288000-838860800

5.4 进入/退出容器内部 exec/exit

#进入容器内部
#docker exec -it  CONTAINER_ID  bash|sh|redis-cli|...
docker exec [OPTIONS] CONTAINER COMMAND [ARG...]
#详细参数
Options:
-d :分离模式: 在后台运行
-i :即使没有附加也保持STDIN 打开
-t :分配一个伪终端

#退出容器内部
exit:直接退出容器并且停止容器运行
ctrl+p+q:退出容器,容器正常运行

#https://blog.tag.gg/showinfo-3-36188-0.html
#Docker容器中执行命令会报例如 bash: ping: command not found 错误,原因是容器中没安装该命令
#支持ip/ping/curl/route/ifconfig/vi/yum命令安装
#如下命令需登录容器内部执行

#bash: ip: command not found
apt-get update && apt-get install -y iproute2
#bash: yum: command not found
apt-get update && apt-get install yum
#bash: ping: command not found
apt-get update && apt install iputils-ping
#bash: ifconfig: command not found
apt-get update && apt install net-tools
#bash: vi: command not found
apt-get update &&  apt-get install vim
#bash: route: command not found
apt-get update && apt-get install -y iproute2 && apt-get update && apt install net-tools
#bash: netstat: command not found
apt-get update && apt install net-tools
#bash: ps: command not found
apt-get update && apt-get install procps
#bash: top: command not found
apt-get update && apt-get install procps

5.5 容器运行操作 start/stop/kill/rm

#启动已停止运行的容器
docker start 容器ID或者容器名
#重启容器
docker restart 容器ID或者容器名
#停止容器
docker stop 容器ID或者容器名
#强制停止容器
docker kill 容器ID或容器名

#删除容器
docker rm 容器ID
#一次性删除多个容器实例
docker rm -f $(docker ps -a -q)
docker ps -a -q | xargs docker rm

5.6 查看运行的容器 ps

监控容器最简单的方法是使用Docker自带的监控命令:docker ps、docker top、docker stats。
可以使用 docker psdocker container ls 命令显示容器列表。

#命令:
docker ps [OPTIONS]
#详细参数
Options:
-a          显示所有的容器,包括未运行的。
-f          根据条件过滤显示的内容。
--format    指定返回值的模板文件。
-l          显示最近创建的容器。
-n          列出最近创建的n个容器。
--no-trunc  不截断输出。
-q          静默模式,只显示容器编号。
-s          显示总的文件大小。

#格式化选项(–-format)
.ID         容器ID
.Image      镜像ID
.Command    Quoted command
.CreatedAt  创建容器的时间点.
.RunningFor 从容器创建到现在过去的时间.
.Ports      暴露的端口.
.Status     容器状态.
.Size       容器占用硬盘大小.
.Names      容器名称.
.Labels     容器所有的标签.
.Label      指定label的值 例如'{{.Label “com.docker.swarm.cpu”}}’
.Mounts     挂载到这个容器的数据卷名称

# 案例
[root@localhost docker]# docker ps 
CONTAINER ID   IMAGE     COMMAND       CREATED         STATUS         PORTS     NAMES
4fd309be3850   ubuntu    "/bin/bash"   3 seconds ago   Up 2 seconds             busy_cray

5.7 容器日志管理 logs

容器的监控和日志管理 https://www.cnblogs.com/xiugeng/p/16285637.html

对运行中的容器,Docker会将日志发送到容器的 STDOUT 和STDERR 上。
可以将STDOUT 和STDERR视为容器的控制台终端。

5.7.1 容器日志管理工具
1. docker logs

docker logs命令输出正在运行的容器的日志信息。默认输出自容器启动以来完整的日志。
docker logs命令可能不会显示有用信息的两种情形:

  • 如果使用将日志发送到文件、外部主机、数据库或另外一个后端日志系统的日志驱动,

    则docker logs命令不会显示有用信息,这时可以通过其他方式处理日志。

  • 如果镜像运行的是Web服务器或数据库等非交互式进程,那么应用程序可能会将输出发送到日志文件而不是STDOUT和STDERR中。

  • 如果容器以后台方式运行,则也不能看到输出的日志。

#命令,docker logs 60176bb01f53 -f -t -n 20
docker logs [OPTIONS] 容器ID或容器名

# 语法
[root@localhost ~]# docker logs --help
Usage:  docker logs [OPTIONS] CONTAINER
Fetch the logs of a container
Options:
      --details        Show extra details provided to logs        # 显示更详细的日志信息
  -f, --follow         Follow log output                          # 跟踪日志输出
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m
                       for 42 minutes)                            # 显示某时间戳之后的日志或显示多少时间之内的日志
  -n, --tail string    Number of lines to show from the end of the logs (default "all")   # 从最后一行开始显示N行
  -t, --timestamps     Show timestamps                            # 显示时间戳
      --until string   Show logs before a timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g.
                       42m for 42 minutes)                        # 显示某时间戳之前的日志或显示多少分钟之前的日志

# 案例1:访问查看日志
# 1.创建apache容器
[root@localhost ~]# docker run --rm -d -p 8080:80 --name web-http httpd
8e226c5a8c4fdcd3bcb91f716d01b2876dda98cc8bc0179021ae783ddf45196b
# 2.访问apache和查看日志
在浏览器访问:http://10.10.10.111:8080
[root@localhost ~]# docker logs web-http
...省略
10.10.10.1 - - [25/May/2022:08:23:32 +0000] "GET / HTTP/1.1" 200 45
# 3.显示更详细信息
[root@localhost ~]# docker logs --details web-http      《————对httpd容器没有区别

# 案例2:持续显示新日志
[root@localhost ~]# docker logs -f web-http
...省略
10.10.10.1 - - [25/May/2022:08:32:04 +0000] "GET / HTTP/1.1" 304 -    《————每次访问页面都会输出新日志
10.10.10.1 - - [25/May/2022:08:32:06 +0000] "GET / HTTP/1.1" 304 -
10.10.10.1 - - [25/May/2022:08:32:08 +0000] "GET / HTTP/1.1" 304 -

# 案例3:显示时间戳(对没有时间的日志非常有用)
[root@localhost ~]# docker logs -t web-http
2022-05-25T08:22:59.900685745Z AH00558: httpd: Could not reliably determine the servers f..   《————前面都会加上时间戳

# 案例4:显示最后几行
[root@localhost ~]# docker logs -n 3  web-http
10.10.10.1 - - [25/May/2022:08:32:06 +0000] "GET / HTTP/1.1" 304 -
10.10.10.1 - - [25/May/2022:08:32:08 +0000] "GET / HTTP/1.1" 304 -
10.10.10.1 - - [25/May/2022:08:32:55 +0000] "-" 408 -

# 案例5:显示最后一分钟内的日志
[root@localhost ~]# docker logs --since 1m  web-http
10.10.10.1 - - [25/May/2022:08:41:51 +0000] "GET / HTTP/1.1" 304 -

# 案例6:显示某个时间戳之后的日志
[root@localhost ~]# docker logs --since 2022-05-25T08:32:10.339156073Z web-http
10.10.10.1 - - [25/May/2022:08:32:55 +0000] "-" 408 -
10.10.10.1 - - [25/May/2022:08:41:51 +0000] "GET / HTTP/1.1" 304 -
10.10.10.1 - - [25/May/2022:08:42:42 +0000] "-" 408 -

# 案例7:显示多少分钟之前的日志
[root@localhost ~]# docker logs --until 30m  web-http
...省略
10.10.10.1 - - [25/May/2022:08:23:32 +0000] "GET / HTTP/1.1" 200 45
10.10.10.1 - - [25/May/2022:08:24:23 +0000] "-" 408 -

# 案例8:显示某时间戳之前的日志
[root@localhost ~]# docker logs --until 2022-05-25T08:32:10.339156073Z web-http
...省略
10.10.10.1 - - [25/May/2022:08:31:56 +0000] "GET / HTTP/1.1" 304 -
10.10.10.1 - - [25/May/2022:08:32:04 +0000] "GET / HTTP/1.1" 304 -
2. docker service logs

docker service logs命令显示swarm某服务/任务的所有容器的日志信息。
该命令适用于集群环境。

# 语法
[root@localhost ~]# docker service logs --help
Usage:  docker service logs [OPTIONS] SERVICE|TASK
Fetch the logs of a service or task
Options:
      --details        Show extra details provided to logs
  -f, --follow         Follow log output
      --no-resolve     Do not map IDs to Names in output
      --no-task-ids    Do not include task IDs in output
      --no-trunc       Do not truncate output
      --raw            Do not neatly format logs
      --since string   Show logs since timestamp (e.g. 2013-01-02T13:23:37Z) or relative (e.g. 42m
                       for 42 minutes)
  -n, --tail string    Number of lines to show from the end of the logs (default "all")
  -t, --timestamps     Show timestamps
5.7.2 容器日志驱动

日志驱动(Logging Driver):Docker提供的帮助用户从运行的容器中提取日志信息的机制。默认的日志驱动是 json-file

选项值如下:

选项值说明
none禁用容器日志,docker logs命令不会输出任何日志信息
json-fileDocker默认的日志驱动。该驱动将日志保存在JSON文件中,Docker负责格式化其内容并输出到STDOUT和STDERR
syslog将日志信息写入syslog日志系统,syslog守护进程必须在主机上运行
journald将日志信息写入journald日志系统,journald守护进程必须在主机上运行
gelf将日志信息写入像Graylog或Logstash这样的GELF(Graylog Extended Log Format)终端
fluentd将日志信息写入fluentd,fluentd守护进程必须在主机上运行
splunk将日志信息写入使用HTTP事件搜集器的splunk
1. 配置默认的日志驱动

daemon.json文件中的log-driver值设为日志驱动名称。
案例1:将默认日志驱动设为syslog

[root@localhost ~]# vi /etc/docker/daemon.json 
[root@localhost ~]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://nxwgbmaq.mirror.aliyuncs.com"],
  "log-driver":"syslog"
}
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker
# 查看确认日志驱动已经改了
[root@localhost ~]# docker info | grep "Logging Driver"
 Logging Driver: syslog
# 开启一个新session,跟踪syslog日志输出
[root@localhost ~]# tail -f /var/log/messages
# 启动一个新的redis容器
[root@localhost ~]# docker run -tid redis
# 可以看到syslog显示redis容器相关日志
May 17 00:40:04 localhost a0e2ba47cf5f[4870]:                _._
May 17 00:40:04 localhost a0e2ba47cf5f[4870]:           _.-``__ ''-._
May 17 00:40:04 localhost a0e2ba47cf5f[4870]:      _.-``    `.  `_.  ''-._           Redis 7.0.11 (00000000/0) 64 bit
May 17 00:40:04 localhost a0e2ba47cf5f[4870]:  .-`` .-```.  ```\/    _.,_ ''-._
May 17 00:40:04 localhost a0e2ba47cf5f[4870]: (    '      ,       .-`  | `,    )     Running in standalone mode
May 17 00:40:04 localhost a0e2ba47cf5f[4870]: |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
May 17 00:40:04 localhost a0e2ba47cf5f[4870]: |    `-._   `._    /     _.-'    |     PID: 1

log-opts可以配置可配置选项。
案例2:日志驱动可配置选项

[root@localhost ~]# vi /etc/docker/daemon.json         《————注意:改之前将之前驱动的容器都删除
{
  "registry-mirrors": ["https://nxwgbmaq.mirror.aliyuncs.com"],
  "log-driver":"json-file",
  "log-opts":{
    "labels":"production_status",
    "env":"os,customer"
  }
}
# 重新加载daemon和重启docker服务
[root@localhost ~]# docker info | grep 'Logging Driver'
 Logging Driver: syslog
[root@localhost ~]# systemctl daemon-reload
[root@localhost ~]# systemctl restart docker
# 查看守护进程的默认日志驱动是否改变:
[root@localhost ~]# docker info | grep 'Logging Driver'
 Logging Driver: json-file
# 查看容器的配置选项
[root@localhost ~]# docker run -tid --name test-opt  ubuntu
5d8ad65d59bca65a988ef0b5c17504601fdc82d2d14b41619e981983bc9bc76d
[root@localhost ~]# docker inspect -f='{{.HostConfig.LogConfig.Type}}--{{.HostConfig.LogConfig.Config}}' test-opt
json-file--map[env:os,customer labels:production_status]
2. 配置容器的日志驱动

启动容器时,可以使用--log-driver 选项来配置日志驱动,可以使用--log-opt设置可配置选项(可以以键值对的方式配置多个)。
注意:同一个值配两次,最后一个生效。

[root@localhost ~]# docker run --help
      --log-driver string              Logging driver for the
                                       container            # 配置容器的日志驱动
      --log-opt list                   Log driver options   # 配置容器的日志驱动可配置选项

# 案例1:配驱动和查看
[root@localhost ~]# docker run --rm -d --log-driver none --name redis redis
cf2d244c250a8b9d457e4f601cd359c73dc9d530788890b6ffd74406293c94f0
[root@localhost ~]# docker inspect -f='{{.HostConfig.LogConfig.Type}}' redis
none
# 案例2:配驱动和可配置选项
[root@localhost ~]# docker run --rm -d --log-driver syslog --log-opt env=os,customer --log-opt labels='test' --name redis02 redis
8cd319bde772774fa00950efa80608ea05823023799554a5e45248c768a3ce29
[root@localhost ~]# docker inspect -f='{{.HostConfig.LogConfig.Type}}-{{.HostConfig.LogConfig.Config}}' redis02
syslog-map[env:os,customer labels:test]
5.7.3 容器日志清理

容器的日志文件会占用大量的空间,经常需要进行清理。如果直接删除 /var/lib/docker/containers/<容器id> 目录下的日志文件,并不会释放磁盘空间,因为日志文件是被打开的。

1. 清理正在运行的容器日志的shell脚本
#!/bin/sh 
logs=$(find /var/lib/docker/containers/ -name *-json.log)  
for log in $logs  
    do  
         echo "clean logs : $log"  
         cat /dev/null > $log  
    done
2. 限制容器的日志上限

在daemon.json配置文件中通过log-opts选项来限制日志大小的上限

#设置容器日志大小上限是500M,容器最多有两个日志文件。
vi /etc/docker/daemon.json
{
  "registry-mirrors": ["https://nxwgbmaq.mirror.aliyuncs.com"],
  "log-driver":"json-file",
	"log-opts": {"max-size":"500m", "max-file":"2"} 
}
5.7.4 将容器日志重定向到LINUX日志系统

运行在Linux操作系统的Docker主机上可以通过配置日志驱动将容器的日志重定向到Linux日志系统。

1. 将容器日志记录到 syslog

syslog是Linux标配的日志记录工具,主要用来收集系统产生的各种日志,日志文件默认放在/var/log目录下。
选择syslog作为日志驱动可将日志定向输出到syslog日志系统中,条件是:syslog守护进程必须在主机上运行。

# 打开或复制一个终端窗口,使用tail工具实时监控系统日志文件/var/log/messages。
[root@host1 ~]# tail -f /var/log/messages
# 打开另一个终端窗口,创建容器,将该容器的日志记录到syslog日志文件。
[root@localhost containers]# docker run --rm -d --log-driver syslog --name redis03 redis
2d7cba9c0c6466c0ecb18e4bfd156710148c8205b299e05f3eed987f873f8b8e
# 观察/var/log/messages输出:
May 26 03:01:06 localhost dockerd: time="2022-05-26T03:01:06.231489908+08:00" level=info msg="Configured log driver does not support reads, enabling local file cache for container logs" container=2d7cba9c0c6466c0ecb18e4bfd156710148c8205b299e05f3eed987f873f8b8e driver=syslog
2. 将容器日志记录到 journald

journald是一个收集并存储日志数据的 systemd 日志系统服务,可以使用 journalctl 命令查看它。
选择journald作为日志驱动可将日志定向输出到systemd日志系统中。

# 创建容器
[root@localhost ~]# docker run --rm -d --log-driver journald --name ubuntu01 ubuntu
cdd3963ab27eac51e8a7d5fc43f92e0f9fb921705e235af822b41bf555a80e23
# 查看systemd日志系统
[root@localhost containers]# journalctl
# 进入日志系统后,输入大写"GG",翻到日志的最后一页
May 26 03:36:10 localhost.localdomain dockerd[3090]: time="2022-05-26T03:36:10.292765481+08:00" level=info msg="ignoring event" container=cdd3963ab27eac51e8a7d5fc43f92e0f9fb921705e235af822b
May 26 03:36:10 localhost.localdomain containerd[876]: time="2022-05-26T03:36:10.293637172+08:00" level=info msg="shim disconnected" id=cdd3963ab27eac51e8a7d5fc43f92e0f9fb921705e235af822b41
May 26 03:36:10 localhost.localdomain containerd[876]: time="2022-05-26T03:36:10.293708026+08:00" level=warning msg="cleaning up after shim disconnected" id=cdd3963ab27eac51e8a7d5fc43f92e0f
May 26 03:36:10 localhost.localdomain containerd[876]: time="2022-05-26T03:36:10.293715955+08:00" level=info msg="cleaning up dead shim"
May 26 03:36:10 localhost.localdomain containerd[876]: time="2022-05-26T03:36:10.302648699+08:00" level=warning msg="cleanup warnings time=\"2022-05-26T03:36:10+08:00\" level=info msg=\"sta
5.7.5 使用Logspout收集所有容器的日志

Logspout 是一个 Docker 容器,大小仅 14MB,使用 BusyBox 作为其核心,它可以将来自容器应用程序的日志发送到某一个中央位置,比如单一 JSON 对象或者通过 HTTP API 可获得的流式端点。

-t 选项容器会以前台方式运行。
-e 选项可以设置容器环境变量。可以用来排除对某个容器日志路由:`-e "LOGSPOUT=ignore"
1. 将所有容器的输出路由到远程syslog

案例:将所有日志转发给远程的syslog服务器,这里将本地服务器作为远程syslog服务器。

# 1.修改centos7的日志服务器rsyslog配置文件
[root@localhost ~]# vi /etc/rsyslog.conf
# 找到以下内容(15\16行)去除行首的‘#’
$ModLoad imudp
$UDPServerRun 514
# 改完后,就允许rsyslog服务在UDP的514端口接收日志信息了。

# 2.重启rsyslog,检查514端口是否开启
[root@localhost ~]# systemctl restart rsyslog
# 安装网络工具
[root@localhost ~]# yum install -y net-tools
# 检查514端口
[root@localhost ~]# netstat -antup | grep 514
tcp        0      0 192.168.100.111:22      192.168.100.1:55959     ESTABLISHED 1514/sshd: root@pts 
udp        0      0 0.0.0.0:514             0.0.0.0:*                           4172/rsyslogd       
udp6       0      0 :::514                  :::*                                4172/rsyslogd

# 3.启动logspout容器,将日志转发到docker主机的syslog服务中
# 下载logspout镜像
[root@localhost ~]# docker pull gliderlabs/logspout
Using default tag: latest
latest: Pulling from gliderlabs/logspout
8572bc8fb8a3: Pull complete 
Digest: sha256:2d81c026e11ac67f7887029dbfd7d36ee986d946066b45c1dabd966278eb5681
Status: Downloaded newer image for gliderlabs/logspout:latest
docker.io/gliderlabs/logspout:latest
# 拉起容器
# 注意:logspout需要访问docker守护进程来获取日志,因此需要把UNIX sockets挂载到容器内。
[root@localhost ~]# docker run --name="logspout" --volume=/var/run/docker.sock:/var/run/docker.sock gliderlabs/logspout syslog+udp://192.168.100.111:514
2022/05/25 20:03:20 # logspout v3.2.14 by gliderlabs
2022/05/25 20:03:20 # adapters: tls udp multiline raw syslog tcp
2022/05/25 20:03:20 # options : 
2022/05/25 20:03:20 persist:/mnt/routes
2022/05/25 20:03:20 # jobs    : http[routes,health,logs]:80 pump routes
2022/05/25 20:03:20 # routes  :
#   ADAPTER	ADDRESS			CONTAINERS	SOURCES	OPTIONS
#   syslog+udp	192.168.100.111:514				map[]

# 4.监控和验证
# 打开syslog日志监控
[root@localhost containers]# tail -f /var/log/messages
# 启动一个新容器
[root@localhost ~]# docker run --rm -d --name redis10 redis
8113851c267c18a5cfe51cde0ad923c8abb5b949aec34df528ba3db3b61a90ed
# 查看到新刷出的日志信息
May 26 04:06:43 localhost containerd: time="2022-05-26T04:06:43.783205236+08:00" level=info msg="starting signal loop" namespace=moby path=/run/containerd/io.containerd.runtime.v2.task/moby/8113851c267c18a5cfe51cde0ad923c8abb5b949aec34df528ba3db3b61a90ed pid=4728
2. 通过HTTP查看Logspout收集的日志

使用 Logspout 的HTTP流模块,可以实时查看由它聚合的本地日志,而不用提供日志路由的URI。

# 1.使用Logspout的HTTP流模块,实时查看由它聚合的本地日志
[root@localhost ~]# docker run -d --name="logspout02" --volume=/var/run/docker.sock:/var/run/docker.sock \
>  --publish=127.0.0.1:8000:80 gliderlabs/logspout
5571173f20bfb08f7935cb0e819d34580753a22b3963d1573f26c8df7ad75900

# 2.使用curl观察容器的日志流。
[root@localhost ~]# curl http://127.0.0.1:8000/logs

# 3.打开另一个终端窗口,启动redis容器
[root@localhost ~]# docker run --rm -d --name redis06 redis
7cd8769551266de5955147e409dd48ed9d6df6c41a6d33a9326beed0924a030f

# 4.切回日志流的终端窗口,会发现关于redis容器启动的日志流。
redis06|1:C 26 May 2022 20:09:47.862 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis06|1:C 26 May 2022 20:09:47.862 # Redis version=6.2.6, bits=64, commit=00000000, modified=0, pid=1, just started
...略

5.8 查看容器内运行的进程 top

容器的监控和日志管理 https://www.cnblogs.com/xiugeng/p/16285637.html

查看容器中正在运行的进程。

docker top 容器ID

# 语法
[root@localhost ~]# docker top --help
Usage:  docker top CONTAINER [ps OPTIONS]
Display the running processes of a container

# 案例
# 查看已有的容器的进程
[root@localhost ~]# docker top busy_cray    《————注意替换为自己的容器
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                1467                1448                0                   01:33               pts/0               00:00:00            /bin/bash
[root@localhost ~]# docker run -tid --name redis-test redis
3a0d4ca05b5c3ab4b65beb333264b504247c6dd4cedee323a7ecdb41c518f6bc
[root@localhost ~]# 
[root@localhost ~]# docker top redis-test
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
polkitd             1655                1636                0                   01:34               pts/0               00:00:00            redis-server *:6379

# 案例:跟参数的情况
[root@localhost ~]# docker top redis-test -e
PID                 TTY                 TIME                CMD
1655                pts/0               00:00:03            redis-server
[root@localhost ~]# docker top redis-test -f
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
polkitd             1655                1636                0                   01:34               pts/0               00:00:03            redis-server *:6379
[root@localhost ~]# docker top redis-test -ef
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
polkitd             1655                1636                0                   01:34               pts/0               00:00:00            redis-server *:6379
[root@localhost ~]# docker top redis-test aux
USER                PID                 %CPU                %MEM                VSZ                 RSS                 TTY                 STAT                START               TIME                COMMAND
polkitd             1655                0.1                 0.4                 52812               9880                pts/0               Ssl+                01:34               0:00                redis-server *:6379

# 案例:查看所有正在运行的容器中的进程信息
[root@localhost ~]# for i in `docker ps | grep Up|awk '{print $1}'`;do echo \ &&docker top $i;done
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
polkitd             1655                1636                0                   01:34               pts/0               00:00:00            redis-server *:6379
 
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                1467                1448                0                   01:33               pts/0               00:00:00            /bin/bash
 
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                1521                1503                0                   01:33               pts/0               00:00:00            /bin/bash
 
UID                 PID                 PPID                C                   STIME               TTY                 TIME                CMD
root                1575                1556                0                   01:33               pts/0               00:00:00            /bin/bash

5.9 查看容器资源使用 stats

5.9.1 docker stats 实时查看

docker stats 命令实时查看容器的系统资源使用情况。

# 语法
[root@localhost ~]# docker stats --help
Usage:  docker stats [OPTIONS] [CONTAINER...]
Display a live stream of container(s) resource usage statistics
Options:
  -a, --all             Show all containers (default shows just running)        # 显示所有的容器(默认只显示运行中的容器)
      --format string   Pretty-print images using a Go template                 # 根据指定格式显示内容
      --no-stream       Disable streaming stats and only pull the first result  # 只显示第一条记录
      --no-trunc        Do not truncate output                                  # 不截断输出,显示出完整的信息(id)

# 案例1:默认查看————连续刷新输出
[root@localhost ~]# docker run -tid --name test1 -m 300M  ubuntu /bin/bash
a63b5add08d9039c0347ddd16a64098ce43e1f917463ee2215f6974031772e2b
[root@localhost ~]# docker stats
容器ID         容器名称        CPU使用百分比    使用内存/最大可用内存  内存使用百分比  网络I/O     磁盘I/O     进程ID
CONTAINER ID   NAME                  CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O     PIDS
a63b5add08d9   test1                 0.00%     536KiB / 300MiB       0.17%     648B / 0B     0B / 0B       1
3a0d4ca05b5c   redis-test            0.10%     7.695MiB / 1.936GiB   0.39%     648B / 0B     39.4MB / 0B   5
4fd309be3850   busy_cray             0.00%     1.59MiB / 300MiB      0.53%     1.09kB / 0B   8.16MB / 0B   1
53c7acadfb91   quizzical_clarke      0.00%     544KiB / 300MiB       0.18%     996B / 0B     0B / 0B       1
687d85c07aaf   xenodochial_swanson   0.00%     552KiB / 1.936GiB     0.03%     996B / 0B     0B / 0B       1  

# 案例2:只输出当前状态(仅一条)
[root@localhost ~]# docker stats --no-stream
CONTAINER ID   NAME                CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O     PIDS
6a5891ff7c91   distracted_galois   0.00%     540KiB / 300MiB       0.18%     648B / 0B     0B / 0B       1
ca8e91bf5a35   test                0.00%     1.586MiB / 1.936GiB   0.08%     1.09kB / 0B   8.13MB / 0B   1
# 指定某个容器且只输出一次
[root@localhost ~]# docker stats --no-stream test1
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT   MEM %     NET I/O     BLOCK I/O   PIDS
a63b5add08d9   test1     0.00%     536KiB / 300MiB     0.17%     648B / 0B   0B / 0B     1

# 案例3:只输出一次,且输出所有容器(包含停止)的状态
[root@localhost ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS                      PORTS      NAMES
4393de823c60   ubuntu    "bash"                   36 seconds ago   Exited (0) 36 seconds ago              happy_leakey
df240f1a0d45   ubuntu    "bash"                   37 seconds ago   Exited (0) 37 seconds ago              interesting_poitras
2570e260027e   ubuntu    "bash"                   47 seconds ago   Exited (0) 46 seconds ago              adasdsad
...略
[root@localhost ~]# docker stats --no-stream -a
CONTAINER ID   NAME                  CPU %     MEM USAGE / LIMIT     MEM %     NET I/O       BLOCK I/O     PIDS
4393de823c60   happy_leakey          0.00%     0B / 0B               0.00%     0B / 0B       0B / 0B       0
df240f1a0d45   interesting_poitras   0.00%     0B / 0B               0.00%     0B / 0B       0B / 0B       0
2570e260027e   adasdsad              0.00%     0B / 0B               0.00%     0B / 0B       0B / 0B       0
a63b5add08d9   test1                 0.00%     536KiB / 300MiB       0.17%     648B / 0B     0B / 0B       1
3a0d4ca05b5c   redis-test            0.08%     7.695MiB / 1.936GiB   0.39%     648B / 0B     39.4MB / 0B   5
4fd309be3850   busy_cray             0.00%     1.91MiB / 300MiB      0.64%     1.09kB / 0B   8.16MB / 0B   1
53c7acadfb91   quizzical_clarke      0.00%     544KiB / 300MiB       0.18%     996B / 0B     0B / 0B       1
687d85c07aaf   xenodochial_swanson   0.00%     552KiB / 1.936GiB     0.03%     996B / 0B     0B / 0B       1

# 案例4:查看某个容器内存限制
[root@localhost ~]# docker stats test1
CONTAINER ID   NAME      CPU %           MEM USAGE / LIMIT      MEM %           NET I/O     BLOCK I/O   PIDS
a63b5add08d9   test1     0.00%           536KiB / 300MiB        0.17%           648B / 0B   0B / 0B     1

# 案例5:自定义输出的内容和格式
[root@localhost ~]# docker stats --no-stream --format "{{.ID}}"
6a5891ff7c91
ca8e91bf5a35
[root@localhost ~]# docker stats --no-stream  --format  "{{.Name}}" test1
test1
[root@localhost ~]# docker stats --no-stream  --format  "{{json .Name}}" test1
"test1"
[root@localhost ~]# docker stats --no-stream  --format  "{{json .Name}}-{{.CPUPerc}}-{{.MemUsage}}" test1
"test1"-0.00%-536KiB / 300MiB
[root@localhost ~]# docker stats --no-stream  --format  "table {{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}" test1
NAME      CPU %     MEM USAGE / LIMIT
test1     0.00%     536KiB / 300MiB
[root@localhost ~]# docker stats --no-stream  --format  "table {{.ID}}\t{{.Name}}\t{{.CPUPerc}}\t{{.MemUsage}}\t{{.MemPerc}}\t{{.NetIO}}\t{{.BlockIO}}\t{{.PIDs}}" myweb
CONTAINER ID   NAME      CPU %     MEM USAGE / LIMIT     MEM %     NET I/O          BLOCK I/O     PIDS
463b15216693   myweb     0.00%     11.57MiB / 1.936GiB   0.58%     2.84kB / 1.5kB   11.9MB / 0B   109
[root@localhost ~]# docker stats --no-stream  --format  "{{.ID}}-{{.Name}}-{{.CPUPerc}}-{{.MemUsage}}-{{.MemPerc}}-{{.NetIO}}-{{.BlockIO}}-{{.PIDs}}" myweb
463b15216693-myweb-0.00%-11.57MiB / 1.936GiB-0.58%-2.84kB / 1.5kB-11.9MB / 0B-109
5.9.2 第三方工具cAdvisor

用于分析正在运行的容器的资源占用情况和性能指标,是具有图形界面、最易于入门的Docker容器监控工具。
cAdvisor以守护进程方式运行,负责收集、聚合、处理、输出运行中容器的数据,可以监控资源隔离参数、历史资源使用情况和网络统计数据。
cAdvisor优势:可以将监控数据导出给第三方工具;
劣势:只能监控一个主机,数据展示功能有限。

# 使用cAdvisor案例
# 1.启动容器用于测试
[root@localhost ~]# docker run --rm -d --name redis redis
b1435f629a764712cf235b63a498e6b5cd58c44e8384146467e79f43233c4652
[root@localhost ~]# docker run --rm -d --name myweb -p 80:80 httpd
dfe1728c9576d72ef2d3652bc0b319e977ff63c8064f8f5aa35ff79b141ff32d
[root@localhost ~]# docker ps 
CONTAINER ID   IMAGE     COMMAND                  CREATED          STATUS          PORTS                               NAMES
dfe1728c9576   httpd     "httpd-foreground"       5 seconds ago    Up 4 seconds    0.0.0.0:80->80/tcp, :::80->80/tcp   myweb
b1435f629a76   redis     "docker-entrypoint.s…"   30 seconds ago   Up 29 seconds   6379/tcp                            redis

# 2.创建启动cAdvisor容器
# 拉取镜像
[root@localhost ~]# docker pull google/cadvisor
Using default tag: latest
latest: Pulling from google/cadvisor
ff3a5c916c92: Pull complete 
44a45bb65cdf: Pull complete 
0bbe1a2fe2a6: Pull complete 
Digest: sha256:815386ebbe9a3490f38785ab11bda34ec8dacf4634af77b8912832d4f85dca04
Status: Downloaded newer image for google/cadvisor:latest
docker.io/google/cadvisor:latest
# 启动容器:
# 4个volume定义的绑定挂载都不能缺,否则无法连接docker守护进程
# centos/redhat主机的容器,必须加上--privileged选项,才能真正拥有root权限,检测主机上的设备
[root@localhost ~]# docker run --privileged \
> --volume /:/rootfs:ro --volume /var/run:/var/run:rw \
> --volume /sys:/sys:ro --volume /var/lib/docker/:/var/lib/docker:ro \
> --publish 8080:8080 --detach --name cadvisor google/cadvisor:latest
7ecef0c00cb922d9686db11234325a00609bf38bde3c9b26f3529245f0eb59af

# 3.访问 cAdvisor监控服务
# 再创建一个限制资源的容器
[root@localhost ~]# docker run -m 300M --memory-swap 500M --memory-reservation 200M -c 512 -tid  ubuntu 
d2eb61efefcf30687a4e70a43793866ffccb7d286e1f2f1ba144a43e91928a8f

#访问网址:http://[主机IP]:8080
#案例访问:http://192.168.100.111:8080/containers/

#cAdvisor提供配置:
--storage_duration:历史数据保存的时间,默认为2min,即只保存最近2min的数据。
--allow_dynamic_housekeeping:控制cAdvisor如何和何时执行周期性的容器状态收集工作。
--global_housekeeping_interval:设置检测是否有新容器的时间周期。
--housekeeping_interval:统计每个容器数据的时间周期,默认每1s取一次数据,选取统计到的最近的60个数据。

#cAdvisor将数据直接导出到本地文件:
[root@localhost ~]# docker run --volume /:/rootfs:ro \
 --volume /var/run:/var/run:rw --volume /sys:/sys:ro \
 --volume /var/lib/docker/:/var/lib/docker:ro \
 --publish 8080:8080 --name cadvisor-stdout \
 google/cadvisor:latest --storage_driver stdout >> data
 
[root@localhost ~]# du -sh *
4.0K	anaconda-ks.cfg
104K	data

[root@localhost ~]# cat data 
cAdvisor监控
5.9.3 Weave Scope

开源的故障诊断与监控工具,除了用于Docker外,还可以用于Kubernetes集群。
Weave Scope会自动生成容器之间的关系图,便于管理员直观地以可视化的方式监控容器化和微服务化的应用。
Weave Scope能够进行跨主机监控,并且消耗的资源非常少。
Weave Scope主要功能:

  • 实时了解容器状态
  • 提供内部细节与深度链接
  • 支持容器的交互与管理
  • 通过插件进行扩展与定制
  1. Weave Scope安装

    前提是安装并运行Docker,此软件以容器方式运行。

    # 1.下载二进制安装脚本
    curl -L git.io/scope -o /usr/local/bin/scope
    
    # 2.赋予脚本可执行权限
    chmod a+x /usr/local/bin/scope
    
    # 3.执行命令下载镜像并启动容器
    [root@localhost ~]# scope launch
    Unable to find image 'weaveworks/scope:1.13.2' locally
    1.13.2: Pulling from weaveworks/scope
    ba3557a56b15: Pull complete 
    dd0e726a9a15: Pull complete 
    05cb5f9d0d32: Pull complete 
    e956cf3e716a: Pull complete 
    Digest: sha256:8591bb11d72f784f784ac8414660759d40b7c0d8819011660c1cc94271480a83
    Status: Downloaded newer image for weaveworks/scope:1.13.2
    6ac75f19cb9cb7d72036d88de376c0f367acfb16cfb4f1e130f86fa875a1ee04
    Scope probe started
    Weave Scope is listening at the following URL(s):
      * http://192.168.100.111:4040/
    
  2. 访问熟悉weave scope界面

5.10 查看容器内部细节 inspect

#以 json 格式得到 docker 镜像/容器的元数据
docker inspect [OPTIONS] NAME|ID [NAME|ID...]
#详细参数
Options:
--format        指定输出格式,可以使用 Go 模板语言自定义输出格式;
--type          指定要查看的 Docker 对象类型,包括 container、image、network、volume;
--size          显示 Docker 对象的磁盘使用情况;
-v , --verbose  显示更详细的信息

5.11 容器与宿主机文件拷贝 cp

#从容器复制文件到宿主机
docker cp [OPTIONS] CONTAINER:SRC_PATH DEST_PATH|-

#从宿主机复制文件到容器
docker cp [OPTIONS] SRC_PATH|- CONTAINER:DEST_PATH
docker copy  /web/redis-6.2-rc2/redis.conf 92323cd4d868:/etc/redis/redis.conf
#SRC_PATH 指定一个文件
#若 DEST_PATH 不存在
#创建 DEST_PATH 所需的文件夹,文件正常保存到 DEST_PATH 中

#若 DEST_PATH 不存在,并以 / 结尾
#错误:目标目录必须存在

#若 DEST_PATH 存在并且是一个文件
#目标被源文件的内容覆盖

#若 DEST_PATH 存在并且是目录
#使用 SRC_PATH 中的基本名称将文件复制到此目录中
#SRC_PATH指定目录

#若 DEST_PATH 不存在
#将 DEST_PATH 创建为目录,并将源目录的内容复制到该目录中
#若 DEST_PATH存在并且是一个文件
#错误:无法将目录复制到文件

#若 DEST_PATH存在并且是目录
#SRC_PATH 不以 /. 结尾,源目录复制到此目录
#SRC_PATH 以 /. 结尾,源目录的内容被复制到该目录中

6. docker镜像

docker镜像:https://www.cnblogs.com/xiugeng/p/15980752.html

6.1 什么是镜像?

是一种轻量级、可执行的独立软件包,它包含运行某个软件所需的所有内容,我们把应用程序和配置依赖打包好形成一个可交付的运行环境(包括代码、运行时需要的库、环境变量和配置文件等),这个打包好的运行环境就是image镜像文件。

只有通过这个镜像文件才能生成Docker容器实例(类似Java中new出来一个对象)。分层的镜像
以我们的pull为例,在下载的过程中我们可以看到docker的镜像好像是在一层一层的在下载

UnionFS(联合文件系统):Union文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。

特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录

6.2 Docker镜像加载原理

Docker镜像加载原理:
docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。
bootfs(boot file system)主要包含bootloader和kernel, bootloader主要是引导加载kernel, Linux刚启动时会加载bootfs文件系统,在Docker镜像的最底层是引导文件系统bootfs。这一层与我们典型的Linux/Unix系统是一样的,包含boot加载器和内核。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由bootfs转交给内核,此时系统也会卸载bootfs。

rootfs (root file system) ,在bootfs之上。包含的就是典型 Linux 系统中的 /dev, /proc, /bin, /etc 等标准目录和文件。rootfs就是各种不同的操作系统发行版,比如Ubuntu,Centos等等。

image-20230206193147157

平时我们安装进虚拟机的CentOS都是好几个G,为什么docker这里才200M??

对于一个精简的OS,rootfs可以很小,只需要包括最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供 rootfs 就行了。由此可见对于不同的linux发行版, bootfs基本是一致的, rootfs会有差别, 因此不同的发行版可以公用bootfs。

为什么 Docker 镜像要采用这种分层结构呢?

镜像分层最大的一个好处就是共享资源,方便复制迁移,就是为了复用。

比如说有多个镜像都从相同的 base 镜像构建而来,那么 Docker Host 只需在磁盘上保存一份 base 镜像;
同时内存中也只需加载一份 base 镜像,就可以为所有容器服务了。而且镜像的每一层都可以被共享。

重点理解

Docker镜像层都是只读的,容器层是可写的 当容器启动时,一个新的可写层被加载到镜像的顶部。 这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。

当容器启动时,一个新的可写层被加载到镜像的顶部。这一层通常被称作“容器层”,“容器层”之下的都叫“镜像层”。
所有对容器的改动 - 无论添加、删除、还是修改文件都只会发生在容器层中。只有容器层是可写的,容器层下面的所有镜像层都是只读的。

image-20230206193314316

6.3 Docker镜像commit

docker commit提交容器副本使之成为一个新的镜像
docker commit -m="提交的描述信息" -a="作者" 容器ID 要创建的目标镜像名:[标签名]

6.4 容器导入导出

#容器的导出  
docker export CONTAINER_ID > containerName.tar
docker export b48f679497e4 > rabbitMQ.tar

# 容器的导入
cat fileName.tar | docker import - MIRROR_USER/MIRROR_NAME:MIRROR_VERSION

6.5 save 和 export区别

1. docker export 和 docker import

docker export 容器ID/容器Name > xxx.tar 导出一个容器快照
docker import xxx.tar NewImageName:tag 导入一个容器快照到本地镜像库

适用场景:主要用来制作基础镜像,比如从一个ubuntu镜像启动一个容器,然后安装一些软件和进行一些设置后,使用docker export保存为一个基础镜像。然后把这个镜像分发给其他人使用,作为基础的开发环境。(因为export导出的镜像只会保留从镜像运行到export之间对文件系统的修改,所以只适合做基础镜像)

注意事项:
①会丢弃历史记录和元数据。
②启动export与import命令导出导入的镜像必须加/bin/bash或者其他/bin/sh,否则会报错。
③docker export 导出的镜像是不带历史记录的,如果原本的镜像有3层,export 之后只会有1层,这一层为从镜像运行到export之间对文件系统的修改。
④可以使用docker history ImageName/ImageID 查看镜像,只有一层(待测试)。

2. docker commit
docker commit 容器ID/容器Name 生成新的镜像名字

选项说明:
-a:提交的镜像作者
-c:使用dockerfile指令来创建镜像
-m:提交时的说明文字
-p:在commit的时候,将正在运行的容器暂停

适用场景:主要作用是将配置好的一些容器复用,再生成新的镜像。
注意事项:
commit是合并了save、load、export、import这几个特性的一个综合性的命令,它主要做了:
将container当前的读写层保存下来,保存成一个新层
和镜像的历史层一起合并成一个新的镜像
如果原本的镜像有3层,commit之后就会有4层,最新的一层为从镜像运行到commit之间对文件系统的修改。

3. docker save 和 docker load

docker save -o xxx.tar 镜像名 将指定镜像导出。
docker load -i xxx.tar 导入镜像到本地镜像库
适用场景:生产环境没有外网,在本机将镜像打包成tar。拷贝到生产环境,再通过docker push到生产环境本地镜像仓库。

区别:
docker save 保存的是镜像(image)
docker export 保存的是容器(container)
docker load /docker import 载入的时候,两者都会恢复为镜像。
docker load 无法对镜像重命名,docker import 可以对镜像指定新名称。
docker export 比 docker save的包要小,原因是save的是一个分层的文件系统,export导出的只是一层文件系统。
docker commit保存镜像文件系统的历史层,docker export保存从镜像运行到export之间对文件系统的修改的最新一层。

6.6 docker commit

docker commit -m="" -a="作者" 容器ID 要创建的目标镜像

7. 将镜像推送到阿里云

  1. 登录阿里云,找到镜像服务,创建命名空间
image-20230206222049503
  1. 创建镜像仓库选择本地镜像
image-20230206222121383
  1. 在linux服务器上登录仓库
docker login --username=阿里云账号 registry.cn-hangzhou.aliyuncs.com
  1. 从仓库中拉取镜像
docker pull registry.cn-hangzhou.aliyuncs.com/compasss/compass-registry:3.9
  1. 将镜像推送到阿里云镜像仓库
docker login --username=crazy2732195202 registry.cn-hangzhou.aliyuncs.com
docker tag 108b9ad78dcd registry.cn-hangzhou.aliyuncs.com/compasss/compass-registry:3.9
docker push registry.cn-hangzhou.aliyuncs.com/compasss/compass-registry:3.9

8. docker 注册中心和仓库

Docker注册中心:https://www.cnblogs.com/xiugeng/p/16043012.html

### 8.1.下载 registry
docker pull registry

### 8.2.启动
docker run -d --name reg -p 5000:5000 registry

### 8.3.推送到私服
docker tag  redis:6.0  192.168.22.162:5000/edis:6.0
docker push 192.168.22.162:5000/edis:6.0

### 8.4.pull到本地
docker pull 192.168.22.162:5000/edis:6.0

9. docker存储管理

Docker存储管理:https://www.cnblogs.com/xiugeng/p/16194410.html

Docker挂载主机目录访问如果出现cannot open directory .: Permission denied
解决办法:在挂载目录后多加一个–privileged=true参数即可

如果是CentOS7安全模块会比之前系统版本加强,不安全的会先禁止,所以目录挂载的情况被默认为不安全的行为,
在SELinux里面挂载目录被禁止掉了额,如果要开启,我们一般使用–privileged=true命令,扩大容器的权限解决挂载目录没有权限的问题,也即使用该参数,container内的root拥有真正的root权限,否则,container内的root只是外部的一个普通用户权限。

卷就是目录或文件,存在于一个或多个容器中,由docker挂载到容器,但不属于联合文件系统,因此能够绕过Union File System提供一些用于持续存储或共享数据的特性:卷的设计目的就是数据的持久化,完全独立于容器的生存周期,因此Docker不会在容器删除时删除其挂载的数据卷

9.1.容器数据卷挂载

docker run -it --privileged=true -v /host_dir:/container_dir  IMAGR_NAME

特点:
1:数据卷可在容器之间共享或重用数据
2:卷中的更改可以直接实时生效
3:数据卷中的更改不会包含在镜像的更新中
4:数据卷的生命周期一直持续到没有容器使用它为止
5:即使docker停止了,重新启动,也会从主机上把文件同步过来

9.2.容器只读不写

docker run -it --privileged=true -v /host_dir:/container_dir:ro  IMAGR_NAME

9.3 容器数据传递

#容器之间配置信息的传递,数据卷的生命周期一直持续到没有容器使用它为止。
docker run -it --privileged=true -v /host_dir:/container_dir --volumes-from CONTIANER_NAME  IMAGR_NAME 

10. dockerFile

10.1 dockerFile概述

Dockerfile是用来构建Docker镜像的文本文件,是由一条条构建镜像所需的指令和参数构成的脚本。

10.1.1 构建三步骤
  1. 编写Dockerfile文件
  2. docker build命令构建镜像
  3. docker run镜像运行容器实例
10.1.2 Dockerfile内容基础知识
  1. 每条保留字指令都必须为大写字母且后面要跟随至少一个参数
  2. 指令按照从上到下,顺序执行
  3. #表示注释
  4. 每条指令都会创建一个新的镜像层并对镜像进行提交
10.1.3 Docker执行Dockerfile的大致流程
  1. docker从基础镜像运行一个容器
  2. 执行一条指令并对容器作出修改
  3. 执行类似docker commit的操作提交一个新的镜像层
  4. docker再基于刚提交的镜像运行一个新容器
  5. 执行dockerfile中的下一条指令直到所有指令都执行完成
10.1.4 从应用软件的角度来看

Dockerfile、Docker镜像与Docker容器分别代表软件的三个不同阶段:

Dockerfile是软件的原材料
Docker镜像是软件的交付品
Docker容器则可以认为是软件镜像的运行态,也即依照镜像运行的容器实例
Dockerfile面向开发,Docker镜像成为交付标准,Docker容器则涉及部署与运维,三者缺一不可,合力充当Docker体系的基石。

image-20230207222240206

  • Dockerfile,需要定义一个Dockerfile,Dockerfile定义了进程需要的一切东西。Dockerfile涉及的内容包括执行代码或者是文件、环境变量、依赖包、运行时环境、动态链接库、操作系统的发行版、服务进程和内核进程(当应用进程需要和系统服务和内核进程打交道,这时需要考虑如何设计namespace的权限控制)等等;
  • Docker镜像,在用Dockerfile定义一个文件之后,docker build时会产生一个Docker镜像,当运行 Docker镜像时会真正开始提供服务;
  • Docker容器,容器是直接提供服务的

10.2 dockerFIle经典案例

# user defined centos7
# 定义当前镜像基于centos
FROM centos
# 定义作者的名字和邮箱
MAINTAINER compass<compass.@qq.com>
# 用来在构建镜像过程中设置环境变量
ENV MYPATH /usr/local
# 指定在创建容器后,终端默认登陆的进来工作目录
WORKDIR $MYPATH
# 容器构建时需要运行的命令
RUN yum -y install vim
RUN yum -y install net-tools
# 对外开放的端口号
EXPOSE 80
# 指定一个容器启动时要运行的命令
CMD echo $MYPATH
CMD echo "my defined centos7  build success"
CMD /bin/bash

10.3 DockerFile常用保留字指令

1. FROM

指定当前镜像是基于那个镜像进行构建

# 例如基于centos镜进行构建
FROM centos:7
2. MAINTAINER

标识镜像的维护作者和邮箱

# 例如
MAINTAINER compass<compass.@qq.com>
3. VOLUME

指定主机和容器之间数据同步的目录

#格式:
VOLUME ["/path/to/dir"]
#示例:
VOLUME ["/data"]
VOLUME ["/var/www", "/var/log/apache", "/etc/apache"]
4. EXPOSE

当前容器对外暴露的端口号

EXPOSE 3060
5. WORKDIR

容器构建完毕后,使用终端进入容器的默认路径

WORKDIR /usr/local/bin/software
6. USER

指定用于以什么样的角色去执行,如果不指定,默认是root

USER root
7. ENV

容器构建过程中设置的环境变量

#定义环境变量
ENV CLASS_PATH /usr/local/jdk/bin
#别的地方引用环境变量
WORKDIR $CLASS_PATH
8. ADD

将宿主机目录下的文件拷贝进镜像且会自动处理URL和解压tar压缩包

将宿主机目录下的文件拷贝到镜像里面 (会自动解压 tar 压缩包),src 可以是一个本地文件或者是一个本地压缩文件,压缩文件会自动解压。还可以是一个 url,如果把 src 写成一个 url,那么 ADD 就类似于 wget 命令,然后自动下载和解压。

#格式:
ADD <src>... <dest>
ADD ["<src>",... "<dest>"]  # 用于支持包含空格的路径
#示例:
ADD hom* /mydir/            # 添加所有以"hom"开头的文件
ADD hom?.txt /mydir/        # ? 替代一个单字符,例如:"home.txt"
ADD test relativeDir/       # 添加 "test" 到 `WORKDIR`/relativeDir/
ADD test /absoluteDir/      # 添加 "test" 到 /absoluteDir/
9. COPY

类似ADD,拷贝文件和目录到镜像中。 将从构建上下文目录中 <源路径> 的文件/目录复制到新的一层的镜像内的 <目标路径> 位置

COPY ["src", "dest"]
10. RUN

容器构建时需要执行的shell指令

#例如容器构建时安装vim编辑器 [shell格式]
RUN yum install vim
#例如容器构建时安装vim编辑器 [CMD格式]
RUN ['可执行文件','参数1','参数n']
RUN ['./statat.sh','-p','3306']
11. CMD

指定容器启动后的要干的事情

Dockerfile 中可以有多个 CMD 指令,但只有最后一个生效,CMD 会被 docker run 之后的参数替换

#CMD 指令:类似于 RUN 指令,用于运行程序,但二者运行的时间点不同;CMD 在docker run 时运行,而非docker build;
#CMD 指令的首要目的在于为启动的容器指定默认要运行的程序,程序运行结束,容器也就结束;
#注意: CMD 指令指定的程序可被 docker run 命令行参数中指定要运行的程序所覆盖。

#语法格式:
CMD <command> 或
CMD ["<executeable>","<param1>","<param2>",...] 
CMD ["<param1>","<param2>",...] #该写法是为 ENTRYPOINT 指令指定的程序提供默认参数;
12. NTRYPOINT

容器启动后需要执行的指令,不会被覆盖

#NTRYPOINT 指令:类似于 CMD 指令,但其不会被 docker run 的命令行参数指定的指令所覆盖,而且这些命令行参数会被当作参数送给 ENTRYPOINT 指令指定的程序;
#但是, 如果运行 docker run 时使用了 --entrypoint 选项,此选项的参数可当作要运行的程序覆盖 ENTRYPOINT 指令指定的程序;

#语法格式:
ENTRYPOINT <command> 或
ENTRYPOINT ["<executeable>","<param1>","<param2>",...]
13. ONBUILD

当该镜像被用于构建其他基础镜像的时候需要触发的操作

#格式:
ONBUILD [INSTRUCTION]
#示例:
ONBUILD ADD . /app/src
14. LABEL

为镜像添加标签

#说明:LABEL会继承基础镜像种的LABEL,如遇到key相同,则值覆盖
LABEL <key>=<value> <key>=<value> <key>=<value> ...

#例如 \ 表示换行
LABEL multi.label1="value1" \
multi.label2="value2" \
15. ARG

指定构建参数

#设置变量命令,ARG命令定义了一个变量,在docker build创建镜像的时候,使用 --build-arg <varname>=<value> 来指定参数
#如果用户在build镜像时指定了一个参数没有定义在Dockerfile种,那么将有一个Warning

ARG username # 声明变量
ARG buildVersion=1 #给变量赋默认值
16. STOPSIGNAL

当容器停止时给系统发送什么样的指令,默认是15

STOPSIGNAL signal

10.4 docker build 构建镜像

Docker构建镜像:https://www.cnblogs.com/xiugeng/p/16074850.html

#语法: 
docker build [OPTIONS] PATH | URL | -
#OPTIONS说明:
--build-arg=[] :设置镜像创建时的变量;
--cpu-shares :设置 cpu 使用权重;
--cpu-period :限制 CPU CFS周期;
--cpu-quota :限制 CPU CFS配额;
--cpuset-cpus :指定使用的CPU id;
--cpuset-mems :指定使用的内存 id;
--disable-content-trust :忽略校验,默认开启;
-f :指定要使用的Dockerfile路径;
--force-rm :设置镜像过程中删除中间容器;
--isolation :使用容器隔离技术;
--label=[] :设置镜像使用的元数据;
-m :设置内存最大值;
--memory-swap :设置Swap的最大值为内存+swap,"-1"表示不限swap;
--no-cache :创建镜像的过程不使用缓存;
--pull :尝试去更新镜像的新版本;
--quiet, -q :安静模式,成功后只输出镜像 ID;
--rm :设置镜像成功后删除中间容器;
--shm-size :设置/dev/shm的大小,默认值是64M;
--ulimit :Ulimit配置。
--squash :将 Dockerfile 中所有的操作压缩为一层。
--tag, -t: 镜像的名字及标签,通常 name:tag 或者 name 格式;可以在一次构建中为一个镜像设置多个标签。
--network: 默认 default。在构建期间设置RUN指令的网络模式

10.5 示例docker构建java环境

# 基础镜像
FROM centos:7
#作者信息
MAINTAINER compass<compass.@qq.com>
# bash进入终端时的默认路径
WORKDIR /
# 下载工具包
RUN yum install -y yum-utils
# 安装vim
RUN yum install -y vim 
# 下载网络工具包
RUN yum install -y net-tools
#创建目录
RUN   mkdir  -p /soft/java
# 将外部的jdk解压到指定路径 指定 -C解压到指定路径,不然解压后不知道存放到哪儿去了
COPY ["jdk-11.0.8_linux-x64_bin.tar.gz", "/soft/java/"]
RUN tar -zxvf /soft/java/jdk-11.0.8_linux-x64_bin.tar.gz  -C /soft/java
# 配置环境变量
ENV JAVA_HOME=/soft/java/jdk-11.0.8
ENV JRE_HOME=${JAVA_HOME}/jre
ENV CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH=${JAVA_HOME}/bin:$PATH
# 暴露端口
EXPOSE 8080
# 执行构建成功的命令
CMD echo "build success"
# 进入到bash终端
CMD /bin/bash

镜像构建,注意最后的.符号

# 文件名必须是叫 DockerFile ,在Dockerfile路径下准备好jdk,并且需要确认解压后的名称和Dockerfile中的名称一致
docker build -t centos-java:11 .

11. docker网络

Docker网络:https://www.cnblogs.com/xiugeng/p/16135849.html

docker启动后,网络情况会产生一个名为docker0的虚拟网桥

11.1 docker网络常用命令

[root@server100 ~]# 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.

#1.查看docker网络模式命令
docker network ls
#2.查看网络数据源
docker network inspect [NETWORT_NAME]
#3.删除网络
docker network rm [NETWORT_NAME]
#4.创建一个网络
docker network create [NETWORT_NAME]
#5.将正在运行的容器连接到网络
docker network connect [NETWORT_NAME] CONTATINER_NAME
#6.指定容器的ip地址
docker network connect --ip 10.10.10.10 网络名 容器
#7.启动容器时需要连接的网络
docker run -itd --network=网络名 即将启动的容器
#8.删除没有使用的网络
docker network prune
#9.强制停止容器的网络
docker network disconnect 网络名 容器

11.2 网络模式

11.2.1 bridge

为每一个容器分配、设置IP等,并将容器连接到docker0的虚拟网桥。若没有特别申明,则为默认自带一个IP以及网络设置。(一人一个)

--network bridge
#没有进行特殊申明的话默认为docker0
11.2.2 host

容器不会虚拟出自己的网卡、IP等,而是使用宿主机的IP和端口。(多人一个)

--network host
11.2.3 none

容器有自己独立的Network namespace,但是没有进行任何的相关配置。(有,但是空的)

--network none
11.2.4 container

新创建的容器不会创建自己的网卡,没有自己的IP,也不会进行相应的配置。而是和一个指定的容器共享IP端口范围等。(自己没有,用别人的)

--network container:[容器名或容器ID]
11.2.5 自定义网络

自定义网络新建时默认依旧是bridge模式,连接到这个自定义网络的容器可以使用服务名称进行通信

#创建一个网络
docker network create van_network
#让容器使用自定义网络
docker run -d -p 8081:8080 --network van_network --name tomcat81 billygoo/tomcat8-jdk8

12. Docker-compose

12.1 Docker-compose是什么

Compose 是 Docker 公司推出的一个工具软件,可以管理多个 Docker 容器组成一个应用。你需要定义一个 YAML 格式的配置文件docker-compose.yml,写好多个容器之间的调用关系。然后,只要一个命令,就能同时启动/关闭这些容器
Docker-Compose是Docker官方的开源项目, 负责实现对Docker容器集群的快速编排。

12.2 docker-compose能做什么

docker建议我们每一个容器中只运行一个服务,因为docker容器本身占用资源极少,所以最好是将每个服务单独的分割开来但是这样我们又面临了一个问题?

如果我需要同时部署好多个服务,难道要每个服务单独写Dockerfile然后在构建镜像,构建容器,这样累都累死了,所以docker官方给我们提供了docker-compose多服务部署的工具

例如要实现一个Web微服务项目,除了Web服务容器本身,往往还需要再加上后端的数据库mysql服务容器,redis服务器,注册中心eureka,甚至还包括负载均衡容器等等

Compose允许用户通过一个单独的docker-compose.yml模板文件(YAML 格式)来定义一组相关联的应用容器为一个项目(project)。

可以很容易地用一个配置文件定义一个多容器的应用,然后使用一条指令安装这个应用的所有依赖,完成构建。Docker-Compose 解决了容器与容器之间如何管理编排的问题。

12.3 安装docker-compose

下载地址:https://docs.docker.com/compose/install/

官网:https://docs.docker.com/compose/compose-file/compose-file-v3/

二进制下载地址:https://github.com/docker/compose/releases/download/v2.5.0/docker-compose-linux-x86_64

#docker-compose离线下载:
https://github.com/docker/compose/releases
#docker compose的v1\v2版本安装及使用上的区别
https://github.com/docker/compose/releases?page=5
https://blog.csdn.net/hanxiaotongtong/article/details/125477514

#安装docker-compose。使用下面的命令行直接将二进制文件存储到/usr/local/bin目录,并重命名为docker-compose:
curl -L https://github.com/docker/compose/releases/download/1.26.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
curl -L "https://github.com/docker/compose/releases/download/1.29.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

#换一种下载方式
wget https://github.com/docker/compose/releases/download/1.26.0/docker-compose-$(uname -s)-$(uname -m) -O /usr/local/bin/docker-compose

#对二进制文件应用可执行权限
chmod +x /usr/local/bin/docker-compose

#创建连接放入/usr/bin,因为/usr/bin在PATH目录下可以不用绝对路径直接访问
sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

#查询docker-compose版本信息:
docker-compose version
#完成!

#如果报错:
bash: line 37: docker-compose: command not found
#原因: jenkins用户执行命令式,会从/usr/bin里找命令。
#解决办法:建立软连接:
ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose

#####################################################
#docker-compose命令:https://blog.csdn.net/t_200609/article/details/130634600
#docker-compose up/down 和 restart 的区别:https://blog.csdn.net/weixin_40734030/article/details/113500085
问题的引出:工作中修改了yaml文件,执行restart命令,发现服务没有实现重启,遂去网上学习了一下,发现先down再up,和直接restart效果不一样。
区别体现:
	只要xxx.yaml文件(默认是docker-compose.yaml文件)有任何修改,一定要执行docker-compose up才会生效,执行docker-compose restart是不会生效的;
	如果是code发生变化,执行docker-compose restart是有效的。
	
#卸载docker-compse
rm -f /usr/local/bin/docker-compose

12.4 Compose核心概念

  • 一文件
    • docker-compose.yml
  • 两要素
    • 服务(service): 一个个应用容器实例,比如订单微服务、库存微服务、mysql容器、nginx容器或者redis容器
    • 工程(project) : 由一组关联的应用容器组成的一个完整业务单元,在 docker-compose.yml 文件中定义。

12.5 Compose使用的三个步骤

  1. 编写Dockerfile定义各个微服务应用并构建出对应的镜像文件
  2. 使用 docker-compose.yml 定义一个完整业务单元,安排好整体应用中的各个容器服务。
  3. 最后,执行docker-compose up命令 来启动并运行整个应用程序,完成一键部署上线

12.6 compose常用命令

#查看帮助
docker compose -h        
#启动所有docker-compose服务
docker compose up    
#启动所有docker-compose服务并后台运行
docker compose up -d       
#停止并删除容器、网络、卷、镜像。
docker compose down                   
#进入容器实例内部  docker-compose exec docker-compose.yml文件中写的服务id /bin/bash
docker compose exec  yml里面的服务id        
#展示当前docker-compose编排过的运行的所有容器
docker compose ps          
#展示当前docker-compose编排过的容器进程
docker compose top                   
#查看容器输出日志
docker compose logs  yml里面的服务id  
#检查配置
docker compose config     
#检查配置,有问题才有输出
docker compose config -q  
#重启服务
docker compose restart   
#启动服务
docker compose start     
#停止服务
docker compose stop   

12.7 docker-compose启动多服务

version: "3"
 
services:
  microService:
    image: order_service:1.6
    container_name: ms01
    ports:
      - "6001:6001"
    volumes:
      - /app/microService:/data
    networks: 
      - docker_compose_net 
    depends_on: 
      - redis
      - mysql
 
  redis:
    image: redis:6.0.8
    ports:
      - "6379:6379"
    volumes:
      - /app/redis/redis.conf:/etc/redis/redis.conf
      - /app/redis/data:/data
    networks: 
      - docker_compose_net
    command: redis-server /etc/redis/redis.conf
 
  mysql:
    image: mysql:5.7
    environment:
      MYSQL_ROOT_PASSWORD: '123456'
      MYSQL_ALLOW_EMPTY_PASSWORD: 'no'
      MYSQL_DATABASE: 'db2021'
      MYSQL_USER: 'root'
      MYSQL_PASSWORD: 'root'
    ports:
       - "3306:3306"
    volumes:
       - /app/mysql/db:/var/lib/mysql
       - /app/mysql/conf/my.cnf:/etc/my.cnf
       - /app/mysql/init:/docker-entrypoint-initdb.d
    networks:
      - docker_compose_net
    command: --default-authentication-plugin=mysql_native_password #解决外部无法访问
 
networks: 
   docker_compose_net: 
#执行
docker compose up -f xxx.yml
#或者(推荐后台执行)
docker compose up -d -f xxx.yml

文章仅供学习使用,非盈利谢谢!
本篇文章下载:docker学习和进阶2023

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
感谢您的提问!以下是一些关于 Docker 进阶学习的建议: 1. 学习容器编排工具:Docker Compose 和 Kubernetes 是两个常用的容器编排工具。通过学习它们,您可以更好地管理和编排多个容器,构建复杂的应用架构。 2. 持续集成与持续部署(CI/CD):学习如何使用 Docker 构建持续集成和持续部署流程。这将有助于自动化应用程序的构建、测试和部署,提高开发和交付效率。 3. 多阶段构建(Multi-stage Builds):掌握多阶段构建技术可以帮助您优化 Docker 镜像的大小和性能。通过在构建过程中创建多个阶段,并且只保留最终运行所需的组件,可以减小镜像的体积。 4. Docker 插件和扩展:探索 Docker 的插件和扩展生态系统,了解如何使用它们来扩展 Docker 的功能。一些常见的扩展包括网络插件、存储插件和身份验证插件,它们可以提供额外的功能和灵活性。 5. 容器安全和隔离:学习如何配置和管理容器的安全性和隔离性。了解容器的安全最佳实践,并使用适当的配置和工具来加强容器的安全性,以防止潜在的攻击和数据泄漏。 6. Docker Swarm:Docker Swarm 是 Docker 官方提供的一个原生的容器编排和集群管理工具。通过学习 Docker Swarm,您可以了解如何使用它来管理分布式应用程序,并实现负载均衡和高可用性。 7. 监控和日志:学习如何监控和记录 Docker 容器的性能和日志。了解如何使用相关工具和技术来监测容器的资源利用率、运行状况和错误日志,以便及时发现和解决问题。 这些是 Docker 进阶学习的一些建议,希望对您有所帮助!如有任何其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值