docker 容器和镜像的区别

        总的来说,镜像是一个包含程序运行代码和必要环境的只读文件,而container更像是头镜像的一个运行态。当程序员进行开发的时候,docker file是程序员开发的东西,docker镜像作为开发结束的交付形态,docker容器则是部署时候的运行态。

      首先我们看一下镜像。镜像可以看作一个文件系统,不含有运行时候的动态数据,内容也不会改变。镜像就是一堆只读层的堆叠:

docker 容器和镜像的区别

        如果觉得不太好理解的话,我们首先先看以下传统Linux文件系统:

        一个典型的 Linux 文件系统由 bootfs 和 rootfs 两部分组成,bootfs(boot file system) 主要包含bootloader 和 kernel,bootloader 主要用于引导加载 kernel,当 kernel 被加载到内存中后 bootfs 会被 umount 掉。rootfs (root file system) 包含的就是典型 Linux 系统中的/dev,/proc,/bin,/etc 等标准目录和文件。传统的 Linux 加载 bootfs 时会先将 rootfs 设为 read-only,然后在系统自检之后将 rootfs 从 read-only 改为 read-write,然后我们就可以在 rootfs 上进行读写操作了。如下如所示

docker 容器和镜像的区别

        但 Docker 在 bootfs 自检完毕之后并不会把 rootfs 的 read-only 改为 read-write,而是利用 union mount(UnionFS 的一种挂载机制)将 image镜像 中的其他的 layer 加载到之前的 read-only 的 rootfs层之上,每一层 layer 都是 rootfs 的结构,并且是read-only 的。所以,我们是无法修改一个已有镜像里面的 layer 的!只有当我们创建一个容器,也就是将 Docker 镜像进行实例化,系统会分配一层空的 read-write 的 rootfs ,用于保存我们做的修改。一层 layer 所保存的修改是增量式的,就像 git 一样。也就是我们部署运行的时候,只能看到最上面一层读写层,而对于这一层下面的多层readonly的layer,我们并不知道,我们也不关心。如下图所示:

docker 容器和镜像的区别

        这个堆叠的文件系统就是联合文件系统(Union FS),它把几层目录堆叠在一起形成了一个虚拟文件系统。docker通过这些文件再加上宿主机的内核提供了一个linux虚拟环境。每一层文件系统都叫做一个layer,但是在镜像中请一定再次注意,每一层都是readonly的,也就是不能被修改。

docker 容器和镜像的区别

        上面就是一个联合文件系统。最底层的是kernel,然后向上看蓝色部分,加上了只读的debian,然后再加上一层一层只读的emacs和apache, 这样形成了一个docker镜像。

       对于容器来说,也是一层一层layer的堆叠,但是最上面那一层并不是只读的!而是读写(read-write)的!在运行的时候,可以对上面最上一层进行读写,所以说容器实际上是docker镜像的运行形态。

        也就是说: 容器 = 镜像image + 读写层