什么是docker镜像
Docker镜像是由文件系统叠加而成。
- 最底端是一个引导文件系统,即bootfs:
- 这很像典型的Linux/Unix的引导文件系统。Docker用户几乎永远不会和引导文件系统有什么交互。实际上,当一个容器启动后,它将会被移到内存中,而引导文件系统则会被卸载(unmount),以留出更多的内存供initrd磁盘镜像使用。
- Docker镜像的第二层是root文件系统rootfs:
- 它位于引导文件系统之上。rootfs可以是一种或多种操作系统(如Debian或者Ubuntu文件系统)。
在传统的Linux引导过程中,root文件系统会最先以只读的方式加载,当引导结束并完成了完整性检查之后,它才会被切换为读写模式。但是在Docker里,root文件系统永远只能是只读状态,并且Docker利用联合加载(union mount)技术又会在root文件系统层上加载更多的只读文件系统。联合加载指的是一次同时加载多个文件系统,但是在外面看起来只能看到一个文件系统。联合加载会将各层文件系统叠加到一起,这样最终的文件系统会包含所有底层的文件和目录。
Docker将这样的文件系统称为镜像。一个镜像可以放到另一个镜像的顶部。位于下面的镜像称为父镜像(parent image),可以一次类推,直到镜像栈的最底部,最底部的镜像称为基础镜像(base image)。最后,当从一个镜像启动容器时,Docker会在该镜像的最顶层加载一个读写文件系统。我们想在Docker中运行的程序就是在这个读写层中执行。
当Docker第一次启动一个容器时,初始的读写层是空的。当文件系统发生变化时,这些变化都会应用到这一层上。比如,如果想要修改一个文件,这个文件首先会从该读写层下面的只读层复制到读写层。该文件的只读层版本依然存在,但是已经被读写层中的该文件副本所隐藏。通常这种机制被称为写时复制(copy on write),这也是使Docker如此强大的技术之一。每个只读镜像层都是只读的,并且以后永远不会变化。当创建一个新容器时,Docker会构建出一个镜像栈,并在栈的最顶端添加一个读写层。这个读写层再加上其下面的镜像层以及一些配置数据,就构成了一个容器。在上一章我们已经知道,容器可以修改,它们有自己的状态,并且是可以启动和停止的。容器的这种特点加上镜像分层框架(image-layering framework),使我们可以快速构建镜像并运行包含我们自己的应用程序和服务的容器。
镜像管理
列出镜像:
通过docker images命令列出docker主机上可用的镜像:
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu latest f5bb94a8fac4 2 weeks ago 117.3 MB
在之前我们执行了docker run命令的同时将ubuntu的镜像也下载到了本地,本地镜像都保存在Docker宿主机的/var/lib/docker目录下。镜像从仓库下载下来,而仓库在Registry中。默认的Registry是由Docker公司运营的公共Registry服务,即Docker Hub。https://hub.docker.com/
我们可以通过docker pull来拉去我们想要的镜像,比如说Centos:
# docker pull centos
latest: Pulling from centos
5932f74ff0cd: Pull complete
4a7b890637c2: Pull complete
4beff0251382: Pull complete
Digest: sha256:cb2a2bffb199880da9c69e7f647c01c720c6f95b186a86cfbd3ef168b8032074
Status: Downloaded newer image for centos:latest
# docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
centos latest 4beff0251382 3 days ago 192.5 MB
ubuntu latest f5bb94a8fac4 2 weeks ago 117.3 MB
我们虽然称之为Ubuntu操作系统,但实际上它并不是一个完整的操作系统。它只是一个裁剪版,只包含最低限度的支持系统运行的组件。
为了区分同一个仓库中的不同镜像,Docker提供了一种称为标签(tag)的功能。每个镜像在列出来时都带有一个标签,每个标签对组成特定镜像的一些镜像层标记。这种机制使得在同一个仓库中可以存储多个镜像。我们可以通过在仓库名后面加上一个冒号和标签名来指定该仓库中的某一个镜像。用docker run命令从镜像启动一个容器时,如果该镜像不在本地,Docker会先从Docker Hub下载该镜像。如果没有指定具体的镜像标签,那么Docker会自动下载latest标签的镜像。
查找镜像:
通过docker search命令来查找所有Docker Hub上公共的可用镜像:
# docker search puppet
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
devopsil/puppet Dockerfile for a container with puppet ins... 22 [OK]
camptocamp/puppetserver Puppetlabs's puppetserver 7 [OK]
devopsil/puppet-yum 5 [OK]
vladgh/puppet Ubuntu 16.04 LTS Base image with Puppet 2 [OK]
solict/provisionous-puppet-centos CentOS provisions with Puppet included 2 [OK]
...
这条命令会完成镜像查找工作,返回如下信息:
- 仓库名;
- 镜像描述;
- 用户评论(Stars)——反映出一个镜像的受欢迎程度;
- 是否官方(Official)——由上游开发者管理的镜像;
- 自动构建(Automated)——表示这个镜像是由Docker Hub的自动构建(Automated Build)流程创建的。
## 这条命令将会下载devopsil/puppet镜像到本地
# docker pull devopsil/puppet
## 构建容器
# docker run -i -t devopsil/puppet /bin/bash
[root@b87f9dde62b0 /]# facter
architecture => x86_64
augeasversion => 1.0.0
[root@b87f9dde62b0 /]# puppet --version
3.7.4
这里我们以交互的方式启动了该容器,并且在里面运行了Bash shell。在进入容器shell之后,我们运行了Facter(Puppet的主机探测应用),它也是预安装在镜像之内的。最后,在容器里,我们运行了puppet程序以验证Puppet是否安装正常。