03. 使用Docker镜像
2025-02-17
简介
Docker 镜像是容器运行的基础。当需要运行容器时,Docker 会检查本地是否存在所需的镜像,如果不存在则会从镜像仓库下载。本文将介绍:
- 如何获取和使用镜像
- 管理本地镜像
- 理解镜像的基本原理
1. 获取和使用镜像
Docker Hub上存在大量的镜像,如何获取?
获取Docker镜像仓库中的镜像命令: docker pull。格式:
# 拉取镜像的命令格式
docker pull [选项] [registry地址[:端口号]/]仓库名[:标签]
# 示例:拉取 Ubuntu 18.04 镜像
docker pull ubuntu:18.04命令说明:
- registry地址:镜像仓库地址,默认为 Docker Hub
- 仓库名:
<用户名>/<镜像名>,官方镜像省略用户名 - 标签:指定版本,默认为 latest
1.2 运行镜像
获取镜像后,可以基于该镜像启动容器:
# 启动交互式容器
docker run -it --rm ubuntu:18.04 bash
# 查看系统信息
cat /etc/os-release参数说明:
-i:保持标准输入打开-t:分配伪终端--rm:容器退出后自动删除
1.3 运行镜像
当存在镜像后,就能够以这个镜像为基础启动并运行一个容器。 当打算启动镜像里面的bash并且进行交互式操作的话,可以执行下面的命令
docker run -it --rm ubuntu:18.04 bash
cat /etc/os-release# docker run 运行容器的命令
# -it 两个参数 -i:交互操作 -t 终端。因为进入bash执行一些命令并查看返回结果,需要交互式终端。
# --rm 表示的是:容器退出后随之将其删除。默认情况下,为了保障需求,退出的容器并不会立即删除,除非手动 docker rm。
# cat /etc/os-release 是我进入容器后,查看当前版本信息
# exit 表示的是退出容器2. 管理本地镜像
2.1 查看镜像列表
使用 docker images ls 命令查看本地镜像:
docker images ls显示信息包括:
- 仓库名
- 标签
- 镜像ID(唯一标识)
- 创建时间
- 占用空间
2.2 镜像体积
如果仔细观察,会注意到,这里标识的所占用空间和在 Docker Hub 上看到的镜像大小不同。 Docker Hub中显示的体积是压缩后的体积。在镜像下载和上传过程中镜像是保持压缩状态的,因此Docker Hub所显示的大小是网络传输中更关心的流量大小。
而docker image ls显示的是镜像下载到本地后,展开的大小,准确说,是展开后的各层所占用空间的总和,因为镜像到本地后,查看空间的时候,更关心的是本地磁盘空间占用的大小。
另外一个需要注意的问题是,docker image ls 列表中的镜像体积总和并非是所有镜像实际硬盘消耗。由于 Docker 镜像是多层存储结构,并且可以继承、复用,因此不同镜像可能会因为使用相同的基础镜像,从而拥有共同的层。由于 Docker 使用Union FS,相同的层只需要保存一份即可,因此实际镜像硬盘占用空间很可能要比这个列表镜像大小的总和要小的多
可以通过下面的命令查看镜像 容器 数据卷所占用的空间
docker system df虚悬镜像
但给一个镜像没有仓库名,也没有标签,均为<none>.导致这种的情况的原因:
由于进行维护,发布新的版本,当docker pull是就会出现这种情况。docker build也同样可以导致这种现象。
由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为<none>的镜像。这类无标签镜像也成为虚悬镜像.
可用下面的命令显示这类镜像
docker image ls -f dangling=true
# 一般,虚悬镜像都是去了存在的价值,可以所以删除
docker image prune #删除虚悬镜像中间层镜像
为了加速镜像构建、重复利用资源,Docker会利用中间层镜像。so:在使用一段时间后,可能会看到一些依赖的中间层镜像。默认的docker image ls列表只会显示顶层镜像。需要查看中间层镜像 用
docker image ls -a这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。实际上,这些镜像也没必要删除,因为之前说过,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份,无论如何你也会需要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除
列出部分镜像
不加任何参数的情况下,docker image ls会列出所有顶级镜像,但只希望列出部分镜像。 docker image ls 有好几个参数可以选择
1.根据仓库名列出镜像
docker image ls ubuntu2.列出特定的某个镜像,
docker iamge ls ubuntu:18.04除此,docker image ls 还支持强大的过滤参数 --filter 或者简写 -f
# 比如希望看到在mongo:3.2之后建立的镜像
docker image ls -f since=mongo:3.2
# 看某个位置之前的镜像 把since换成before
# 当镜像构建时,定义了LABEL,还可以通过LABEL来过滤
docker image ls -f label=com.example.version=0.1以特定格式显示
docker image ls #输出一个完整的表格docker image ls -q 把所有镜像ID输出出来--filter配合-q产生出指定范围ID列表,然后送给另一个docker命令作为参数,从而针对这组实体成批的进行某种操作。
当只是对表格的结构不满意,希望自己组织列;或者不希望有标题,这样方便其他程序解析结果等,就用到Go的模块语法
# 直接输出只包含镜像ID和仓库名:
docker image ls --format "{{:ID}}:{{:Repository}}"
# 以表格等距显示,并有标题行,自己定义列
docker image ls --format "table{{.ID}}\t{{.Repository}}\t{{.Tag}}"删除本地镜像
- 用ID、镜像名、摘要删除镜像
- Untagged和Deleted
- 用docker image ls进行配合
- Centos/RHEL需要注意的问题
删除镜像的格式:
docker image rm [选项] <镜像> [<镜像2> ...]用ID、镜像名、摘要删除镜像
<镜像>可以是镜像短ID、镜像长ID、 镜像名 或者镜像摘要
docker image ls
docker iamge rm 镜像ID
docker image rm 镜像名
docker image ls --digestsREPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
node slim sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228 6e0c4c8e3913 3 weeks ago 214 MB
docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228Untagged和Deleted
镜像的删除行为分为两类:
UntaggedDeleted
镜像的唯一标识是其ID和摘要,而一个镜像可以有多个标签
因此当我们使用docker image rm命令删除镜像的时候,实际上是在要求删除某个标签的镜像。
所以首先需要做的是将满足我们要求的所有镜像标签都取消,这就是我们看到的Untagged的信息。
因为一个镜像可以对应多个标签,因此当我们删除了所指定的标签后,可能还有别的标签指向了这个镜像,如果是这种情况,那么 Delete 行为就不会发生。
所以并非所有的docker image rm都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已.
当该镜像所有的标签都被取消了,该镜像很可能会失去了存在的意义,因此会触发删除行为 。镜像是多层存储结构,因此在删除的时候也是从上层向基础层方向依次进行判断删除。镜像的多层结构让镜像复用变动非常容易,因此很有可能某个其它镜像正依赖于当前镜像的某一层。这种情况,依旧不会触发删除该层的行为。直到没有任何层依赖当前层时,才会真实的删除当前层。这就是为什么,有时候会奇怪,为什么明明没有别的标签指向这个镜像,但是它还是存在的原因,也是为什么有时候会发现所删除的层数和自己docker pull看到的层数不一样的源。
除了镜像依赖以外,还需要注意的是容器对镜像的依赖。如果有用这个镜像启动的容器存在(即使容器没有运行),那么同样不可以删除这个镜像。之前讲过,容器是以镜像为基础,再加一层容器存储层,组成这样的多层存储结构去运行的。因此该镜像如果被这个容器所依赖的,那么删除必然会导致故障。如果这些容器是不需要的,应该先将它们删除,然后再来删除镜像。
用docker image ls命令进行配合
像其他可以承接多个实体的命令一样,可以使用 docker image ls -q来配合使用 docker image rm,这样可以成批的删除希望删除的镜像。
# 如:我们需要删除所有仓库名为redis的镜像:
docker image rm $(docker images ls -q redis)
# 或者删除所有在mongo:3.2之前的镜像
docker image rm $(docker image ls -q -f before=mongo:3.2)