Docker的镜像与容器
-
Image Definition
镜像(Image)就是一堆只读层(read-only layer)的统一视角。
在上图左边,是由多个只读层堆叠在一起。除了最下边层,其他每层都会有一个指针指向下一层。这些是Docker内部的细节,并且都能够在主机的文件系统上访问。统一文件系统(union file system)技术能够将不同的层整合成为一个文件系统,为这些层提供了一个统一的视角,这样就隐藏了多层的存在,在用户角度看来,只存在一个文件系统。
在一个运行中的容器内部,这些层是不可见的。在主机上通常位于 $ /var/lib/docker/aufs $ 目录下。
sudo tree -L 1 /var/lib/docker/
-
Container Definition
容器(container)的定义和镜像(Image)几乎一样,也是一堆同意视角,唯一的区别在于容器的最上边那一层是可读可写的。
要点:容器 = 镜像 + 可读写层
-
Running Container Definition
一个运行态容器(running container)被定义为一个可读写的统一文件系统加上隔离的进程空间和包含其中的进程。
一个容器中的进程可能会对文件进行修改、删除、创建等操作,这些改变都将作用到读写层(read-write layer)。
-
全局理解
$ docker\textit{ }create $ 命令为指定的镜像添加一个可读写层,构成一个新的容器。注意,此时容器并未运行。
$ docker\textit{ }start $ 命令为容器文件系统创建一个进程隔离空间。注意一个容器只能够由一个进程隔离空间。
$ docker\textit{ }run $ 命令与 $ docker\textit{ }start$ 的主要区别在于, $ docker\textit{ }run $ 先是利用镜像创建了一个容器,然后运行这个容器。
$ docker\textit{ }ps $ 命令会列出所有运行中的容器。这个隐藏了非运行态容器的存在,如果需要找到所有的已创建容器,则需要使用 $ docker\textit{ }ps\textit{ }-a $ 命令。
$ docker\textit{ }images $ 会列出创建容器时使用的镜像或者直接pull下来的镜像,并且每一个顶层镜像下面都隐藏了多个镜像层。 $ docker\textit{ }images\textit{ }-a $ 命令则列出所有的镜像,也就是说列出所有的可读层。
$ docker\textit{ }stop $ 命令则会向运行中的容器发送一个SINTREM信号,然后停止所有的进程。
$ docker\textit{ }kill $ 命令向所有在运行中的进程发送一个不友好的SIGKILL信号。
$ docker\textit{ }rm$ 命令会一处构成容器的可读写层。注意,这个命令只能对非运行状态的容器执行。
$ docker\textit{ }rmi $ 命令会移除构成镜像的一个只读层。只能使用 $ docker\textit{ }rmi $ 命令来移除镜像,也可以使用 $ -f $ 参数来前置删除中间的只读层。
$ docker\textit{ }commit $ 命令将容器的可读写层转换为一个只读层,这样就把一个容器转换成了不可变的镜像。
$ docker\textit{ }build $ 命令会反复执行多个命令。build命令根据Dockerfile文件中的FROM指令获取到镜像,然后重复的①run(create和start),②修改,③commit。在循环中的每一步都会生成一个新的层,因此许多新的层会被创建。
$ docker\textit{ }exec $ 命令会在运行中的容器执行一个新进程。
$ docker\textit{ }inspect $ 命令会提取出容器或者进项最顶层的元数据。
$ docker\textit{ }save $ 命令会创建一个镜像的压缩文件,这个文件能够在另外一个主机的docker上使用。和 $ export $ 命令不同,这个命令为每一层都保存了他们的元数据。这个命令支队镜像生效。
$ docker\textit{ }export $ 命令创建一个tar文件,并且移除了元数据和不必要的层,将多个层整合成了一个层,只保存了当前统一视角看到的内容,export后的容器再import到docker中,通过 $ docker\textit{ }images\textit{ }tree $ 命令只能看到一个镜像;而save后的镜像则不同,它能够看到这个镜像的历史镜像。