Docker系列-镜像的相关操作

获取镜像

Docker Hub 上有大量的高质量的镜像可以用,这里我们就说一下怎么获取这些镜像。

从 Docker 镜像仓库获取镜像的命令是 docker pull。其命令格式为:

1
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

具体的选项可以通过 docker pull --help 命令看到,这里我们说一下镜像名称的格式。

  • Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub。
  • 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
    比如:
1
2
3
4
5
6
7
8
9
$ docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
bf5d46315322: Pull complete
9f13e0ac480c: Pull complete
e8988b5b3097: Pull complete
40af181810e7: Pull complete
e6f7c7e5c03e: Pull complete
Digest: sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae97c3d643fbbe
Status: Downloaded newer image for ubuntu:16.04

列出镜像

要想列出已经下载下来的镜像,可以使用 docker image ls或者 docker images命令。

1
2
3
4
5
6
7
8
9
10
11
12
$ docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-hello latest 2921286533e1 17 minutes ago 924MB
python 3.6 2dfb6d103623 5 days ago 914MB
redis latest 987b78fc9e38 6 days ago 104MB
caijiacheng0707/hello-c latest eca19e80e3c4 13 days ago 861kB
wordpress latest fd5f88e17621 2 weeks ago 541MB
mysql 5.7 f965319e89de 3 weeks ago 448MB
mysql latest a7a67c95e831 3 weeks ago 541MB
nginx latest 602e111c06b6 4 weeks ago 127MB
python 2.7-alpine 8579e446340f 4 weeks ago 71.1MB
arm32v7/python 2.7-slim b532061a7f5b 4 weeks ago 107MB

列表包含了 仓库名、标签、镜像 ID、创建时间 以及 所占用的空间。

其中仓库名、标签在之前的基础概念章节已经介绍过了。镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个标签。

镜像体积

如果仔细观察,会注意到,这里标识的所占用空间和在 Docker Hub 上看到的镜像大小不同。比如,ubuntu:16.04 镜像大小,在这里是 127 MB,但是在 Docker Hub 显示的却是 50 MB。这是因为 Docker Hub 中显示的体积是压缩后的体积。在镜像下载和上传过程中镜像是保持着压缩状态的,因此 Docker Hub 所显示的大小是网络传输中更关心的流量大小。而 docker image ls 显示的是镜像下载到本地后,展开的大小,准确说,是展开后的各层所占空间的总和,因为镜像到本地后,查看空间的时候,更关心的是本地磁盘空间占用的大小。

另外一个需要注意的问题是,docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用 Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多。

你可以通过以下命令来便捷的查看镜像、容器、数据卷所占用的空间。

1
2
3
4
5
6
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 10 3 2.59GB 2.418GB (93%)
Containers 4 2 127.4kB 0B (0%)
Local Volumes 5 1 478.1MB 478.1MB (100%)
Build Cache 0 0 0B 0B

过滤器参数

docker images 还支持强大的过滤器参数 –filter,或者简写 -f。之前我们已经看到了使用过滤器来列出虚悬镜像的用法,它还有更多的用法。比如,我们希望看到在 mysql:5.7 之后建立的镜像,可以用下面的命令:

1
2
3
4
5
6
7
$ docker image ls -f since=mysql:5.7
REPOSITORY TAG IMAGE ID CREATED SIZE
flask-hello latest 2921286533e1 15 minutes ago 924MB
python 3.6 2dfb6d103623 5 days ago 914MB
redis latest 987b78fc9e38 6 days ago 104MB
caijiacheng0707/hello-c latest eca19e80e3c4 13 days ago 861kB
wordpress latest fd5f88e17621 2 weeks ago 541MB

想查看某个位置之前的镜像也可以,只需要把 since 换成 before 即可。

1
2
3
4
5
6
$ docker image ls -f before=mysql:5.7
REPOSITORY TAG IMAGE ID CREATED SIZE
mysql latest a7a67c95e831 3 weeks ago 541MB
nginx latest 602e111c06b6 4 weeks ago 127MB
python 2.7-alpine 8579e446340f 4 weeks ago 71.1MB
arm32v7/python 2.7-slim b532061a7f5b 4 weeks ago 107MB

此外,如果镜像构建时,定义了 LABEL,还可以通过 LABEL 来过滤。
默认情况下,docker image ls 会输出一个完整的表格,但是我们并非所有时候都会需要这些内容。比如,刚才删除虚悬镜像的时候,我们需要利用 docker image ls 把所有的虚悬镜像的 ID 列出来,然后才可以交给 docker image rm 命令作为参数来删除指定的这些镜像,这个时候就用到了 -q 参数

1
2
3
4
5
6
7
8
$ docker image ls -q
5f515359c7f8
05a60462f8ba
fe9198c04d62
00285df0df87
f753707788c5
f753707788c5
1e0c3dd64ccd

–filter 配合 -q 产生出指定范围的 ID 列表,然后送给另一个 docker 命令作为参数,从而针对这组实体成批的进行某种操作的做法在 Docker 命令行使用过程中非常常见,不仅仅是镜像,将来我们会在各个命令中看到这类搭配以完成很强大的功能。因此每次在文档看到过滤器后,可以多注意一下它们的用法。

另外一些时候,我们可能只是对表格的结构不满意,希望自己组织列;或者不希望有标题,这样方便其它程序解析结果等,这就用到了 Go 的模板语法。

比如,下面的命令会直接列出镜像结果,并且只包含镜像ID和仓库名:

1
2
3
4
5
6
7
8
$ docker image ls --format "{{.ID}}: {{.Repository}}"
5f515359c7f8: redis
05a60462f8ba: nginx
fe9198c04d62: mongo
00285df0df87: <none>
f753707788c5: ubuntu
f753707788c5: ubuntu
1e0c3dd64ccd: ubuntu

或者打算以表格等距显示,并且有标题行,和默认一样,不过自己定义列:

1
2
3
4
5
6
7
8
9
10
11


$ docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
5f515359c7f8 redis latest
05a60462f8ba nginx latest
fe9198c04d62 mongo 3.2
00285df0df87 <none> <none>
f753707788c5 ubuntu 16.04
f753707788c5 ubuntu latest
1e0c3dd64ccd ubuntu 14.04

Docker 删除本地镜像

如果要删除本地的镜像,可以使用 docker image rm 命令,其格式为:

1
docker image rm [选项] <镜像1> [<镜像2> ...]

像其它可以承接多个实体的命令一样,可以使用 docker image ls -q 来配合使用 docker image rm,这样可以成批的删除希望删除的镜像。我们在“镜像列表”章节介绍过很多过滤镜像列表的方式都可以拿过来使用。

比如,我们需要删除所有仓库名为 redis 的镜像:

1
docker image rm $(docker image ls -q redis)

或者删除所有在 mysql:5.7 之前的镜像:

1
docker image rm $(docker image ls -q -f before=mysql:5.7)

虚悬镜像

有时候在镜像列表中,还可以看到一个特殊的镜像,这个镜像既没有仓库名,也没有标签,均为 。:

1
<none>               <none>              00285df0df87        5 days ago          342 MB

一般有两种会产生虚悬镜像:
dockers pull: 原来有一个镜像 mongo:3.2,随着官方镜像维护,发布了新版本后,重新 docker pull mongo:3.2 时,mongo:3.2 这个镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消,从而成为了
docker build:也同样可以导致这种现象。由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 的镜像。这类无标签镜像也被称为 虚悬镜像(dangling image)

显示虚悬镜像

1
2
3
$ docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 00285df0df87 5 days ago 342 MB

删除虚悬镜像

一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用下面的命令删除。

1
docker rmi $(docker images -q -f dangling=true)

更多精彩内容:mrxccc