目录
获取镜像
Docker 运行容器前需要本地存在对应的镜像,如果本地不存在该镜像,Docker 会从镜像仓库下载该镜像。
Docker Hub上有大量的高质量的镜像可以用;
从 Docker 镜像仓库获取镜像的命令是 docker pull 。其命令格式为:
docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
- 地址:地址的格式一般是 [:端口号] 。默认地址是 Docker Hub。
- 仓库名:仓库名是两段式名称,即 / 。对于 Docker Hub,如果不给出用户名,则默认为 library ,也就是官方镜像。
例如:
[root@docker ~]# docker pull ubuntu:16.04
16.04: Pulling from library/ubuntu
e80174c8b43b: Pull complete
d1072db285cc: Pull complete
858453671e67: Pull complete
3d07b1124f98: Pull complete
Digest: sha256:bb5b48c7750a6a8775c74bcb601f7e5399135d0a06de004d000e05fd25c1a71c
Status: Downloaded newer image for ubuntu:16.04
docker.io/library/ubuntu:16.04
上面的命令中没有给出 Docker 镜像仓库地址,因此将会从 Docker Hub 获取镜像。而镜像名称是 ubuntu:16.04 ,因此将会获取官方镜像 library/ubuntu 仓库中标签为 16.04 的镜像。
运行镜像
以上面的 ubuntu:16.04 为例,启动里面的 bash 并且进行交互式操作的话:
[root@docker ~]# docker run -it --rm ubuntu:16.04 bash
root@3a31439393f0:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.6 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.6 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
VERSION_CODENAME=xenial
UBUNTU_CODENAME=xenial
root@3a31439393f0:/# ls
bin dev home lib64 mnt proc run srv tmp var
boot etc lib media opt root sbin sys usr
root@3a31439393f0:/# exit
exit
[root@docker ~]#
docker run:运行容器的命令。如果没有此镜像,会先pull再运行。
参数说明:
- -it :这是两个参数,一个是 -i :交互式操作,一个是 -t 终端。这里打算进入bash 执行一些命令并查看返回结果,因此需要交互式终端。
- --rm :容器退出后随之将其删除。默认情况下,为了排障需求,退出的容 器并不会立即删除,除非手动 docker rm 。这里只是随便执行个命令,看看结果, 不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
- ubuntu:16.04 :指用 ubuntu:16.04 镜像为基础来启动容器。
- bash :放在镜像名后的是命令,这里希望有个交互式 Shell,因此用的是 bash 。
进入容器后,可以在 Shell 下操作,执行任何所需的命令。
最后通过 exit 退出这个容器。
列出镜像
列出已经下载下来的镜像:docker image ls 或 docker images
列表包含了 仓库名 、 标签 、 镜像 ID 、 创建时间 以及 所占用的空间 。
[root@docker ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 16.04 5f2bf26e3524 11 days ago 123MB
ubuntu new-tag 5f2bf26e3524 11 days ago 123MB
hello-world latest fce289e99eb9 10 months ago 1.84kB
镜像 ID 则是镜像的唯一标识,一个镜像可以对应多个标签。在上面的例子中, ubuntu:16.04 和 ubuntu:new-tag拥有相同的 ID,因为它们对应的是同一个镜像。
修改标签命令:
[root@docker ~]# docker tag IMAGEID(镜像id) REPOSITORY:TAG(仓库:标签)
[root@docker ~]# docker tag 5f2bf26e3524 ubuntu:new-tag
删除标签命令:
# docker rmi -f REPOSITORY:TAG(仓库:标签)
查看镜像、容器、数据卷所占用的空间:
[root@docker ~]# docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 2 1 122.6MB 122.6MB (99%)
Containers 1 0 0B 0B
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0B
docker system df -v 命令可以进一步查看空间占用细节,以确定是哪个镜像、容器或本地卷占用过高空间
扩展:
[root@docker ~]# docker image ls ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 16.04 5f2bf26e3524 11 days ago 123MB
ubuntu new-tag 5f2bf26e3524 11 days ago 123MB
[root@docker ~]# docker image ls ubuntu:16.04
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 16.04 5f2bf26e3524 11 days ago 123MB
虚悬镜像
镜像列表中,有时还可以看到一个特殊的镜像,这个镜像既没有仓库名,也没有标签,均为 <none>
可以用下面的命令专门显示这类镜像:
[root@docker ~]# docker image ls -f dangling=true
REPOSITORY TAG IMAGE ID CREATED SIZE
<none> <none> 00285df0df87 12 days ago 340MB
这个镜像原本是有镜像名和标签的,随着官方镜像维护,发布了新版本 后,重新 docker pull 时, 这个镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消,从而成为了 <none> 。除了 docker pull 可能导致 这种情况, docker build 也同样可以导致这种现象。由于新旧镜像同名,旧镜像名称被取 消,从而出现仓库名、标签均为的镜像。这类无标签镜像也被称为 虚悬镜像 (dangling image) 。
一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用下面的命令删除:
[root@docker ~]# docker image prune
该命令所清理的对象如下:
已停止的容器
未被任何容器使用的卷
未被任何容器所关联的网络
所有悬空的镜像
中间层镜像
docker image ls 列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加 -a 参数。
# docker image ls -a
这样会看到很多无标签的镜像,与之前的虚悬镜像不同,这些无标签的镜像很多都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。实际上,这些镜像也没必要删除,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份,无论如何你也会需要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。
以特定格式显示
列出 镜像 ID :
[root@docker ~]# docker image ls -q
5f2bf26e3524
5f2bf26e3524
fce289e99eb9
列出 镜像ID、仓库名 和 标签:
[root@docker ~]# docker image ls --format "{{.ID}}: {{.Repository}} {{.Tag}}"
5f2bf26e3524: ubuntu 16.04
5f2bf26e3524: ubuntu new-tag
fce289e99eb9: hello-world latest
以表格等距显示,有标题行,自己定义列:
[root@docker ~]# docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID REPOSITORY TAG
5f2bf26e3524 ubuntu 16.04
5f2bf26e3524 ubuntu new-tag
fce289e99eb9 hello-world latest
删除本地镜像
docker image rm [选项] <镜像1> [<镜像2> ...]
其中, <镜像> 可以是 镜像短 ID 、 镜像长 ID 、 镜像名 或者 镜像摘要 。
删除所有仓库名为 xx 的镜像:
# docker image rm $(docker image ls -q xx)
可以用 docker image ls 命令来配合 docker image rm,实现批量删除。
例如:
# 需要停止容器,解除容器对镜像的依赖,才可删除
[root@docker ~]# docker image rm fce289e99eb9
Error response from daemon: conflict: unable to delete fce289e99eb9 (must be forced) - image is being used by stopped container 4e6514cbf838
# 停止所有容器
[root@docker ~]# docker stop $(docker ps -a -q)
4e6514cbf838
# 短ID 来删除镜像;一般取前3个字符以上,只要足够区分于别的镜像就可以了。
[root@docker ~]# docker image rm fce289
Untagged: hello-world:latest
Untagged: hello-world@sha256:c3b4ada4687bbaa170745b3e4dd8ac3f194ca95b2d0518b417fb47e5879d9b5f
Deleted: sha256:fce289e99eb9bca977dae136fbe2a82b6b7d4c372474c9235adc1741675f587e
Deleted: sha256:af0b15c8625bb1938f1d7b17081031f649fd14e6b233688eea3c5483994a66a3
观察上面删除输出信息的话,会发现到删除行为分为两类,一类是 Untagged ,另一类是 Deleted 。
镜像的唯一标识是其 ID 和摘要,而一个 镜像可以有多个标签。
因此当我们使用上面命令删除镜像的时候,实际上是在要求删除某个标签的镜像。所以首先需要做的是将满足我们要求的所有镜像标签都取消,这就是我们看到的 Untagged 的信息。 因为一个镜像可以对应多个标签,因此当我们删除了所指定的标签后,可能还有别的标签指向了这个镜像,如果是这种情况,那么 Delete 行为就不会发生。所以并非所有的 docker rmi 都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。
当该镜像所有的标签都被取消了,该镜像很可能会失去了存在的意义,因此会触发删除行为。镜像是多层存储结构,因此在删除的时候也是从上层向基础层方向依次进行判断删除。 镜像的多层结构让镜像复用变动非常容易,因此很有可能某个其它镜像正依赖于当前镜像的某一层。这种情况,依旧不会触发删除该层的行为。直到没有任何层依赖当前层时,才会真实的删除当前层。这就是为什么,有时候会奇怪,为什么明明没有别的标签指向这个镜像, 但是它还是存在的原因,也是为什么有时候会发现所删除的层数和自己 docker pull 看到的层数不一样的源。
除了镜像依赖以外,还需要注意的是容器对镜像的依赖。如果有用这个镜像启动的容器存在 (即使容器没有运行),那么同样不可以删除这个镜像。容器是以镜像为基础, 再加一层容器存储层,组成这样的多层存储结构去运行的。因此该镜像如果被这个容器所依赖的,那么删除必然会导致故障。如果这些容器是不需要的,应该先将它们删除,然后再来删除镜像。