标签:代码 mount 补充 进程 分享 registry 端口 hub 指定
docker是一个轻量级容器,属于操作系统层面的虚拟化技术,封装了文件系统(AUFS)以及网络互联,进程隔离等特性。
传统虚拟化架构:
docker虚拟化架构:
可以看出,docker是没有Guest OS一层的,它属于宿主机上面开启的一个单独进程,共享宿主机的内核和硬件。 传统虚拟化技术每个实例都要虚拟出一套OS的硬件支持,当一台宿主机开启多个虚拟机的时候,这些硬件虚拟无疑是重复的,且占用了大量宿主机的资源。 因此,docker这种轻量级的容器技术会更高效地使用宿主机的内核和硬件资源。同时由于没有完整OS的启动,docker的启动也非常快,就像你在win10里面开启一个浏览器一样,可以类比出,docker的级别与OS上面的application是一层的。
docker库的架构: docker registry -> docker repository -> docker image docker
registry相当于一个邮轮,repository是邮轮上的集装箱,image是集装箱内部的系统镜像。
docker的最小单元为image,docker image是只读的,不支持修改,因此当你看上去修改了一个docker image,哪怕是只改了它的名字,docker的真实实现是复制出来一份列在下面,而原来的仍旧被保留。同时为便于文件管理,docker image 可以通过命令被export为tar包,也可以import tar包成为本地的image。
注意:docker只是提供了一个环境,这个概念是独特的,其他虚拟机是一个完全隔离开的封闭的就像一个完整的物理机那样,而docker的用户获得的是一个基于通用OS上面的一个相同的环境,只要使用相同的image,docker能运行起来,那么环境就是一致的。docker不限制OS的种类、版本,现在docker已经可以支持几乎所有流行的OS,这就使docker变成了跨平台技术,避免了用户环境变化导致的Bug。
docker container 是 docker image 的实例化。
docker提供的这个环境,可以达到如一个纯净OS一样对其进行具体的操作,如安装新的包,文件变更等。上面提到的docker的image是只读,不支持修改image本身,那么这个环境变更真的不是对image进行操作吗?
答:确实不是的,docker的文件系统是AUFS,当我们对image进行修改的时候,表面上是进入那个container,然后做安装命令,文件变更等修改,其实这些变更并不是发生在像传统虚拟系统那样在容器内部,而是在外部!docker container并不是一个封闭独立的空间。
这些变更是存在于本地文件路径/var/lib/docker/aufs/中,每次与原image不同的修改都会放在本地的这个目录中。然而docker也提供了修改这个默认目录的方式,就是在启动容器的时候,使用-v参数设置这个本地目录的映射,每一次修改都是针对映射的这个本地目录,但是要注意以后的每次启动都要带着这个-v参数和这个本地目录,否则又指向了默认的目录相当于启动一个新的container了。
我们来深究一下上面的操作,进入docker container以后,会发现终端的用户名和主机名,包括该用户的root目录(user@dockermachine:~/)都与进入之前不同了,这就是linux的change root命令的效果,利用chroot命令将当前目录映射为该用户的root目录。当exit的时候,恢复到真正的用户root目录,对应的container也被退了出来。
如果想提交这个最新的变更后的环境,实际也是提交一个本地的image,通常是使用commit和dockerfile的方式,而commit方式每次都要提交具体的变更细节,深入docker的实现原理,它是将每次的commit的差异文件存在AUFS文件系统的diff文件夹中,这就很麻烦,因为每次部署环境的时候,如果要检查其中某次提交的文件变更,就要捋顺一遍这个commit列表,这实在是不方便。因此dockerfile的方式被广泛应用。dockerfile会记录以初始的基础image为原点的每次对环境的变更,例如安装了某个新的命令,它像一个描述文件,每当以dockerfile启动的时候,它会先启动其依赖的基础image,然后在按照dockerfile中的命令顺序一条条去执行,最终会获得一个变更后的环境。这样,部署人员只需要维护dockerfile中的代码即可。所有docker的用户仅需要本地拥有一个基础image,然后按照业务需要去get相应的dockerfile,启动的时候就会获得最新的环境,与同组其他同事获得的也会保持一致。
总结一下,docker是如此轻巧灵活仅相当于一个普通app开启一个宿主机的进程,image是只读,dockerfile用来描述变更,container修改映射到本地卷。
补充:
上面多次提到了docker的aufs文件系统,它非常强大,对应的路径是在/var/lib/docker/aufs,它可以分块Blob的去存储一个image,这个image是只读的,所以分块存储可以更快地读取。如果不做-v修改本地映射卷的话,它还可以存储用户在container中修改的变更文件。它还可以存储commit时与基础image的差异文件。提到分块存储image的特性,就要说一下linux的mount,它可以将两个具体路径映射成一个目录,合并包含两个具体路径下的内部文件。例如,mount -t aufs -o dirs="/tmp/a;/tmp/b" none /mnt。执行以后,原/tmp/a和/tmp/b中的内容都会出现在/mnt中。
在docker run一个image的时候,如果不加任何参数,则默认是在docker-hub(https://hub.docker.com/)去下载,这就如同maven,有一个public registry。同样的,如果我想给team建立一个局域网的“邮轮”,提高传输(上传下载,push和pull)的效率,就要自己创建一个registry服务端。 registry创建也非常简单,registry服务本身在docker hub中仍旧是以一个image的形式存在的,所以直接在服务器上docker run registry就ok了。 客户端container可以指定服务端的IP端口去pull image,也可以将本地的image tag成服务端的IP端口下的image,然后push到服务端去。
标签:代码 mount 补充 进程 分享 registry 端口 hub 指定
原文地址:http://www.cnblogs.com/Evsward/p/docker.html