一,什么是镜像?
Docker的镜像文件是由文件系统叠加而成的。最底端是一个引导文件系统,即bootfs。Docker用户几乎永远没有机会和引导文件有什么交互,实际上,当一个容器启动之后,容器就会被移动到内存中,而创建容器镜像文件中的引导文件系统就会被卸载。
Docker镜像的第二层是root文件系统rootfs,位于引导文件系统之上,rootfs可以是一种或者多种操作系统的文件系统(比如说Debian或者Ubuntu的文件系统)。在传统的Linux引导过程中,root文件系统最先会以只读的方式加载,当引导完成并完成了完整性检查之后,才会切换到读写模式。但是在Docker里,root的文件系统只能为只读状态,并且Docker利用联合加载(union mount)技术又会在root文件系统上加载更多的只读文件系统。联合加载是指一次同时加载多个文件系统,但是外面只能看到一个文件系统。联合加载会将各层文件系统叠加在一起,这样最终的文件系统会包含所有底层的文件和目录。Docker将这样的文件系统称为镜像。一个镜像可以放在另一个镜像的顶部,位于下部的镜像称之为父镜像,可以以此类推,直到最底部,最底部的镜像是基础镜像。最后,当从一个镜像启动容器时,Docker会在该镜像的最顶层加载一个读写文件系统。我们想在Docker中运行的程序就是在这个读写层中执行的。
当Docker第一次启动一个容器的时候,初始读写层是空的。当文件系统发生变化时,这些变化都会应用到这一层上。比如,想修改一个文件,这个文件首先会从该读写层下面的只读层复制到该读写层,该文件的只读版本仍然存在,但是已经被读写层中的该文件副本所隐藏。通常这种机制被称为写时复制,这也是Docker如此强大的技术之一。每一个镜像层都是只读的,并且以后永远都不会变化。当创建一个容器的时候,Docker会构建一个镜像栈,并在栈顶添加一个读写层,这个读写层加上其下面的镜像层以及一些配置数据,就构成了一个容器。
在基础镜像中,比如,Ubuntu:14.04中,是不包含Linux的内核的。
二,获取镜像
可以使用docker pull命令从仓库中获取需要的镜像。 如下获取Ubuntu12.04操作系统的镜像
下载过程中,会输出获取镜像的每一层信息。该命令相当于$ sudo docker pull registry.hub.docker.com/ubuntu:12.04,即从注册服务器registry.hub.docker.com中的ubuntu仓库来下载标记为12.04的镜像。
有时候官方的仓库会比较慢,那么可以自己指定从其他的仓库中下载,从其他仓库中下载镜像的时候需要指定完整的仓库注册服务器地址。如下:
$ sudo docker pull dl.dockerpool.com:5000/ubuntu:12.04
三,列出镜像
下载镜像之后,我们可以查看自己本地的镜像,使用$ sudo docker images
REPOSITORY:指明镜像来自于哪一个仓库
TAG:镜像的标记。如果不指定具体的标记,则默认使用latest。
IMAGE ID:它的id号,这个字段是唯一的。id相同表明是同一个镜像。
CREATED:镜像的创建的时间
VIRTUAL SIZE:镜像的大小
四,创建一个镜像
先使用下载的镜像启动一个容器:
然后在这个容器中安装软件gem
$sudo apt-get install gem
那么容器就改变了,然后退出容器。
然后将改变后的容器保存为镜像,使用docker commit命令,如下:
返回的是镜像的ID。
使用docker commit来扩展一个镜像比较简单,但是不方便在一个团队中分享。我们可以使用docker build来创建一个新的镜像,为此必须创建一个Dockfile,包含一些如何创建镜像的指令。
$ mkdir sinatra $ cd sinatra $ touch Dockerfile
Dockerfile中每一条指令都创建镜像的一层,例如:
# This is a comment
FROM ubuntu:14.04
MAINTAINER Docker Newbee <newbee@docker.com>
RUN apt-get -qq update
RUN apt-get -qqy install ruby ruby-dev
RUN gem install sinatra
FROM 指明Docker使用哪个镜像作为基础
#表示的是注释
MAINTAINER 指的是维护者的信息
RUN开头的指令都会在创建中运行,比如安装一个软件包。
编写完成之后就可以使用docker build来生成镜像了。
$sudo docker build -t="hujingwei:hu2" .
其中-t是来添加tag,指定镜像的库和tag信息。"."是Docfile所在的路径(当前目录),也可以替换为一个具体的路径。
build进程在执行操作的过程中,第一件事就是上传这个Dockfile内容,然后Dockfile中的指令被一条一条的执行,每一步都创建一个新的容器,在容器中执行指令并提交修改。当所有的指令都执行完毕之后,返回了最终镜像的id,所有中间步骤所产生的容器都被删除和清理了。注意一个镜像不能超过127层。
五,存入和载入镜像
存入镜像
$sudo docker save -0 ubuntu_14.04.tar ubuntu:14.04 导出镜像到本地文件。
载入镜像文件
sudo docker load --input ubuntu_14.04.tar 从导入的本地文件中再导入到本地镜像库中。或 $sudo docker <ubuntu_14.04.tar
六,移除本地镜像
$sudo docker rmi training/sinatra 注意在删除这个镜像之前需要用 docker rm删除掉依赖于这个镜像的所有容器。