6.1 Docker镜像——简介
对于运维人员来说,Docker镜像可以理解为VM模板,VM模板就像停止运行的VM,而Docker镜像就像停止运行的容器;对于开发人员,可以把镜像理解为类(Class)。
读者需要从镜像仓库中拉取镜像。常见的镜像仓库服务是Docker Hub,但是也存在其他镜像仓库服务。拉取操作会将镜像下载到本地Docker主机,读者可以使用该镜像启动一个或者多个容器。
镜像由多层组成,每层叠加之后,从外部看来就如一个独立的对象。镜像内部是一个精简的操作系统,同时还包含应用运行所必须的文件和依赖包。因为容器的设计初衷就是快速和小巧,所以镜像通常都比较小。
6.2 Docker镜像——详解
前面多次提到镜像就像是停止运行的容器(类)。实际上,读者可以停止某个容器的运行,并从中创建新的镜像。在该前提下,镜像可以理解为一种构建时结构,而容器可以理解为一种运行时结构。
6.2.1 镜像和容器
我们通常使用docker container run 和 docker service create 命令从某个镜像启动一个或多个容器。一旦容器从镜像启动后,二者之间就变成了相互依赖的关系,并且在镜像上启动的容器全部停止之前,镜像是没法被删除的。
容器的目的就是运行应用或者服务,这意味这容器的镜像中必须包含应用/服务运行所必须的操作系统和应用文件。但是,容器由追求小巧和快速,这意味这构建镜像的时候通常需要裁剪掉不必要的部分,保持较小的体积。
例如,Docker镜像不会像一个完整的Linux那样提供多个Shell让读者选择——通常Docker镜像中只有一个精简的Shell,甚至没有Shell。此外,镜像中还不包含内核——容器都是共享所在Docker主机的内核的。所以有时会说容器仅包含必要的操作系统(通常只有操作系统文件和文件系统对象)。Docker官方镜像Alpine Linux大约只有4MB,Ubuntu官方Docker镜像大小大概为110MB,这都远远小于完整的Linux OS镜像。
6.2.2 拉取镜像
Docker主机安装之后,本地并没有镜像。Linux Docker主机本地镜像仓库通常位于 /var/lib/docker/<storage-driver>
,我们可以使用下面的命令来查看Docker主机的本地仓库中包含了哪些镜像
docker image ls
将镜像拉取到本地Docker主机的操作是拉取,如果你要使用最新版本的Ubuntu镜像,那就需要拉取它。可以通过下面的命令去拉取:
docker image pull ubuntu:latest
我的Dokcer主机在前面已经拉取了几个镜像,我们来看下:
[pangcm@docker01 ~]$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu latest 775349758637 2 weeks ago 64.2MB
nginx latest 540a289bab6c 3 weeks ago 126MB
alpine latest 965ea09ff2eb 3 weeks ago 5.55MB
hello-world latest fce289e99eb9 10 months ago 1.84kB
6.2.3 镜像仓库服务
Docker镜像存储在镜像仓库服务(Image Registry)当中。Docker 客户端的镜像仓库服务是可以配置的,默认使用 Docker Hub。Docker Hub可以分为官方仓库和非官方仓库,通常我们更加建议使用官方仓库的镜像,因为这会更加安全可靠;非官方仓库虽然也有不少的优秀镜像,但是使用之前要仔细确认,以免造成不必要的损失。
6.2.4 镜像命名和标签
只要给出镜像的名称和标签,就能在官方仓库中定位一个镜像(采用“:”分隔)。从官方参考拉取镜像时,使用docker image pull 命令。默认情况下,我们拉取的是带有标签 "latest"的镜像,如果要拉取不同的镜像,需要指定特有的标签,如:
docker image pull ubuntu:18.04
这里要注意标签为latest的镜像不保证这是最新的镜像,比如Apline的最新镜像的标签通过是edge。如果要从非官方镜像中拉取镜像,还需要在镜像名称中加入 "/" 分割符。
docker image pull nigelpoulton/tu-demo:v2
如果你要从第三方仓库下载镜像,那还有在前面加上第三方镜像仓库的DNS名称,在拉取镜像之前还需要完成登录。
一个镜像可以有多个标签,比如我们刚刚下载的ubuntu:18.04镜像,以及前面现在的ubuntu:latest 实际上是同一个镜像来的,我们使用docker image ls ubuntu 来查看,可以看到这两个镜像的ID是一样的。
[pangcm@qcloud01 ~]$ docker image ls ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 775349758637 2 weeks ago 64.2MB
ubuntu latest 775349758637 2 weeks ago 64.2MB
6.2.5 使用 --filter 参数
Docker提供了--filter参数来过滤docker image ls命令返回的镜像列表内容。下面的示例指挥返回悬虚(dangling)镜像。
[pangcm@qcloud01 ~]$ docker image ls --filter dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
b3log/solo <none> ff78fbb88bec 2 weeks ago 151MB
b3log/solo <none> f5d60038de5c 3 weeks ago 151MB
悬虚镜像就是那些没有标签的镜像,在列表中展示为<none>:<none>。出现这种情况通常是因为构建了一个新镜像的时候,打上了一个已存在的标签。这时候,Docker会移除旧镜像上的标签,然后把这个标签打在新的镜像上。这样下来,旧的镜像旧变成了悬虚镜像。
使用docker image prune命令可以移除全部的悬虚镜像,如果加上 -a 参数,Docker会额外移除没有被使用的镜像(那些没有被任何容器使用的镜像)。
Docker image 目前支持如下的过滤器:
- dangling:可以指定true或者false,仅返回悬虚镜像或者非悬虚镜像。
- before: 需要镜像名称或者ID作为参数,返回之前被创建的全部镜像
- label:根据标注(label)的名称或者值,对镜像进行过滤。docker image ls 命令中不显示标注内容。
我们除了在docker image ls 中使用filter参数之外,通常在docker search 命令中也会用到。docker search 命令允许通过CLI的方式搜索Docker Hub,比如我要搜索ubuntu的镜像:
[pangcm@qcloud01 ~]$ docker search ubuntu
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 10169 [OK]
dorowu/ubuntu-desktop-lxde-vnc Docker image to provide HTML5 VNC interface … 362 [OK]
rastasheep/ubuntu-sshd Dockerized SSH service, built on top of offi… 235 [OK]
consol/ubuntu-xfce-vnc Ubuntu container with "headless" VNC session… 194 [OK]
ubuntu-upstart Upstart is an event-based replacement for th… 101 [OK]
ansible/ubuntu14.04-ansible Ubuntu 14.04 LTS with ansible 98 [OK]
......
要进一步过滤查询结果,我们可以使用 filter 参数,必要我只要官方的镜像:
[pangcm@qcloud01 ~]$ docker search ubuntu --filter is-official=true
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
ubuntu Ubuntu is a Debian-based Linux operating sys… 10169 [OK]
ubuntu-upstart Upstart is an event-based replacement for th… 101 [OK]
ubuntu-debootstrap debootstrap --variant=minbase --components=m… 40 [OK]
有一点要注意的是,默认情况下,Docker只返回25行结果,要显示更多结果请使用 --limit 参数,最多为100行。
6.2.6 镜像和分层
Docker镜像有一些松耦合的只读镜像层组成,如下图所示:
Docker负责堆叠这些镜像层,并且将它们表示为单个统一对象。在你使用docker image pull ubuntu 拉取镜像的时候,你会发现拉取多个镜像层的过程。此外,我们可以使用docker image inspect 命令来查看镜像的分层情况:
[pangcm@qcloud01 ~]$ docker image inspect ubuntu
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:cc967c529ced563b7746b663d98248bc571afdb3c012019d7f54d6c092793b8b",
"sha256:2c6ac8e5063e35e91ab79dfb7330c6154b82f3a7e4724fb1b4475c0a95dfdd33",
"sha256:6c01b5a53aac53c66f02ea711295c7586061cbe083b110d54dafbeb6cf7636bf",
"sha256:e0b3afb09dc386786d49d6443bdfb20bc74d77dcf68e152db7e5bb36b1cca638"
]
},
...
可以看到Ubuntu这个镜像一个包含了4个镜像层,这里使用了SHA256散列值来表示镜像层。
所有的Docker镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。举个例子,加入基于ubuntu:18.04创建了一个新的镜像层,这就是新镜像层的第一层;如果在该镜像中添加python包,就会在这个基础上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。
Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多个镜像层对外展示为一个统一的文件。Linux上可用的存储引擎有AUFS、Overlay2、Device Maooer等等,每种存储引擎都基于Linux对应的文件系统或者块设备技术,并且每种存储引擎都有独特的性能特点。
Docker通过共享镜像层来节省空间并且提高性能。我们使用docker image pull命令的时候,Docker会识别出要拉取的镜像中,哪几层已经在本地存在的了。这样只需要拉取不存在的镜像层即可。
6.2.7 删除镜像
当不需要某个镜像的时候,可以通过docker image rm命令从Docker主机删除该镜像,其中,rm是remove的缩写。
删除操作会在当前主机上删除该镜像以及相关的镜像层。这意味着无法通过docker image ls 命令看到删除后的镜像,并且对应的包含镜像层数据的目录也会被删除。但是,如果某个镜像层被多个镜像共享,那只有当全部依赖该镜像层的镜像都被删除后,该镜像层才会被删除。
下面示例使用镜像ID来删除镜像
[pangcm@qcloud01 ~]$ docker image rm 9b915a241e29
Untagged: nigelpoulton/tu-demo:latest
Untagged: nigelpoulton/tu-demo@sha256:42e34e546cee61adb100144aed000d90e6dc403a0c5b53f324a9e1c1aae451e9
Untagged: nigelpoulton/tu-demo@sha256:9ccc0c67e5c5eaae4bebeeed9b22e0e22f8a35624c1d5c80f2c9623cbcc9b59a
Deleted: sha256:9b915a241e29dc2767980445e3109412b1905b6f1617aea7098e7ac1e5837ae2
Deleted: sha256:27eb08aec7b41dbfa2fd49bc2b3fad9b020fe40b0bc8289af7f53770f0843e7d
如果被删除的镜像上存在运行状态的容器,那么该删除操作不会被允许。再次执行删除镜像命令之前,需要停止并删除该镜像相关的全部容器。
要快速删除Dokcer 主机上的全部镜像,可以使用docker image ls -q 来传入镜像ID。如下:
docker image rm $(docker image ls -q) -f
6.3 镜像——命令
- docker image pull 是下载镜像的命令。
- docker image ls 列出了本地Docker主机上存储的镜像。
- docker image inspect 命令可以展示镜像的细节,包括镜像层和元数据。
- docker image rm 用于删除镜像。
6.4 本章小结
在本章中,读者学习了Docker镜像的相关内容,包括镜像和虚拟机模板很类似,可用于启动容器;镜像由一个或者多个只读镜像层构成,当多个镜像层堆叠在一起,就构成了一个完整镜像。
本书使用Docker image pull命令拉取到Docker主机本地仓库。此外,本章还涵盖了镜像命名、官方和非官方仓库、镜像分层、镜像层共享以及加密ID等等。本章还极少了Docker是如何支持多架构和多平台镜像的,并且在本章最后重新梳理了常见的镜像操作命令。
网友评论