《Docker技术入门与实战 第4版》阅读笔记 2 Docker 镜像
第3章 使用 Docker 镜像
在书中,以 $ 开头的命令表示普通用户,以 # 开头的命令表示 root 用户,需要在命令前使用 sudo 临时提升权限。
3.1 获取镜像
我截图演示的,就是需要掌握的,我没截图演示的,了解即可。
可以使用 dockerimagepull 命令直接从镜像源来下载镜像,该命令的格式为 dockerimagepull NAME:TAG。其中,NAME 是镜像仓库的名称(用来区分镜像),TAG 是镜像的标签(往往用来表示版本信息)。通常情况下,描述一个镜像需要包括名称和标签信息。
例如,要获取一个 Ubuntu 24.04 系统的基础镜像,可以使用如下命令:
bash
docker pull ubuntu:24.04

对于 Docker 镜像来说,如果不显式指定 TAG,则默认会选择 latest 标签,下载仓库中最新版本的镜像。
bash
docker pull ubuntu
# 等于
docker pull ubuntu:latest
镜像的 latest 标签意味着该镜像是最新版本,因此版本并不稳定。为了确保生产环境的稳定性,建议避免忽略镜像的标签信息和使用默认的latest标记的镜像。
在使用 docker pull 命令下载镜像时,会发现镜像文件通常由多个层 (layer) 组成。类似 966c395d29cb 的字符串是层的唯一ID(实际上,完整的 ID 由256位,即 64 个十六进制字符组成)。下载过程中,命令行会显示镜像的各个层信息。若不同的镜像包含相同的层,则本地仅存储一份该层的内容,从而减少了存储空间的占用。

不同的镜像仓库服务器上,镜像重名怎么办?
镜像的仓库名称应当包含仓库地址作为前缀。前缀可以省略使用默认的仓库地址。
bash
docker pull ubuntu:24.04
# 等同于
docker pull 默认仓库地址/ubuntu:24.04
Docker 自 1.3.0 版本起对镜像管理引入了签名系统,可以通过比对签名来验证镜像的完整性,加强了镜像的安全性。
pull 子命令支持的选项主要包括:
bash
-a 或 --all-tags=true|false # 是否获取仓库中的所有标签,默认为否。
--disable-content-trust=true|false # 取消镜像的内容校验,默认为真。
有时需要使用镜像代理服务来加速 Docker 镜像获取过程,可以在 Docker 服务启动配置中增加 --registry-mirror=proxy_URL 来指定镜像代理服务地址。阿里云服务器已经帮我们配置好了镜像代理服务。
下载镜像到本地后,利用该镜像创建一个容器,在其中运行 bash 应用,执行打印 "Hello World" 的命令:
bash
docker run -it ubuntu:24.04
echo "Hello World"
exit

使用代理服务器下载镜像
当需要通过代理服务器下载外网镜像时,可以通过修改 Docker 配置文件,重启 Docker 服务后生效。Ubuntu 系统中的配置文件路径为 /lib/systemd/system/docker.service。代理协议可以使用 Socks5、HTTP、HTTPS 等。NO_PROXY 可以指定不用代理服务器的仓库地址范围。
3.2 查看镜像信息
1.使用 images 命令列出镜像
使用 docker images 或 docker image ls 命令可以列出本地主机上已有镜像的基本信息。
bash
docker images
# 或
docker image ls

| REPOSITORY | TAG | IMAGE ID | CREATED | SIZE |
|---|---|---|---|---|
| 镜像所属的仓库 | 镜像的版本信息 | 镜像的唯一标识 | 镜像最后一次更新的时间 | 镜像的体积大小 |
镜像 ID 唯一标识了一个镜像。在使用镜像 ID 时,通常可以使用该 ID 前几个字符组成的可区分子串来代替完整的ID。
标签信息用于区分来自同一个仓库的不同镜像。例如,在 Ubuntu 仓库中,可以通过不同的标签(如24.04、17.10等)来区分各个发行版本。
镜像大小信息仅表示镜像的逻辑体积大小。实际上,由于相同的镜像层在本地只会存储一份,因此所有的镜像物理上占用的存储空间之和通常小于镜像逻辑体积之和。
docker images 子命令支持许多选项:
bash
-a 或 --all=true|false #列出所有镜像文件,默认为否。
--digests=true|false #列出镜像的数字摘要值,默认为否。
-f 或 --filter=[] #过滤要列出的镜像,例如使用dangling=true只显示未被使用的镜像,也可以指定带有特定标签的镜像等。
--format="TEMPLATE" #自定义输出格式,包括table、json、Go模板格式等。
--no-trunc=true|false #设置是否对过长的输出结果进行截断,例如镜像的ID信息,默认为是。
-q 或 --quiet=true|false #仅输出ID信息,默认为否。
更多子命令选项还可以通过 docker images --help 命令查看。

2.使用 tag 命令添加镜像标签
可以使用 docker tag 命令为本地镜像添加新的标签。例如,添加一个新的 myubuntu:latest 镜像标签:
bash
docker tag ubuntu:24.04 myubuntu:latest
再次使用 docker images 列出本地镜像信息,可以看到多了一个 myubuntu:latest 标签的镜像:
注意,myubuntu:latest 镜像和 ubuntu:latest 镜像的 ID 是完全一致的,它们实际上指向了同一个镜像文件,只是别名不同而已。docker tag 命令添加的标签实际上起到了软链接的作用。
bash
docker images

3.使用 inspect 命令查看详细信息
使用 docker image inspect 命令可以获取该镜像的详细信息,包括制作者、适用架构、各层的数字摘要等:
返回的是一个 JSON 格式的消息,如果只需要其中一项内容时,可以使用 -f 来指定,例如,获取镜像的 Architecture:
bash
docker inspect ubuntu:24.04
docker inspect -f {{".Architecture"}} ubuntu:24.04


4.使用 history 命令查看镜像历史
既然镜像文件由多个层组成,那么怎么知道各个层的内容具体是什么?这时可以使用 history 子命令,该命令将列出各层的创建信息。
注意,过长的命令被自动截断了,可以使用 --no-trunc 选项来输出完整命令。
bash
docker history ubuntu:24.04
docker history ubuntu:24.04 --no-trunc

3.3 搜寻镜像
使用 docker search 命令可以搜索 Docker Hub 官方仓库中的镜像,命令格式为 docker search option keyword。支持的选项主要包括:
bash
-f 或 --filter filter #过滤输出内容。
--format string #格式化输出内容。
--limit int #限制输出结果个数,默认为25个。
--no-trunc #不截断输出结果。
例如,搜索带 nginx 关键字的镜像,命令如下:
bash
docker search --filter=is-official=true nginx
再比如,搜索所有收藏数超过 4 的关键词包括 tensorflow 的镜像,命令如下:
bash
docker search --filter=stars=4 tensorflow
默认的输出结果将按照星级评价进行排序。

3.4 删除和清理镜像
1.使用标签删除镜像
使用 docker rmi 或 docker image rm 命令可以删除镜像,命令格式为 docker rmi OPTIONS IMAGE IMAGE...,其中 IMAGE 可以为标签或ID。
支持的选项包括:
bash
-f 或 --force #强制删除镜像,即使有容器依赖它。
--no-prune #不要清理未带标签的父镜像。
例如,创建一个新的 myubuntu:latest 镜像标签,然后删除它,可以使用如下命令:
bash
docker images # 查看镜像,已经加过标签 myubuntu:latest 了。
# docker tag ubuntu:24.04 myubuntu:latest
docker rmi myubuntu:latest
本地的 ubuntu:24.04 镜像不会受到此命令的影响。当同一个镜像拥有多个标签时,docker rmi 命令只是删除了该镜像多个标签中的指定标签而已,并不影响镜像文件。因此上述操作只是删除了镜像的一个标签副本。
但当镜像只剩下一个标签时就要小心了,此时再使用 docker rmi 命令会删除镜像标签和数据文件。
再次查看本地的镜像,发现 ubuntu:24.04 镜像仍然存在:

2.使用镜像 ID 来删除镜像
当使用 docker rmi 命令,并且后面跟上镜像的 ID(或能进行区分的部分前缀)时,会先尝试删除所有指向该镜像的标签,然后删除该镜像文件本身。
注意,当存在通过该镜像创建的容器时,镜像文件默认是无法被删除的。
使用 docker ps -a 命令可以看到本机上存在的所有容器:
可以看到,后台存在一个退出状态的容器,是基于 ubuntu:24.04 镜像创建的。
如果试图删除该镜像,Docker 会提示有容器正在运行,无法删除,
如果要想强行删除镜像,可以使用 -f 参数,注意,不推荐使用 -f 参数来强制删除一个存在容器依赖的镜像。正确的做法是,先删除依赖该镜像的所有容器,再来删除镜像。
bash
docker rmi ubuntu:24.04

首先删除容器,然后使用镜像 ID 删除镜像,此时会正常打印出删除的各层信息:
bash
docker rm 容器id
docker rmi 镜像id

3.清理镜像
使用 Docker 一段时间后,系统中可能会遗留一些临时的镜像文件,以及一些没有被使用的镜像,此时可以通过 docker image prune 命令进行清理。
支持的选项包括:
bash
-a 或 --all #删除所有无用镜像,不仅是临时镜像。
--filter filter #只清理符合给定过滤器的镜像。
-f 或 --force #强制删除镜像,而不进行提示确认。
例如,如下命令会自动清理临时的遗留镜像文件层,最后会提示释放的存储空间:
bash
docker image prune -f

3.5 创建镜像
创建镜像的方法主要有三种:
- 基于已有镜像的容器创建
- 基于归档文件导入
- 基于Dockerfile创建
1.基于已有镜像的容器创建
该方法主要是使用 docker commit 命令,命令格式为:
bash
docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
主要选项包括:
bash
-a 或 --author="" #作者信息。
-c 或 --change=[] #提交的时候执行 Dockerfile 指令,包括CMD|ENTRYPOINT|E NV|EXPOSE|LABEL|ONBUILD|USER|VOLUME|WORKDIR等。
-m 或 --message="" #提交消息。
-p 或 --pause=true #提交时暂停容器运行。
首先,启动一个镜像,并在其中进行修改操作。例如,创建一个 test 文件,之后退出,代码如下:
bash
docker run -it ubuntu:24.04 /bin/bash
touch test
exit

此时该容器与原 ubuntu:24.04 镜像相比,已经发生了改变,可以使用 docker commit 命令来提交为一个新的镜像。提交时可以使用 ID 或名称来指定容器,此时查看本地镜像列表,会发现新创建的镜像已经存在了:
bash
docker commit -m "Add a new file" -a "yangjunbo" 容器id test:0.1
docker images

2.基于归档文件导入
用户也可以直接从一个归档文件文件导入一个镜像,主要使用 docker image import 命令,命令格式为:
bash
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
# file|URL|- 支持直接指定文件路径或 URL 或 -(表示从标准输入读取)。
# 从标准输入读取,通过管道导入:cat archive.tar | docker import -
该命令主要是从容器的归档文件中进行导入,形成一个新的镜像。例如,将任何容器导出为本地归档文件,然后使用 import 命令导入即可:
bash
docker ps -a # 查看所有容器的信息
# docker export [OPTIONS] CONTAINER
# docker export -o output.tar CONTAINER
# docker export CONTAINER > output.tar
docker export -o test.tar 容器id # 将容器导出为本地归档文件
docker image import test.tar test/ubuntu:v1
docker export 和 docker container export 是完全相同的命令,没有任何功能区别。

3.基于 Dockerfile 创建
基于 Dockerfile 创建镜像是最常见的方式。Dockerfile 是一个文本文件,其中包括了指令,描述基于某个父镜像创建新镜像的过程。Dockerfile 文件的细节将在后面进行介绍。
bash
touch Dockerfile # 创建 Dockerfile 文件
vi Dockerfile # 编辑 Dockerfile 文件,在其中写创建镜像的步骤。
bash
docker build -t test/python:3 . # 安装 Dockerfile 文件开始构建镜像
3.6 导出和载入镜像
通过运行 docker image save 和 docker image load 命令来分别保存和加载镜像。通过这种方式,可以传输和共享 Docker 镜像,为应用部署提供便利。
1.导出镜像
若要将镜像导出到本地文件,可使用 docker image save 命令。此命令支持 -o 或 --output string 参数,可将镜像导出到指定文件。例如,要将本地的 ubuntu:24.04 镜像导出为 ubun_24.04.tar 文件,请执行以下操作,完成此操作后,用户便可通过复制 ubuntu_24.04.tar 文件将该镜像与他人共享。
bash
docker images # 查看镜像
# docker save [OPTIONS] IMAGE [IMAGE...]
docker save -o ubuntu_v1.tar test/ubuntu:v1
2.载入镜像
可以使用 docker load 命令将导出的 tar 文件再导入为本地镜像。该命令支持 -i,--input string 选项,允许从指定文件中读入镜像内容。
例如,若要从名为 ubuntu_24.04.tar 的文件导入镜像到本地镜像列表,请按照以下方式操作:
执行这些命令将导入镜像及其相关的元数据信息,包括标签等。导入成功后,可以使用 docker images 命令查看本地镜像列表,会发现刚刚导入的镜像与原镜像完全相同。
bash
docker load -i ubuntu_v1.tar
# 或
docker load < ubuntu_v1.tar

3.7 上传镜像
国内默认无法连接 DockerHub 官方仓库,不演示截图了,了解即可。
要将镜像上传至仓库,用户可以使用 docker image push 命令。默认情况下,镜像将被上传至 Docker Hub 官方仓库。如果用户没有 Docker Hub 账号,需要先注册账号。
命令的格式为:
bash
docker image push [OPTIONS] NAME[:TAG]|[REGISTRY_HOST[:REGISTRY_PORT]/]NAME[:TAG]
在 Docker Hub 网站上注册并登录后,便可以上传自己创建的镜像。
以用户 user 为例,假设想要上传本地的 test:latest 镜像。首先,需要为其添加一个以用户名为前缀的标签,如 user/test:latest,然后使用 docker image push 命令上传镜像,首次上传时,会提示输入自己在 Docker Hub 的登录信息或进行注册,之后登录信息会记录到本地的~/.docker目录下,后续上传时无须再次登录。
bash
docker tag test:latest user/test:latest
docker push user/test:latest
docker push 是 docker image push 的简写别名,两者完全等价。
3.8 本章小结
用户可以通过输入 docker image help 命令查阅 Docker 支持的各种镜像操作子命令。