目录
[1. 容器介绍](#1. 容器介绍)
[1.1 什么是容器](#1.1 什么是容器)
[1.2 容器生活案例](#1.2 容器生活案例)
[1.3 为什么需要容器](#1.3 为什么需要容器)
[1.4 容器的生命周期](#1.4 容器的生命周期)
[1.5 容器 OOM](#1.5 容器 OOM)
[1.6 容器异常退出](#1.6 容器异常退出)
[1.7 容器暂停](#1.7 容器暂停)
[1.8 容器命令清单](#1.8 容器命令清单)
[2. 容器操作案例](#2. 容器操作案例)
[2.1 容器基本操作](#2.1 容器基本操作)
[2.2 容器状态迁移](#2.2 容器状态迁移)
[2.3 容器批量处理技巧](#2.3 容器批量处理技巧)
[2.4 容器的交互模式](#2.4 容器的交互模式)
[2.5 容器与宿主机或容器之间的内容拷贝](#2.5 容器与宿主机或容器之间的内容拷贝)
[2.6 容器自动删除](#2.6 容器自动删除)
[2.7 容器自动重启](#2.7 容器自动重启)
[2.8 容器环境变量设置](#2.8 容器环境变量设置)
[2.9 容器详情查看](#2.9 容器详情查看)
[2.10 借助容器执行特殊任务](#2.10 借助容器执行特殊任务)
[2.11 容器镜像的导入导出](#2.11 容器镜像的导入导出)
[2.12 容器日志查看](#2.12 容器日志查看)
[2.13 容器资源查看](#2.13 容器资源查看)
正文开始:
1. 容器介绍
1.1 什么是容器
通俗地讲,容器是镜像的运行实体。镜像是静态的只读文件,而容器带有运行时需要的可写文件层,并且容器中的进程属于运行状态。即容器运行着真正的应用进程。容器有初建、运行、停止、暂停和删除五种状态。
虽然容器的本质是主机上运行的一个进程,但是容器有自己独立的命名空间隔离和资源限制。也就是说,在容器内部,无法看到主机上的进程、环境变量、网络等信息,这是容器与直接运行在主机上进程的本质区别。
容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。 这将添加一个容器层,该层允许修改镜像的整个副本。

1.2 容器生活案例
镜像与容器就相当于同样是开发商提供的毛坯房,但是两家人装修出来的完全不一样。

或者我们都学习了 Java 或者 C++之类的面向对象的语言,可以理解为镜像为基础类,容器是实例化出来的一个个对象,没有用户需要的不一样,里面的内容也就不一样了。

1.3 为什么需要容器
镜像是静态的文件,并不能提供服务,就像我拿了个 Linux 或者 Windows 的光盘一样,只有安装到主机里面运行起来才能对外提供服务,我们才能使用。
1.4 容器的生命周期
容器的生命周期是容器可能处于的状态。
-
created:初建状态
-
running:运行状态
-
stopped:停止状态
-
paused: 暂停状态
-
deleted:删除状态
各生命周期之间的转换关系如图所示:

docker create : 创建容器后,不立即启动运行,容器进入初建状态;
docker run : 创建容器,并立即启动运行,进入运行状态;
docker start : 容器转为运行状态;
docker stop : 容器将转入停止状态;
docker kill : 容器在故障(死机)时,执行 kill(断电),容器转入停止状态,这种操作容易丢失数据,除非必要,否则不建议使用;
docker restart : 重启容器,容器转入运行状态;
docker pause : 容器进入暂停状态;
docker unpause : 取消暂停状态,容器进入运行状态;
docker rm : 删除容器,容器转入删除状态。
killed by out-of-memory(因内存不足被终止) :宿主机内存被耗尽,也被称为 OOM:非计划终止 这时需要杀死最吃内存的容器
container process exitde(异常终止):出现容器被终止后,将进入 Should restart?选择操作:
- yes 需要重启,容器执行 start 命令,转为运行状态。
- no 不需要重启,容器转为停止状态。
1.5 容器 OOM
Docker 在处理 OOM 事件时分为三种情况:
(1)如果容器中的应用耗尽了主机系统分配给容器的内存限额,就会触发 OOM 事件。例如,在容器当中,部署了一个 web 服务。假设主机分配给此容器的内存上限为 1G,当脚本申请的内存大于 1G 时,此容器就会触发 OOM 事件。而在这种情况下,此容器将会被强制关闭。但需要注意的是,此时关闭容器的并非是 Docker Daemon,而是宿主机操作系统。因为一个容器其实就是一组运行在宿主机操作系统当中的进程,宿主机操作系统通过cgroups 对这组进程设定资源上限,当这些进程申请的资源到达上限时,触发的是宿主机操作系统的内核 OOM 事件,因此最终是由宿主机内核来关闭这些进程.
(2) 如果用户不想关闭这个容器,那么可以选择--oom-kill-disable 来禁用 OOM-Killer。使用此参数时,仍需要注意,如果使用-m 设置了此容器内存上限,那么当容器到达内存资源上限时,主机不会关闭容器,但也不会继续向此容器继续分配资源,此时容器将处于 hung 状态。只需要将最坏的情况封闭在一定范围之内,而不至于蔓延出去。
(3)如果用户使用了--oom-kill-disable,但也没有使用-m 来设定上限,因而此时此容器将会尽可能多地使用主机内存资源。换言之,主机内存有多大,它就将用多大。
1.6 容器异常退出
每个容器内部都存在一个 Init 进程,容器中其他所有进程都是此进程的子进程。运行的容器是因为 Init 进程在运行,如果一个子进程因为某种原因造成了退出,那么其父进程也会同步退出,直至 Init 进程也退出。当 Init 进程退出时,也就代表着此容器被关闭。ocker 目前没有办法知道此时的进程退出属于正常退出还是异常退出。当出现容器关闭情况时,Docker Daemon 会尝试再次重新将此容器由 Stopped 状态转为 Running状态。只有设置了--restart 参数的容器,Docker Daemon 才会去尝试启动,否则容器会保持停止状态。
1.7 容器暂停
Docker"剥夺"了此容器的 CPU 资源。而其他资源,如 Memory 资源、Network 资源等还保留未动。如此一来,失去了 CPU 资源的进程,是不会被主机内核系统所调度的,所以此容器就处于"冰封"状态。
1.8 容器命令清单





2. 容器操作案例
2.1 容器基本操作
通过 nginx 镜像文件创建容器:


查看容器详情:(指令中 container 可省略不写)


清理不用的容器:

2.2 容器状态迁移






2.3 容器批量处理技巧

- -a:表示打印所有的容器信息, 包括正在运行和已经退出的
- -q: 表示只返回容器 ID
- -f: 表示基于给的条件过滤 等价于 --filter 选项
容器的批量搜索:




容器的批量操作:


2.4 容器的交互模式
attached 模式:
bash
# 通过 nginx 镜像创建一个容器, 映射 80 端口
docker run --name mynginx006 -p 8106:80 2a06ffcd98fb
-p 8106:80 表示端口映射,第一个端口表示映射到宿主机的端口,第二个端口表示映 射到 Docker 容器的端口。
通过上述方式创建容器,就是 attached****模式,这样容器会在前台运行。
访问服务器网址的时候,每访问一次,命令窗口就会打印一次日志,Docker 容器的日志会实时的展现到窗口并且占用此端口
如果是在 Linux 服务器上,按 Ctrl+C 就会停止掉 Docker 服务,很容易误操作,所以我们需要一个更好的,更稳定的模式,对应的是 detached 模式
attached 模式仅适用于容器和程序的调试阶段。
下面实践一下 attached****模式的用法:第一步: 以 attached 模式创建运行容器, 映射到宿主机的 8106 端口;第二步: 访问服务器的 8106 端口,用浏览器访问服务器 ip 或者域名,默认访问 80端口


detached 模式:
在 docker run --name mynginx006 -p 8106:80 2a06ffcd98fb 命令基础上加一个-d 或者--detach 选项表示 detached****模式, 即在后台执行
-
在后台运行,启动后只显示容器 ID,并且可以输入任何命令
-
就算关掉窗口依然继续运行,停止和删除容器都需要使用 shell 命令,减少了很多的误操作
-
比起 attached 模式更建议使用
下面来实践一下 detached 模式的用法:第一步: 以 detached 模式创建容器, 并映射 8107 端口;第二步: 浏览器访问服务器网址,并查看后台日志


detached 模式转 attached 模式:

interactive 模式:
当我们创建好一个容器之后, 可能需要去容器内部获取一些信息或执行一些命令,就 需要进入到交互式模式。例如创建一个 Ubuntu 容器之后,需要到系统里输入各种Shell命令和系统进行交互就需要进入交互式模式才可以完成。
**情况一:**创建运行容器并进入到交互模式:

-
-i:保持容器运行。通常与 -t 同时使用,加入 it 这两个参数后,容器创建后自动进入容器中,退出容器后,容器自动关闭
-
-t:为容器重新分配一个伪输入终端,通常与 -i 同时使用
-
退出交互式模式: 在交互式 shell 中输入 exit



补充:容器退回到宿主机的shell模式,也意味着该容器的退出。
**情况二:**针对一个已经运行的容器里进入到交互模式


执行exit 退出交互式shell,发现此情况下的通过exec和一个容器进行交互,exit后,不影响该容器的正常运行。
总结:attached模式有一个问题,就是我们退出的时候容器也会停掉。所以attach模式,往往用于调试阶段。 detached模式,我们交互式shell的退出,并不影响我们容器的正常运行,甚至包括断网也不影响。那interactive模式有两种情况:第一种就是我们创建一个交互式模式的容器,我们交互完了,事情也就完了。第二种就是通过exec -it 来完成和一个容器的二次交互,就是一个容器它用了很久以后,看它的服务还正不正常。所以detached模式往往用于生产环境。我们在detached模式下运行一个模式,过了很久后,我们可采取使用我们的docker exec -it 再次进入到容器来做一些检测,也就是说,我们的detached模式配合docker exec 来完成我们的实际生产的一些问题定位以及我们的一个实际生成的服务的运行
2.5 容器与宿主机或容器之间的内容拷贝
启动一个 nginx 服务:

把容器首页拷贝到宿主机上进行编辑,因为容器没有vim编辑器:


然后可在宿主机上通过vim编辑这个 index.html 文件
bash
vim index.html
拷贝宿主机文件到容器中:


2.6 容器自动删除
以交互模式启动一个 nginx,并指定--rm 选项:

容器在交互模式下输入exit退出交互模式,同时容器也会退出,会发现在宿主机shell下输入 docker ps 找不到该容器,同样的docker ps -a | grep mynginx012 也发现没有该容器,该容器自动删除了。
再看看我们后台运行一个容器,docker stop 后会发生什么事情:

提醒:生产环境下 --rm 指令请谨慎使用
2.7 容器自动重启
容器重启选项如下:
-
docker run --restart=no 容器名 :默认值不自动重启
-
docker run --restart=on-failure:3 容器名 : on-failure 若容器的退出状态非 0,则docker 自动重启容器,还可以指定重启次数,若超过指定次数未能启动容器则放弃
-
docker run --restart=always 容器名 :always 容器退出时总是重启
-
docker run --restart=unless-stopped 容器名 unless-stopped 容器退出时总是重启,但不考虑 Docker 守护进程启动时就已经停止的容器
如果容器启动时没有设置--restart 参数,则通过下面命令进行更新:
- docker update --restart=always 容器名




但是:

2.8 容器环境变量设置
启动一个 nginx 容器,配置环境变量,可通过多个 -e 配置多个环境变量。

我们亦可通过一个环境变量的配置文件来配置多个或大量的环境变量:



2.9 容器详情查看
启动容器:


2.10 借助容器执行特殊任务
我们可以直接借助 docker 的容器环境执行一些命令,比如容器中有某个命令而宿主机上没有这个时候借助容器可以完成某些任务。

2.11 容器镜像的导入导出
启动容器,编辑一个自定义首页:

将该容器保存为一个tar包:

将tar包还原成一个镜像:
从HW云的Ubuntu环境下导入进TX云的CentOS环境下,由于是跨云的传输所以 scp 会存在一个速度的限制,我们可通过借助本机来完成拷贝,就是xshell中的Xftp工具



首先HW云和TX云都点击连接Xftp:


拷贝完成后进行导入镜像:

如果使用 import 导入 save 产生的文件,虽然导入不提示错误,但是启动容器时会提示失败,会出现类似"docker: Error response from daemon: Container command not found or does not exist"的错误。我们必须指定启动命令。因为 export 丢失了元数据信息。

通过 docker image inspect mynginx:v0.30 指令查看详情可观察到:


所以我们需要指定启动命令:

2.12 容器日志查看
启动一个 nginx:

查看全部日志:
bash
docker logs mynginx031
实时查看日志:
bash
docker logs -f mynginx031
查看最新的 3 行日志:
bash
docker logs -f -n 3 mynginx031
停止容器,释放资源:
bash
docker stop mynginx031
把容器中的日志,转化为文件提取出来,辅助我们后续的工作:
把日志流重定向到我们的文件里

另一种日志提取方式:

进入到容器所属id的目录下,ls 可发现一个json.log一个json格式的文件,其中就是存放日志的文件,我们可将其打包,从而提取出容器的日志信息。

2.13 容器资源查看
运行一个 nginx:
bash
docker run -d --name mynginx032 -p 8032:80 nginx:1.24.0
我们可以通过 docker top 查看容器中有哪些进程,添加 aux,可以看到占用的内存和 CPU 信息
bash
docker top mynginx032 aux

通过 docker stats 可以看到资源的实时占用变化:
bash
docker stats mynginx032

释放资源
bash
docker stop mynginx032
docker rm mynginx032