镜像是一个只读的 Docker 容器模板,包含启动容器所需要的所有文件系统结构和内容。简单来讲,镜像是一个特殊的文件系统,它提供了容器运行时所需的程序、软件库、资源、配置等静态数据。即镜像不包含任何动态数据,镜像内容在构建后不会被改变。
容器目的就是运行应用或者服务,这意味着容器的镜像中必须包含应用/服务运行所必需的操作系统和应用文件。但是,容器又追求快速和小巧,这意味着构建镜像的时候通常需要裁剪掉不必要的部分,保持较小的体积。例如,Docker镜像通常不会包含6个不同的Shell让读者选择——通常Docker镜像中只有一个精简的Shell,甚至没有Shell。镜像中还不包含内核——容器都是共享所在Docker主机的内核,所以有时会说容器仅包含必要的操作系统(通常只有操作系统文件和文件系统对象)。
镜像操作
拉取镜像
Docker 镜像的拉取使用 docker pull 命令, 命令格式一般为 docker pull [Registry]/[Repository]/[Image]:[Tag]。Linux Docker 主机本地镜像仓库通常位于/var/lib/docker/
- Registry 为注册服务器,Docker 默认会从 docker.io 拉取镜像,如果你有自己的镜像仓库,可以把 Registry 替换为自己的注册服务器。
- Repository 为镜像仓库,通常把一组相关联的镜像归为一个镜像仓库,library 为 Docker 默认的镜像仓库。
- Image 为镜像名称。
- Tag 为镜像的标签,如果你不指定拉取镜像的标签,默认为 latest。
注:标有latest标签的镜像不保证这是仓库中最新的镜像。
例如,我们需要获取一个 busybox 镜像,可以执行以下命令:
busybox 是一个集成了数百个 Linux 命令(例如 curl、grep、mount、telnet 等)的精简工具箱。
$ docker pull busybox
Using default tag: latest
latest: Pulling from library/busybox
61c5ed1cbdf8: Pull complete
Digest: sha256:4f47c01fa91355af2865ac10fef5bf6ec9c7f42ad2321377c21e844427972977
Status: Downloaded newer image for busybox:latest
docker.io/library/busybox:latest
实际上执行 docker pull busybox 命令,都是先从本地搜索,如果本地搜索不到 busybox 镜像则从 Docker Hub 下载镜像。
查看镜像
Docker 镜像查看使用 docker images 或者 docker image ls 命令。如果我们想要查询指定的镜像,也可以使用 docker image ls 命令来查询。
$ docker image ls busybox
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 018c9d7b792b 3 weeks ago 1.22MB
Docker 提供 --filter 参数来过滤 docker image ls 命令返回的镜像列表内容。Docker目前支持如下的过滤器:
- dangling:可以指定true或者false,仅返回悬虚镜像(true),或者非悬虚镜像(false)。
- before:需要镜像名称或者ID作为参数,返回在之前被创建的全部镜像。
- since:与before类似,不过返回的是指定镜像之后创建的全部镜像。
- label:根据标注(label)的名称或者值,对镜像进行过滤。docker image ls命令输出中不显示标注内容。
其他的过滤方式可以使用reference。
也可以使用 --format 参数来通过 Go 模板对输出内容进行格式化。如果需要更复杂的过滤,可以使用 OS 或者 Shell 自带的工具,比如 grep 或者 awk 。
重命名镜像
如果你想要自定义镜像名称或者推送镜像到其他镜像仓库,你可以使用 docker tag 命令将镜像重命名。docker tag 的命令格式为 docker tag SOURCE_IMAGE TARGET_IMAGE。
一个镜像可以根据用户需要设置多个标签,标签是存放在镜像元数据中的任意数字或字符串。
下面通过实例演示一下:
$ docker tag busybox:latest mybusybox:latest
执行完 docker tag 命令后,可以使用查询镜像命令查看一下镜像列表:
docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
busybox latest 018c9d7b792b 3 weeks ago 1.22MB
mybusybox latest 018c9d7b792b 3 weeks ago 1.22MB
可以看到,镜像列表中多了一个 mybusybox 的镜像,busybox 和 mybusybox这两个镜像的 IMAGE ID 是完全一样的。实际上它们指向了同一个镜像文件,只是别名不同而已。
搜索镜像
docker search 命令允许通过 CLI 的方式搜索 Docker Hub。读者可以通过 “NAME” 字段的内容进行匹配,并且基于返回内容中任意列的值进行过滤。
$ docker search aipine
NAME DESCRIPTION STARS OFFICIAL AUTOMATED
wangyulong/aipine_go_jmeter_mysql_redis 0
anjia0532/alpine-package-mirror aipine mirror server 0 [OK]
potachaidocker/aipineweb aipineweb 0
可以使用 --filter "is-official=true",使命令返回内容只显示官方镜像。默认情况下,Docker 只返回 25 行结果。读者可以指定 --limit 参数来增加返回内容行数,最多为 100 行。
删除镜像
可以使用 docker rmi 或者 docker image rm 命令删除镜像。
$ docker rmi mybusybox
Untagged: mybusybox:latest
删除操作会在当前主机上删除该镜像以及相关的镜像层。这意味着无法通过 docker image ls 命令看到删除后的镜像,并且对应的包含镜像层数据的目录会被删除。但是,如果某个镜像层被多个镜像共享,那只有当全部依赖该镜像层的镜像都被删除后,该镜像层才会被删除。
如果被删除的镜像上存在运行状态的容器,那么删除操作不会被允许。再次执行删除镜像命令之前,需要停止并删除该镜像相关的全部容器。
镜像实现原理
Docker镜像由一些松耦合的只读镜像层组成,Docker负责堆叠这些镜像层,并且将它们表示为单个统一的对象。镜像底层的实现依赖于联合文件系统(UnionFS)。
一种查看镜像分层的方式是通过 docker image inspect 命令:
$ docker image inspect ubuntu:latest
[
{
"Id": "sha256:bd3d4369ae.......fa2645f5699037d7d8c6b415a10",
"RepoTags": [
"ubuntu:latest"
...
"RootFS": {
"Type": "layers",
"Layers": [
"sha256:c8a75145fc...894129005e461a43875a094b93412",
"sha256:c6f2b330b6...7214ed6aac305dd03f70b95cdc610",
"sha256:055757a193...3a9565d78962c7f368d5ac5984998",
"sha256:4837348061...12695f548406ea77feb5074e195e3",
"sha256:0cad5e07ba...4bae4cfc66b376265e16c32a0aae9"
]
}
}
]
所有的 Docker 镜像都起始于一个基础镜像层,当进行修改或增加新的内容时,就会在当前镜像层之上,创建新的镜像层。每一层根据镜像的内容都有一个唯一的 ID 值,当不同的镜像之间有相同的镜像层时,便可以实现不同的镜像之间共享镜像层的效果。在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合。
从 Docker 1.10 版本开始,镜像就是一系列松耦合的独立层的集合。镜像本身就是一个配置对象,其中包含了镜像层的列表以及一些元数据信息。镜像层才是实际数据存储的地方(比如文件等,镜像层之间是完全独立的,并没有从属于某个镜像集合的概念)。