1

容器是基于镜像创建的可运行实例,并且单独存在,一个镜像可以创建出多个容器。运行容器化环境时,实际上是在容器内部创建该文件系统的读写副本。这将添加一个容器层,该层允许修改镜像的整个副本。如图所示。

image

容器 VS 虚拟机

在虚拟机模型中,首先要开启物理机并启动Hypervisor引导程序。一旦Hypervisor启动,就会占有机器上的全部物理资源,如CPU、RAM、存储和NIC。Hypervisor接下来就会将这些物理资源划分为虚拟资源,并且看起来与真实物理资源完全一致。然后Hypervisor会将这些资源打包进一个叫作虚拟机的软件结构当中。这样用户就可以使用这些虚拟机,并在其中安装操作系统和应用。

而容器模型则略有不同。服务器启动之后,所选择的操作系统会启动。与虚拟机模型相同,OS也占用了全部硬件资源。在OS层之上,需要安装容器引擎。容器引擎可以获取系统资源,比如进程树、文件系统以及网络栈,接着将资源分割为安全的互相隔离的资源结构,称之为容器。每个容器看起来就像一个真实的操作系统,在其内部可以运行应用。

从更高层面上来讲,Hypervisor是硬件虚拟化——Hypervisor将硬件物理资源划分为虚拟资源;另外,容器是操作系统虚拟化——容器将系统资源划分为虚拟资源。

容器的生命周期

image

容器操作

启动容器

容器启动有两种方式:

  • 使用docker start命令基于已经创建好的容器直接启动。
  • 使用docker run命令直接基于镜像新建一个容器并启动,相当于先执行docker create命令从镜像创建容器,然后再执行docker start命令启动容器。

使用较多的是docker run命令,命令的基础格式为docker [container] run <options> <image>:<tag> <app>。如:

$ docker run -it --name=busybox busybox

当使用docker run创建并启动容器时,Docker后台执行的流程为:

  • Docker会检查本地是否存在busybox镜像,如果镜像不存在则从Docker Hub拉取busybox镜像;
  • 使用busybox镜像创建并启动一个容器;
  • 分配文件系统,并且在镜像只读层外创建一个读写层;
  • 从Docker IP池中分配一个IP给容器;
  • 执行用户的启动命令运行镜像。

上述命令中,-t参数的作用是分配一个伪终端,-i参数则可以终端的STDIN打开,同时使用-it参数可以让我们进入交互模式。

若尝试在容器内执行一些基础命令,可能会发现某些指令无法正常工作。这是因为大部分容器镜像都是经过高度优化的。这意味着某些命令或者包可能没有安装。

需要注意的是,对于容器来说,杀死容器中的主进程,则容器也会被杀死。

进入容器

处于运行状态的容器可以通过 docker attach、docker exec、nsenter 等多种方式进入容器。

  • docker attach: 将本机标准输入(键盘输入)输到容器中,也可以将容器的输出显示在本机的屏幕上,如果你想查看容器运行过程中产生的标准输入输出,用docker attach。
  • docker exec: 如果你要进入已运行的容器,并且执行命令,用docker exec。此时会单独启动一个进程,每个窗口都是独立且互不干扰的,也是使用最多的一种方式。

停止和删除容器

容器启动后,如果我们想停止运行中的容器,可以使用docker stop命令。命令格式为docker [container] stop [-t|--time[=10]]。该命令首先会向运行中的容器发送SIGTERM信号,如果容器内1号进程接受并能够处理SIGTERM,则等待1号进程处理完毕后退出,如果等待一段时间后,容器仍然没有退出,则会发送SIGKILL强制终止容器。

如果你想查看停止状态的容器信息,你可以使用docker ps -a命令。处于终止状态的容器也可以通过docker start命令来重新启动。此外,docker restart命令会将一个运行中的容器终止,并且重新启动它。

删除容器命令的使用方式如下:docker [container] rm [OPTIONS] CONTAINER [CONTAINER...]。如果要删除正在运行中的容器,必须添加-f (或 --force) 参数, Docker会直接发送SIGKILL信号强制终止正在运行的容器。

重启策略

通常建议在运行容器时配置好重启策略。这是容器的一种自我修复能力,可以在指定事件或者错误后重启来完成自我修复。重启策略应用于每个容器,可以作为--restart参数被强制传入docker run命令中,或者在Compose文件中声明(在使用Docker Compose以及Docker Stacks的情况下)。目前容器支持的重启策略包括always、unless-stopped和on-failed。

  • always策略是一种简单的方式。除非容器被明确停止,比如通过docker stop命令,否则该策略会一直尝试重启处于停止状态的容器。该策略有一个很有意思的特性,当Docker daemon重启的时候,停止的容器也会被重启。
  • unless-stopped和always的最大区别,就是那些指定了--restart unless-stopped并处于Stopped(Exited)状态的容器,不会在Docker daemon重启的时候被重启。
  • on-failure策略会在退出容器并且返回值不是0的时候,重启容器。当容器处于Stopped状态,在Docker daemon重启的时候,容器也会被重启。

导入导出容器

我们可以使用docker export命令导出一个容器到文件,不管此时该容器是否处于运行中的状态。

通过docker export命令导出的文件,可以使用docker import命令导入,执行完docker import后会变为本地镜像,最后再使用docker run命令启动该镜像,这样我们就实现了容器的迁移。

导入容器的命令格式为docker import [OPTIONS] file|URL [REPOSITORY[:TAG]]。


与昊
222 声望634 粉丝

IT民工,主要从事web方向,喜欢研究技术和投资之道