参考文章:[Docker技术入门与实战第3版]
镜像是 Docker 三大核心概念中最重要的,Docker 运行容器前需要本地存在对应的镜像,如果镜像不存在,Docker 会尝试先从默认镜像仓库下载,用户也可以通过配置使用自定义的镜像仓库。
获取镜像
本节主要介绍 Docker 镜像的 pull
子命令。可以使用 docker [image] pull
命令直接从 Docker Hub 镜像源来下载镜像。该命令的格式为:
1 | docker [image] pull NAME[:TAG] |
NAME
:镜像仓库名称TAG
:镜像的标签
对于 Docker 镜像来说,如果不显式指定 TAG
,则默认会选择 latest
标签,这会下载仓库中最新版本的镜像。
- 示例1:从官方仓库下载镜像
1 | $ docker image pull ubuntu |
严格地讲,镜像仓库名称中还应该添加仓库地址(即
Registry
,注册服务器)作为前缀,只是默认使用的是官方 Docker Hub服务,该前缀可以忽略。例如,docker pull ubuntu:18.04
命令等同于docker pull registry.hub.docker.com/ubuntu:18.04
命令,即从默认的注册服务器 Docker Hub Registry 中的 ubuntu 仓库来下载标记为 18.04 的镜像。
- 示例二:从非官方仓库下载镜像
如果从非官方的仓库下载,则需要在仓库名称前指定完整的仓库地址。
例如,从网易蜂巢的镜像源来下载ubuntu:18.04
镜像,可以使用如下命令:
1 | docker pull hub.c.163.com/public/ubuntu:18.04 |
pull 子命令支持的选项主要包括
-a, --all-tags=true|false
: 是否获取仓库中的所有镜像,默认为否;--disable-content-trust
: 取消镜像的内容校验,默认为真。
另外,有时候需要使用镜像代理服务来加速 Docker 镜像获取过程,可以在 Docker 服务启动配置中增加 --registry-mirror=proxy_URL
来指定镜像代理服务地址。
查看镜像信息
本节主要介绍 Docker 镜像的 ls
, tag
和 inspect
子命令.
使用 images 命令列出镜像
使用 docker images
或 docker image ls
命令可以列出本地主机上已有镜像的基本信息。
例如,下面的命令列出了上一小节中下载的镜像信息
1 | $ docker images |
在列出的信息中,可以看到几个字段信息:
REPOSITORY
:来自哪个仓库;TAG
:镜像的标签信息;IMAGE ID
:镜像的 ID(唯一标识镜像),如果两个镜像的 ID 相同,说明它们实际上指向了同一个镜像;CREATED
:创建时间,说明镜像最后的更新时间;SIZE
:镜像大小,优秀的镜像往往体积都较小
镜像的大小信息只是表示了该镜像的逻辑体积大小,实际上由于相同的镜像层本地只会存储一份,物理上占用的存储空间会小于各镜像逻辑体积之和。
images 子命令主要支持的选项
-a, --all=true|false
: 列出所有镜像文件(包括临时文件),默认为否;--digests=true|false
:列出镜像的数字摘要值,默认为否;-f, --filter=[]
:过滤列出的镜像,如dangling=true
,只显示没有被使用的镜像;也可以指定带有特殊标注的镜像等;--format="TEMPLATE"
:控制输出格式,如.ID
代表 ID 信息,.Repository
代表仓库信息等;--no-trunc=true|false
:对输出结果中太长的部分是否进行截断,如镜像的 ID 信息,默认为是;-q, --quiet=true|false
:仅输出 ID 信息,默认为否;
更多子命令选项还可以通过 man docker-images
来查看
使用 tag 命令添加镜像标签
为了方便在后续工作中使用特定镜像,还可以使用 docker tag
命令为本地镜像任意添加新的标签。
例如,添加一个新的 myubuntu:latest
镜像标签:
1 | docker tag ubuntu:latest myubuntu:latest |
再次使用 docker images
列出本地主机上镜像信息,可以看到多出一个 myubuntu:latest
标签的镜像
1 | $ docker images |
使用 inspect 命令查看详细信息
使用 docker [image] inspect
命令可以获取该镜像的详细信息, 包括制作者,适应架构,各层的数字摘要等;
如下所示:
1 | $ docker inspect ubuntu:18.04 |
上面代码返回的是一个 JSON 格式的消息,如果我们只要其中某一项内容时,可以使用 -f
来指定,例如,获取镜像的 Architecture
:
1 | $ docker inspect ubuntu:18.04 -f {{".Architecture"}} |
使用 history 命令查看镜像历史
既然镜像文件由多个层组成,那么怎么知道各个层的内容具体是什么呢?这时候可以使用 history
子命令,该命令将列出各层的创建信息。
例如,查看 ubuntu:18.04 镜像的创建过程,可以使用如下命令:
1 | $ docker history ubuntu:18.04 |
注意,过长的命令被自动截断了,可以使用前面提到的 --no-trunc
选项来输出完整命令。
搜寻镜像
本节主要介绍 Docker 镜像的 search
子命令。使用 docker search
命令可以搜索 Docker Hub 官方仓库中的镜像。语法为:
1 | docker search [option] keyword |
支持的选项主要包括:
-f, --filter filter
:过滤输出内容;--format string
:格式化输出内容--limit int
:限制输出结果个数,默认为 25 个;--no-trunc
:不截断输出结果
例如搜索官方提供的带 nginx 关键字的镜像,如下所示:
1 | $ docker search --filter is-official=true nginx |
再比如,搜索所有收藏数超过 4 的关键词包括 TensorFlow 的镜像
1 | $ docker search --filter stars=4 tensorflow |
删除和清理镜像
本节主要介绍 Docker 镜像的 rm
和 prune
子命令
使用标签删除镜像
使用 docker rmi
或者 docker image rm
命令可以删除镜像,命令格式为
1 | docker rmi IMAGE [IMAGE...] |
支持的选项包括:
-f, --force
:强制删除镜像,即使有容器依赖它;--no-prune
:不要清理未带标签的父镜像;
例如,要删除掉 myubuntu:latest
镜像,可以使用如下命令
1 | $ docker rmi myubuntu:latest |
使用镜像 ID 来删除镜像
当使用 docker rmi
命令,并且后面跟上镜像的 ID 时,会先尝试删除所有指向该镜像的标签,然后删除该镜像文件本身。
注意,当有该镜像创建的容器存在时,镜像文件默认是无法被删除的,例如:先利用 ubuntu:18.04
镜像创建一个简单的容器来输出一段话:
1 | $ docker run ubuntu:18.04 echo 'hello! I am here!' |
使用 docker ps -a
命令可以看到本机上存在的所有容器
1 | $ docker ps -a |
可以看到,后台存在一个退出状态的容器,是刚基于 ubuntu:18.04
镜像创建的。试图删除该镜像,Docker 会提示有容器正在运行,无法删除:
1 | $ docker rmi ubuntu:18.04 |
如果想要强行删除镜像,可以使用 -f
参数:
1 | docker rmi -f ubuntu:18.04 |
注意,通常不推荐使用 -f
参数来强制删除一个存在容器依赖的镜像。正确的做法是,先删除依赖该镜像的所有容器,再来删除镜像。
首先,删除容器 eb422933e8cf
1 | docker rm eb422933e8cf |
然后使用 ID 来删除镜像,此时会正常打印出删除的各层信息:
1 | $ docker rmi 2eb2d388e1a2 |
清理镜像
使用 Docker 一段时间后,系统中可能会遗留一些临时的镜像文件,以及一些没有被使用的镜像,可以通过 docker image prune
命令来进行清理。
该命令支持的选项包括:
-a, --all
:删除所有无用的镜像,不光是临时镜像--filter filter
:只清理符合给定过滤器的镜像;-f, --force
:强制删除镜像,而不进行提示确认
例如, 如下命令会自动清理临时的遗留镜像层,最后会提示释放的存储空间:
1 | $ docker image prune -f |
创建镜像
创建镜像的方法主要有三种:基于已有镜像的容器创建,基于本地模板导入,基于 Dockerfile
创建。
本节主要介绍 Docker 的 commit
,import
和 build
子命令。
基于已有容器创建
该方法主要是使用 docker [container] commit
命令.
命令格式为:
1 | docker [container] commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]] |
主要选项包括:
-a, --author=""
:作者信息-c, --change=[]
:提交的时候执行Dockerfile
指令,包括 CMD|ENTRYPOINT|ENV|EXPOSE|LABEL|ONBUILD|USER|VOLUME|WORKDIR 等;-m, --message=""
:提交信息-p, --pause=true
:提交时暂停容器运行。
下面将演示如何使用该命令创建一个新的镜像
首先,启动一个镜像,并在其中进行修改操作。例如,创建一个 test
文件,之后退出,代码如下:
1 | $ docker run -it ubuntu:18.04 /bin/bash |
记住该容器的ID为 78c50d07309a
。
此时该容器与原 ubuntu:18.04
镜像相比,已经发生了改变,可以使用 docker container commit
命令来提交为一个新的镜像。提交时可以使用 ID 或者名称来指定容器:
1 | $ docker commit -m "Add a new file" -a "Docker Newbee" 78c50d07309a test:v0.1 |
顺利的话,会返回新创建的镜像的 ID信息,例如 17f766c5f30b6b656422332d513187b6088713ba7245f8875aba744f3ae26527。
此时查看本地镜像列表,会发现新创建的镜像已经存在了:
1 | $ docker images |
基于本地模板导入
用户也可以直接从一个操作系统模板文件导入一个镜像,主要使用 docker [container] import
命令.命令格式为:
1 | docker [image] import [OPTIONS] file|URL|-[REPOSITORY[:TAG]] |
要直接导入一个镜像,可以使用 OpenVZ
提供的模板来创建,或者用其他已导出的镜像模板来创建。OPENVZ 模板的下载地址为:OpenVZ Templates Download。
例如,下载了 centos-6
的模板压缩包,之后使用以下命令导入即可:
1 | cat centos-6-x86_64-minimal.tar.gz | docker import - centos-6:v1 |
然后,查看新导入的镜像,已经在本地存在了:
1 |
基于 Dockerfile 创建
基于 Dockerfile
创建时最常见的方式。Dockerfile
是一个文本文件,利用给定的指令描述基于某个父镜像创建新镜像的过程。
下面给出 Dockerfile
的一个简单示例,基于 debian:stretch-slim
镜像安装 Python 3 环境,构成一个新的 Python:3
镜像:
1 | FROM debian:stretch-slim |
创建镜像的过程可以使用 docker [image] build
命令,编译成功后本地将多出一个 python:3
镜像:
1 | $ docker build -t python:3 . |
存出和载入镜像
本节主要介绍 Docker 镜像的 save
和 load
子命令。
用户可以使用 docker [image] save
和 docker [image] load
命令和存出和载入镜像。
存出镜像
如果要导出镜像到本地文件可以使用 docker [image] save
命令。
该命令支持的选项:
-o, --output string
:导出镜像到指定的文件中
例如,导出本地的 ubuntu:18.04
镜像为文件 ubuntu_18.04.tar
,如下所示:
1 | $ docker save -o ubuntu_18.04.tar ubuntu:18.04 |
之后,用户就可以通过复制 ubuntu_18.04.tar
文件将该镜像分享给他人。
载入镜像
可以使用 docker [image] load
将导出的 tar 文件再导入到本地镜像库。
该命令支持的选项:
-i, --input string
: 从指定文件中导入镜像内容
例如,从文件 ubuntu:18.04.tar
文件中导入镜像到本地镜像列表,如下所示:
1 | $ docker load -i ubuntu_18.04.tar |
这将导入镜像及其相关的元数据信息(包括标签等)。导入成功后,可以使用 docker images
命令进行查看,与原镜像一致。
上传镜像
本节主要介绍 Docker 镜像的 push
子命令。可以使用 docker [image] push
命令上传镜像到仓库,默认上传到 Docker Hub 官方仓库(需要登录).
命令格式为:
1 | docker [image] push NAME[:TAG] | [REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG] |
用户在 Docker Hub 网站注册后可以上传自制的镜像。
例如,用户 user
上传本地的 test:latest
镜像,可以先添加新的标签 user/test:latest
,然后用 docker [image] push
命令上传。
1 | docker tag test:latest user/test:latest |