Dockerfile 是软件的原材料,Docker 镜像是软件的交付品,而 Docker 容器则能够认为是软件的运行态。从应用软件的角度来看,Dockerfile、Docker 镜像与 Docker 容器分别表明软件的三个不一样阶段,Dockerfile 面向开发,Docker 镜像成为交付标准,Docker 容器则涉及部署与运维,三者缺一不可,协力充当 Docker 体系的基石。json
简单来说,Dockerfile构建出Docker镜像,经过Docker镜像运行Docker容器。ubuntu
咱们能够从Docker容器的角度,来反推三者的关系。首先能够来看下图:网络
咱们假设这个容器的镜像经过如下Dockerfile构建而得:运维
FROM ubuntu:14.04 ADD run.sh / VOLUME /data CMD ["./run.sh"]
首先,咱们结合上图来看看Dockerfile与Docker镜像之间的关系。spa
FROM ubuntu:14.04:设置基础镜像,此时会使用基础镜像 ubuntu:14.04 的全部镜像层,为简单起见,图中将其做为一个总体展现。设计
ADD run.sh /:将 Dockerfile 所在目录的文件 run.sh 加至镜像的根目录,此时新一层的镜像只有一项内容,即根目录下的 run.sh。code
VOLUME /data:设定镜像的 VOLUME,此 VOLUME 在容器内部的路径为 /data。须要注意的是,此时并未在新一层的镜像中添加任何文件,即构建出的磁层镜像中文件为空,但更新了镜像的 json 文件,以便经过此镜像启动容器时获取这方面的信息。orm
CMD ["./run.sh"]:设置镜像的默认执行入口,此命令一样不会在新建镜像中添加任何文件,仅仅在上一层镜像 json 文件的基础上更新新建镜像的 json 文件。进程
所以,经过以上分析,以上的Dockerfile能够构建出一个新的镜像,包含4个镜像层,每一条命令会和一个镜像层对应,镜像之间会存在父子关系。图中很清楚的代表了这些关系。内存
Docker镜像是Docker容器运行的基础,没有Docker镜像,就不可能有Docker容器,这也是Docker的设计原则之一。
能够理解的是:Docker镜像毕竟是镜像,属于静态的内容;而Docker容器就不同了,容器属于动态的内容。动态的内容,你们很容易联想到进程,内存,CPU等之类的东西。的确,Docker容器做为动态的内容,都会包含这些。
为了便于理解,你们能够把Docker容器,理解为一个或多个运行进程,而这些运行进程将占有相应的内存,相应的CPU计算资源,相应的虚拟网络设备以及相应的文件系统资源。而Docker容器所占用的文件系统资源,则经过Docker镜像的镜像层文件来提供。
那么做为静态的镜像,如何才有能力转化为一个动态的Docker容器呢?此时,咱们能够想象:第一,转化的依据是什么;第二,由谁来执行这个转化操做。
其实,转化的依据是每一个镜像的json文件,Docker能够经过解析Docker镜像的json的文件,获知应该在这个镜像之上运行什么样的进程,应该为进程配置怎么样的环境变量,此时也就实现了静态向动态的转变。
谁来执行这个转化工做?答案是Docker守护进程。也许你们早就理解这样一句 话:Docker容器实质上就是一个或者多个进程,而容器的父进程就是Docker守护进程。这样的,转化工做的执行就不难理解了:Docker守护进程 手握Docker镜像的json文件,为容器配置相应的环境,并真正运行Docker镜像所指定的进程,完成Docker容器的真正建立。
Docker容器运行起来以后,Docker镜像json文件就失去做用了。此时Docker镜像的绝大部分做用就是:为Docker容器提供一个文件系统的视角,供容器内部的进程访问文件资源。
再次回到上图,咱们再来看看容器和镜像之间的一些特殊关系。首先,以前已经说起Docker镜像是分层管理的,管理Docker容器的时候,Docker镜像仍然是分层管理的。因为此时动态的容器中已经存在进程,进程就会对文件系统视角内的文件进行读写操做,所以,就会涉及一个问题:容器是否会篡改Docker镜像的内容?
答案天然是不会的。统一来说,正如上图,全部的Docker镜像层对于容器来讲,都是只读的,容器对于文件的写操做绝对不会做用在镜像中。
既然如此,实现的原理就很重要,究其根本:Docker守护进程会在Docker镜像的 最上层之上,再添加一个可读写层,容器全部的写操做都会做用到这一层中。而若是Docker容器须要写底层Docker镜像中的文件,那么此时就会涉及一 个叫Copy-on-Write的机制,即aufs等联合文件系统保证:首先将此文件从Docker镜像层中拷贝至最上层的可读写层,而后容器进程再对读 写层中的副本进行写操纵。对于容器进程来说,它只能看到最上层的文件。
那最后咱们再来讲说:Docker容器的文件系统视角中,究竟是不是存在一些内容,不是存储于Docker镜像中的?
此次的答案依旧是确定的。
再次重申一点,Docker镜像中存储的都是一些静态文件。这些文件原则上应该和容器具体信息以及主机信息彻底解藕。那么Docker容器中不存在Docker镜像中的内容主要有如下几点:
1./proc以及/sys等虚拟文件系统的内容
2.容器的hosts文件,hostname文件以及resolv.conf文件,这些事具体环境的信息,原则上的确不该该被打入镜像。
3.容器的Volume路径,这部分的视角来源于从宿主机上挂载到容器内部的路径
4.部分的设备文件