docker将多个镜像打包成一个镜像 (docker入门教程)

1. 获取镜像

(1)

从Docker镜像仓库获取镜像的命令是 docker pull。其命令格式为:

docker pull [选项] [DockerRegistry地址[:端口号]/]仓库名[:标签]

dockerpull--help

(2)docker pull ubuntu:18.04

[root@centos2 ~]# docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
898c46f3b1a1: Pull complete 
63366dfa0a50: Pull complete 
041d4cd74a92: Pull complete 
6e1bee0f8701: Pull complete 
Digest: sha256:017eef0b616011647b269b5c65826e2e2ebddbe5d1f8c1e56b3599fb14fabec8
Status: Downloaded newer image for ubuntu:18.04

此处没有给出Docker镜像仓库地址,因此将会从Docker Hub获取镜像。而镜像名称是 ubuntu:18.04,因此将会获取官方镜像 library/ubuntu仓库中标签为 18.04的镜像。

在使用上面命令的时候,你可能会发现,你所看到的层ID以及 sha256的摘要和这里的不一样。这是因为官方镜像是一直在维护的,有任何新的bug,或者版本更新,都会进行修复再以原来的标签发布,这样可以确保任何使用这个标签的用户可以获得更安全、更稳定的镜像。

2. 运行

有了镜像后,我们就能够以这个镜像为基础启动并运行一个容器。以上面的ubuntu:18.04为例,如果我们打算启动里面的bash并且进行交互式操作的话,可以执行下面的命令。

[root@centos2 ~]# docker run -it --rm ubuntu:18.04 bash
root@1c2735fd8de9:/# cat /etc/os-release
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.2 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

除了bash命令外,也可以执行其他命令:

[root@centos2 ~]# docker run -it --rm ubuntu:18.04 cat /etc/os-release
WARNING: IPv4 forwarding is disabled. Networking will not work.
NAME="Ubuntu"
VERSION="18.04.2 LTS (Bionic Beaver)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 18.04.2 LTS"
VERSION_ID="18.04"
HOME_URL="https://www.ubuntu.com/"
SUPPORT_URL="https://help.ubuntu.com/"
BUG_REPORT_URL="https://bugs.launchpad.net/ubuntu/"
PRIVACY_POLICY_URL="https://www.ubuntu.com/legal/terms-and-policies/privacy-policy"
VERSION_CODENAME=bionic
UBUNTU_CODENAME=bionic

最后通过exit退出这个容器。

3.列出镜像

(1)查看镜像

[root@centos2 ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 94e814e2efa8 6 weeks ago 88.9MB

此处显示的镜像大小88.9MB可能和 Docker Hub中显示的大小不一样,Docker Hub 中显示的体积是压缩后的体积。在镜像*载下**和上传过程中镜像是保持着压缩状态的,因此Docker Hub所显示的大小是网络传输中更关心的流量大小。而docker image ls显示的是镜像*载下**到本地后,展开的大小,准确说,是展开后的各层所占空间的总和,因为镜像到本地后,查看空间的时候,更关心的是本地磁盘空间占用的大小。

(2)查看镜像占用的空间大小

可以使用如下命令查看镜像、容器、数据卷所占用的空间:

[root@centos2 ~]# docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 3 2 219.9MB 88.91MB (40%)
Containers 2 0 323.6kB 323.6kB (100%)
Local Volumes 0 0 0B 0B
Build Cache 0 0 0B 0B

(3)中间层镜像

为了加速镜像构建、重复利用资源,Docker会利用中间层镜像。所以在使用一段时间后,可能会看到一些依赖的中间层镜像。默认的docker image ls列表中只会显示顶层镜像,如果希望显示包括中间层镜像在内的所有镜像的话,需要加-a参数。

很多无标签的镜像就是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不应该删除,否则会导致上层镜像因为依赖丢失而出错。实际上,这些镜像也没必要删除,因为之前说过,相同的层只会存一遍,而这些镜像是别的镜像的依赖,因此并不会因为它们被列出来而多存了一份。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。

(4)列出指定镜像

不加任何参数的情况下,docker image ls会列出所有顶级镜像,但是有时候我们只希望列出部分镜像

指定镜像的仓库名称(不加tag):

[root@centos2 ~]# docker image ls ubuntu
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 94e814e2efa8 6 weeks ago 88.9MB
ubuntu latest 94e814e2efa8 6 weeks ago 88.9MB

指定镜像的名称:

[root@centos2 ~]# docker image ls ubuntu:18.04
REPOSITORY TAG IMAGE ID CREATED SIZE
ubuntu 18.04 94e814e2efa8 6 weeks ago 88.9MB

指定比某镜像新/旧的镜像:

[root@centos2 ~]# docker image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
shushenlw/mydocker get_started 542981dbc30a 7 days ago 131MB
ubuntu 18.04 94e814e2efa8 6 weeks ago 88.9MB
hello-world latest fce289e99eb9 3 months ago 1.84kB
[root@centos2 ~]# 
[root@centos2 ~]# docker image ls -f since=ubuntu:18.04
REPOSITORY TAG IMAGE ID CREATED SIZE
shushenlw/mydocker get_started 542981dbc30a 7 days ago 131MB
[root@centos2 ~]# 
[root@centos2 ~]# docker image ls -f before=ubuntu:18.04
REPOSITORY TAG IMAGE ID CREATED SIZE
hello-world latest fce289e99eb9 3 months ago 1.84kB

(5)列出镜像的输出格式

只列出镜像id:

[root@centos2 ~]# docker image ls -q
542981dbc30a
94e814e2efa8
fce289e99eb9

列出指定列:

[root@centos2 ~]# docker image ls --format "{{.ID}} \t {{.Repository}} \t {{.Size}}"
542981dbc30a shushenlw/mydocker 131MB
94e814e2efa8 ubuntu 88.9MB
fce289e99eb9 hello-world 1.84kB

可以看出各个列间没有对其,因为列的长度不一样,可以以表格方式输出:

以表格方式输出指定列:

[root@centos2 ~]# docker image ls --format "table {{.ID}} \t {{.Repository}} \t {{.Size}}"
IMAGE ID REPOSITORY SIZE
542981dbc30a shushenlw/mydocker 131MB
94e814e2efa8 ubuntu 88.9MB
fce289e99eb9 hello-world 1.84kB

4. 删除镜像

docker image rm <镜像>

以如下镜像为例:

ubuntu 18.04 94e814e2efa8 6 weeks ago 88.9MB

(1)指定ID删除

以下通过长ID和短ID都可以:

docker image rm 94e814e2efa8

docker image rm 94e

(2)指定镜像名称

docker image rm ubuntu:18.04

(3)指定镜像摘要

[root@centos2 ~]# docker image ls --digests
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
shushenlw/mydocker get_started sha256:f0573992174d8108c8f08f5249ff922b297a2aa6a34b81d74070b037f1cb9f9a 542981dbc30a 7 days ago 131MB
ubuntu 18.04 sha256:017eef0b616011647b269b5c65826e2e2ebddbe5d1f8c1e56b3599fb14fabec8 94e814e2efa8 6 weeks ago 88.9MB
hello-world latest sha256:92695bc579f31df7a63da6922075d0666e565ceccad16b59c3374d2cf4e8e50e fce289e99eb9 3 months ago 1.84kB
[root@centos2 ~]# docker image rm hello-world@sha256:92695bc579f31df7a63da6922075d0666e565ceccad16b59c3374d2cf4e8e50e
Untagged: hello-world@sha256:92695bc579f31df7a63da6922075d0666e565ceccad16b59c3374d2cf4e8e50e
	
[root@centos2 ~]# docker image ls --digests
REPOSITORY TAG DIGEST IMAGE ID CREATED SIZE
shushenlw/mydocker get_started sha256:f0573992174d8108c8f08f5249ff922b297a2aa6a34b81d74070b037f1cb9f9a 542981dbc30a 8 days ago 131MB
ubuntu 18.04 sha256:017eef0b616011647b269b5c65826e2e2ebddbe5d1f8c1e56b3599fb14fabec8 94e814e2efa8 6 weeks ago 88.9MB
hello-world latest <none> fce289e99eb9 3 months ago 1.84kB

删除行为分为两类,一类是Untagged,另一类是Deleted。之前介绍过,镜像的唯一标识是其ID和摘要,而一个镜像可以有多个标签。因此当我们使用上面命令删除镜像的时候,实际上是在要求删除某个标签的镜像。

所以首先需要做的是将满足我们要求的所有镜像标签都取消,这就是我们看到的Untagged的信息。因为一个镜像可以对应多个标签,因此当我们删除了所指定的标签后,可能还有别的标签指向了这个镜像,如果是这种情况,那么Delete行为就不会发生。所以并非所有的docker image rm都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。

镜像是多层存储结构,因此在删除的时候也是从上层向基础层方向依次进行判断删除。镜像的多层结构让镜像复用变动非常容易,因此很有可能某个其它镜像正依赖于当前镜像的某一层。这种情况,依旧不会触发删除该层的行为。直到没有任何层依赖当前层时,才会真实的删除当前层。这就是为什么,有时候会奇怪,为什么明明没有别的标签指向这个镜像,但是它还是存在的原因,也是为什么有时候会发现所删除的层数和自己docker pull看到的层数不一样的原因。

除了镜像依赖以外,还需要注意的是容器对镜像的依赖。如果有用这个镜像启动的容器存在(即使容器没有运行),那么同样不可以删除这个镜像。

(4)批量删除镜像

需要删除所有仓库名为redis的镜像:

[root@centos2 ~]# docker image rm $(docker image ls -q redis)