一、Docker镜像

Docker镜像是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置文件等外,还包含了一些为运行时住呢比的配置参数(匿名卷、环境变量、用户等)。镜像不包含任何动态数据,其内容在构建之后不会被改变。

分层存储技术

因为镜像包含操作系统完整的操作系统,其体积往往非常庞大,所以在docker设计的时候,就充分利用UFS(联合文件系统)技术,将其设计为分层存储架构。
镜像构建时,会一层层构建,前一层是后一层的基础。每一层构建完成后就不再发生改变,后一层上的任何改变只是发生在自己这一层。比如,删除前一层文件的操作,实际不是真的删除,而是仅仅在当前层标记为该文件被删除。最终容器运行的时候虽然看不到这个文件,但实际上该文件会一直跟随镜像。
所以我们在创建镜像的时候会看到下载很多层镜像,而且如果该层镜像之前已经下载了就直接读本地缓存。

二、Docker容器

镜像和容器的关系,就像是java中类和实例的关系一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主机执行的进程不同,容器进程运行于属于自己的独立的命名空间。 因此容器可以拥有自己的root文件系统、自己的网络配置、自己的进程空间,甚至自己的用户id空间。容器内的进程是运行在一个隔离的环境里,使用起来就好像在一个虚拟机中一样。
由于镜像是分层存储,容器也是如此,每运行一个容器时,是以镜像为基础,在其上创建一个当前容器的存储层,我们可以称这个为容器运行时读写而准备的存储层为 容器存储层。 存储层的生命周期和容器一样,容器消亡时,存储层也消亡那个,所以任何保存在存储层的数据都会被删除。按照Docker最佳实践的要求,容器不应该向其存储层写入任何数据,容器存储层要保持无状态化。所有文件的写入操作都应该使用数据卷、或者绑定宿主目录,在这些位置的读写会跳过容器的存储层,直接对宿主机发生读写,其性能和稳定性更高。

三、Docker Registry

镜像构建完成之后,可以很容易的在当前宿主机上运行,但是如果其他机器需要使用这个镜像,我们就需要一个类似git的东西,就是Docker Registry。
一个Docker Registry 可以包含多个仓库(Repository);每个仓库可以包含多个标签(Tag);每个标签对应一个镜像。
这里的仓库我总是理解错,它不是类似于maven的那种仓库;举个例子,
ubuntu有很多个版本,我们可以使用 <仓库名>:<标签> 来获取指定软件的指定版本,即 ubuntu:16.04,其中ubuntu是仓库的名字,16.04是标签。

Docker Registry 公开服务

Docker Registry公开服务是开放给用户使用、允许用户管理镜像的Registry服务。最常用的例如官方的 https://hub.docker.com/ ,又或者是国内的阿里云镜像加速。

私有Docker Registry

Q.E.D.