Docker笔记-02 镜像

常哲彦
2023-12-01

镜像是Docker的三大核心概念之一。Docker运行容器前需要本地存在对应的镜像,如果镜像不存在本地,Docker会尝试先从默认镜像仓库下载(默认使用Docker Hub公共注册服务器中的仓库),用户也可以通过配置,使用自定义的镜像仓库。

1 获取镜像

镜像是Docker运行容器的前提。可以使用pull命令从仓库下载镜像。命令格式:

docker [image] pull NAME [:TAG]
  • NAME : 镜像仓库名称(用来区分镜像)
  • TAG : 镜像的标签(用来表示版本信息)

对于Docker镜像,如果不显示地指定TAG,则默认会选择latest标签,即下载仓库中最新版本的镜像。

另外,默认是从DockerHub的仓库中下。即:sudo docker pull registry.hub.docker.com/ubuntu:18.04其中registry.hub.docker.com是默认值,也不写。

下载过程中可以看出 ,镜像文件一般由若干层(layer)组成 ,6c953ac5d795这样的串是层的唯一id(实际上完整的id包括256比特,64个十六进制字符组成)。使用docker pull命令下载中会获取并输出镜像的各层信息。当不同的镜像包括相同的层时,本地仅存储了层的 一份内容,减小了存储空间。

如果需要从其他注册服务器的仓库下载,需要在仓库名称前指定完整的仓库注册服务器地址。如:sudo docker pull dl.dockerpool.com:5000/ubuntu

1.1 pull子命令选项

  • -a, --all-tags=true|false: 是否获取仓库中的所有镜像,默认为否;
  • –disable-content-trust:取消镜像的内容校验,默认为真。

有时需要使用镜像代理服务来加速Docker镜像获取 过程 ,可以在Docker服务启动配置中增加 --regis七ry-mirror=proxy_URL来指定镜像代理服务地址(如https://registry.docker-en.com) 。

2 查看镜像信息

2.1 使用images命令列出镜像

使用docker imagesdocker image ls命令可以列出本地主机上已有的镜像。

(base) pang@pang-HP:~$ sudo docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   8 months ago   13.3kB
(base) pang@pang-HP:~$ 
  • PEPOSTORY:来自于哪个仓库
  • TAG:镜像的标签信息
  • IMAGE ID:镜像的ID号(唯一),如果两个镜像的ID相同, 说明它们实际上指向了同一个镜像, 只是具有不同标签名称而已;
  • CREATE:创建时间,说明镜像最后的更新时间;
  • VIRTUAL 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来查看。

2.1.1 虚悬镜像

有的镜像列表中,还可以看到一个特殊的镜像,这个镜像既没有仓库名,也没有标签,均为。:

<none>               <none>              00285df0df87        5 days ago          342 MB

这个镜像原本是有镜像名和标签的,原来为mongo:3.2,随着官方镜像维护,发布了新版本后,重新docker pull mongo:3.2时,mongo:3.2这个镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消,从而成为了 。

除了docker pull可能导致这种情况,docker build也同样可以导致这种现象。由于新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 的镜像。这类无标签镜像也被称为虚悬镜像(dangling image),可以用下面的命令专门显示这类镜像:

$ docker image ls -f dangling=true
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
<none>              <none>              00285df0df87        5 days ago          342 MB

一般来说,虚悬镜像已经失去了存在的价值,是可以随意删除的,可以用下面的命令删除。

$ docker image prune

2.1.2 中间层镜像

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

$ docker image ls -a

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

2.1.3 列出部分镜像

不加任何参数的情况下,docker image ls会列出所有顶层镜像,但是有时候我们只希望列出部分镜像。docker image ls有好几个参数可以帮助做到这个事情。

  • 根据仓库名列出镜像
$ docker image ls ubuntu
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              18.04               329ed837d508        3 days ago          63.3MB
ubuntu              bionic              329ed837d508        3 days ago          63.3MB
  • 列出特定的某个镜像,也就是说指定仓库名和标签
$ docker image ls ubuntu:18.04
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
ubuntu              18.04               329ed837d508        3 days ago          63.3MB

除此以外,docker image ls还支持强大的过滤器参数--filter,或者简写-f。之前我们已经看到了使用过滤器来列出虚悬镜像的用法,它还有更多的用法。比如,我们希望看到在mongo:3.2之后建立的镜像,可以用下面的命令:

$ docker image ls -f since=mongo:3.2
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
redis               latest              5f515359c7f8        5 days ago          183 MB
nginx               latest              05a60462f8ba        5 days ago          181 MB

想查看某个位置之前的镜像也可以,只需要把since换成before即可。

此外,如果镜像构建时,定义了LABEL,还可以通过LABEL 来过滤。

$ docker image ls -f label=com.example.version=0.1

2.1.4 以特定格式显示

默认情况下,docker image ls会输出一个完整的表格,但是我们并非所有时候都会需要这些内容。比如,删除虚悬镜像的时候,需要利用docker image ls把所有的虚悬镜像的ID列出来,然后才可以交给docker image rm命令作为参数来删除指定的这些镜像,这个时候就用到了-q参数。

$ docker image ls -q
5f515359c7f8
05a60462f8ba
fe9198c04d62
00285df0df87
329ed837d508
329ed837d508

--filter配合-q产生出指定范围的ID列表,然后送给另一个docker命令作为参数,从而针对这组实体成批的进行某种操作的做法在Docker命令行使用过程中非常常见,不仅仅是镜像,将来我们会在各个命令中看到这类搭配以完成很强大的功能。因此每次在文档看到过滤器后,可以多注意一下它们的用法。

另外一些时候,我们可能只是对表格的结构不满意,希望自己组织列;或者不希望有标题,这样方便其它程序解析结果等,这就用到了Go的模板语法。比如,下面的命令会直接列出镜像结果,并且只包含镜像ID和仓库名:

$ docker image ls --format "{{.ID}}: {{.Repository}}"
5f515359c7f8: redis
05a60462f8ba: nginx
fe9198c04d62: mongo
00285df0df87: <none>
329ed837d508: ubuntu
329ed837d508: ubuntu

或者打算以表格等距显示,并且有标题行,和默认一样,不过自己定义列:

$ docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}"
IMAGE ID            REPOSITORY          TAG
5f515359c7f8        redis               latest
05a60462f8ba        nginx               latest
fe9198c04d62        mongo               3.2
00285df0df87        <none>              <none>
329ed837d508        ubuntu              18.04
329ed837d508        ubuntu              bionic

2.2 使用tag命令添加镜像标签

使用docker tag命令为本地镜像添加新的标签。如sudo docker tag hello-world hello-world1

(base) pang@pang-HP:~$ sudo docker tag hello-world hello-world1
(base) pang@pang-HP:~$ sudo docker images
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
hello-world    latest    feb5d9fea6a5   8 months ago   13.3kB
hello-world1   latest    feb5d9fea6a5   8 months ago   13.3kB
(base) pang@pang-HP:~$ 

hello-world和hello-world1的ID均一致,实际上也均指向同一个镜像文件,只是别名不同而已。

2.3 使用inspect命令查详细信息

使用docker inspect命令可以获取该镜像的详细信息。如:sudo docker inspect hello-world

(base) pang@pang-HP:~$ sudo docker inspect hello-world
[
    {
        "Id": "sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412",
        "RepoTags": [
            "hello-world1:latest",
            "hello-world:latest"
        ],
        "RepoDigests": [
            "hello-world@sha256:80f31da1ac7b312ba29d65080fddf797dd76acfb870e677f390d5acba9741b17"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-09-23T23:47:57.442225064Z",
        "Container": "8746661ca3c2f215da94e6d3f7dfdcafaff5ec0b21c9aff6af3dc379a82fbc72",
        "ContainerConfig": {
            "Hostname": "8746661ca3c2",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
...

该命令返回的是一个JSON格式的信息,如果只需要其中一项内容时,可以使用-f参数来指定。如:sudo docker inspect -f {{".Architecture"}} hello-world 即获取镜像的Architecture信息。

(base) pang@pang-HP:~$ sudo docker inspect -f {{".Architecture"}}  hello-world
amd64
(base) pang@pang-HP:~$

2.4 使用history命令查看镜像历史

既然镜像文件由多个层组成, 具体各个层的内容是什么,可以使用history子命令, 该命令将列出各层的创建信息。

(base) pang@pang-HP:~$ sudo docker history hello-world
IMAGE          CREATED        CREATED BY                                      SIZE      COMMENT
feb5d9fea6a5   8 months ago   /bin/sh -c #(nop)  CMD ["/hello"]               0B        
<missing>      8 months ago   /bin/sh -c #(nop) COPY file:50563a97010fd7ce…   13.3kB    
(base) pang@pang-HP:~$ 

3 搜寻镜像

使用docker search命令可以搜索远端仓库中共享的镜像,默认搜索Docker Hub官方仓库中的镜像。语法为docker search [option] keyword。 支持的命令选项主要包括:

  • -f, --filter filter: 过滤输出内容;
  • –format string: 格式化输出内容;
  • –limit int:限制输出结果个数,默认为25个;
  • –no-trunc: 不截断输出结果
  • –automated=false 仅显示自动创建的镜像
  • –no-trunc=false 输出信息不截断显示
  • -s,–stars=0 指定仅显示评价为指定星级以上的镜像;

3.1 最简单的搜索mysql镜像

以搜寻mysql镜像为例,执行命令sudo docker search mysql,其结果如下:

(base) pang@pang-HP:~$ sudo docker search mysql
NAME                           DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
mysql                          MySQL is a widely used, open-source relation…   12717     [OK]       
mariadb                        MariaDB Server is a high performing open sou…   4882      [OK]       
percona                        Percona Server is a fork of the MySQL relati…   579       [OK]       
phpmyadmin                     phpMyAdmin - A web interface for MySQL and M…   555       [OK]       
bitnami/mysql                  Bitnami MySQL Docker Image                      71                   [OK]
linuxserver/mysql-workbench                                                    36                   
linuxserver/mysql              A Mysql container, brought to you by LinuxSe…   35                   
ubuntu/mysql                   MySQL open source fast, stable, multi-thread…   34                   
circleci/mysql                 MySQL is a widely used, open-source relation…   26                   
google/mysql                   MySQL server for Google Compute Engine          21                   [OK]
rapidfort/mysql                RapidFort optimized, hardened image for MySQL   13                   
vmware/harbor-db               Mysql container for Harbor                      10                   
bitnami/mysqld-exporter                                                        3                    
ibmcom/mysql-s390x             Docker image for mysql-s390x                    2                    
nasqueron/mysql                                                                1                    [OK]
vitess/mysqlctld               vitess/mysqlctld                                1                    [OK]
newrelic/mysql-plugin          New Relic Plugin for monitoring MySQL databa…   1                    [OK]
mirantis/mysql                                                                 0                    
docksal/mysql                  MySQL service images for Docksal - https://d…   0                    
drud/mysql-local-57            ddev mysql local container                      0                    
drud/mysql                                                                     0                    
drud/mysql-docker-local-57     This repo has been deprecated, new tags are …   0                    
drud/mysql-docker-local        docker containers for local womysql rk          0                    [OK]
cimg/mysql                                                                     0                    
silintl/mysql-backup-restore   Simple docker image to perform mysql backups…   0                    [OK]
(base) pang@pang-HP:~$ 

默认的输出结果将按照星级评价进行排序,其字段含义为:

  • NAME - 镜像名字
  • DESCRIPTION - 描述
  • STARS - 星级(表示该镜像的受欢迎程度)
  • OFFICIAL - 是否官方创建,即说明该镜像由官方项目组创建和维护。
  • AUTOMETES - 是否自动创建,允许用户验证镜像的来源和内容。

3.2 搜索官方提供的带nginx关键字的镜像

(base) pang@pang-HP:~$ sudo docker search --filter=is-official=true nginx
NAME      DESCRIPTION                STARS     OFFICIAL   AUTOMATED
nginx     Official build of Nginx.   16944     [OK]       
(base) pang@pang-HP:~$ 

3.3 搜索所有收藏数超过4的关键词包括 tensorflow 的镜像

(base) pang@pang-HP:~$ sudo docker search --filter=stars=4 tensorflow
NAME                                  DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
tensorflow/tensorflow                 Official Docker images for the machine learn…   2027                
tensorflow/serving                    Official images for TensorFlow Serving (http…   123                 
bitnami/tensorflow-serving            Bitnami Docker Image for TensorFlow Serving     25                   [OK]
armswdev/tensorflow-arm-neoverse-n1   Please use "armswdev/tensorflow-arm-neoverse"   10                  
ibmcom/tensorflow-ppc64le             Community supported ppc64le docker images fo…   6                   
intel/intel-optimized-tensorflow      Containers with TensorFlow* optimized with o…   5                   
armswdev/tensorflow-arm-neoverse      TensorFlow builds for AArch64 CPUs              4                   
(base) pang@pang-HP:~$ 

3.4 查询镜像版本信息

有两种办法:

  1. 官网查询
    访问https://hub.docker.com/ 搜索centos

  2. 使用curl查询
    首先,通过命令确认NAME

(base) pang@pang-HP:~/dockerfile$ sudo docker search centos
NAME                                         DESCRIPTION                                     STARS     OFFICIAL   AUTOMATED
centos                                       The official build of CentOS.                   7183      [OK]       
centos/systemd                               systemd enabled base container.                 108                  [OK]
centos/mysql-57-centos7                      MySQL 5.7 SQL database server                   95                   
kasmweb/centos-7-desktop                     CentOS 7 desktop for Kasm Workspaces            20                   
centos/mongodb-36-centos7                    MongoDB NoSQL database server                   8                    
kasmweb/core-centos-7                        CentOS 7 base image for Kasm Workspaces         3                    
continuumio/centos5_gcc5_base                                                                3                    
couchbase/centos7-systemd                    centos7-systemd images with additional debug…   1                    [OK]
spack/centos7                                CentOS 7 with Spack preinstalled                1                    
spack/centos-stream                                                                          0                    
couchbase/centos-72-jenkins-core                                                             0                    
fnndsc/centos-python3                        Source for a slim Centos-based Python3 image…   0                    [OK]
couchbase/centos-72-java-sdk                                                                 0                    
couchbase/centos-69-sdk-nodevtoolset-build                                                   0                    
couchbase/centos-70-sdk-build                                                                0                    
datadog/centos-i386                                                                          0                    
spack/centos6                                CentOS 6 with Spack preinstalled                0                    
starlingx/stx-centos                         StarlingX centos                                0                    
ibmcom/fhe-toolkit-centos-amd64              The IBM Fully Homomorphic Encryption (FHE) T…   0                    
ibmcom/fhe-toolkit-centos                    The IBM Fully Homomorphic Encryption (FHE) T…   0                    
apache/couchdbci-centos                      Apache CouchDB CI CentOS                        0                    
silintl/openldap                             OpenLDAP base image on Centos 6                 0                    [OK]
bitnami/centos-extras-base                                                                   0                    
bitnami/centos-base-buildpack                Centos base compilation image                   0                    [OK]
couchbase/centos-69-sdk-build   

其次,将NAME替换下面命令中的XXXX字符。

curl https://registry.hub.docker.com/v1/repositories/xxxx/tags\
| tr -d '[\[\]" ]' | tr '}' '\n'\
| awk -F: -v image='xxxx' '{if(NR!=NF && $3 != ""){printf("%s:%s\n",image,$3)}}'

例如:

(base) pang@pang-HP:~/dockerfile$ curl https://registry.hub.docker.com/v1/repositories/centos/tags\
| tr -d '[\[\]" ]' | tr '}' '\n'\
| awk -F: -v image='centos' '{if(NR!=NF && $3 != ""){printf("%s:%s\n",image,$3)}}'
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  1745    0  1745    0     0   1253      0 --:--:--  0:00:01 --:--:--  1253
centos:latest
centos:5
centos:6
centos:6.10
centos:6.6
centos:6.7
centos:6.8
centos:6.9
centos:7
centos:7.0.1406
centos:7.1.1503
centos:7.2.1511
centos:7.3.1611
centos:7.4.1708
centos:7.5.1804
centos:7.6.1810
centos:7.7.1908
centos:7.8.2003
centos:7.9.2009
centos:8
centos:8.1.1911
centos:8.2.2004
centos:8.3.2011
centos:8.4.2105
centos:centos5
centos:centos5.11
centos:centos6
centos:centos6.10
centos:centos6.6
centos:centos6.7
centos:centos6.8
centos:centos6.9
centos:centos7
centos:centos7.0.1406
centos:centos7.1.1503
centos:centos7.2.1511
centos:centos7.3.1611
centos:centos7.4.1708
centos:centos7.5.1804
centos:centos7.6.1810
centos:centos7.7.1908
centos:centos7.8.2003
centos:centos7.9.2009
centos:centos8
centos:centos8.1.1911
centos:centos8.2.2004
centos:centos8.3.2011
centos:centos8.4.2105
(base) pang@pang-HP:~/dockerfile$ 

4 删除和清理镜像

4.1 使用标签删除镜像

使用docker rmidocker image rm命令可以删除镜像, 命令格式为docker rmi IMAGE [IMAGE ... ],其中IMAGE可以为标签或ID。

支持选项包括:

  • -f, -force: 强制删除镜像, 即使有容器依赖它;
  • -no-prune: 不要清理未带标签的父镜像。

当同一个镜像拥有多个标签的时候,docker rmi命令只是删除了该镜像多个标签中的指定标签而已,并不影响镜像文件。

例如,sudo docker rmi hello-world1只会删除镜像副本hello-world1

(base) pang@pang-HP:~$ sudo docker images
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
hello-world1   latest    feb5d9fea6a5   8 months ago   13.3kB
hello-world    latest    feb5d9fea6a5   8 months ago   13.3kB
(base) pang@pang-HP:~$ 
(base) pang@pang-HP:~$ sudo docker rmi hello-world1:latest
Untagged: hello-world1:latest
(base) pang@pang-HP:~$ sudo docker images
REPOSITORY    TAG       IMAGE ID       CREATED        SIZE
hello-world   latest    feb5d9fea6a5   8 months ago   13.3kB
(base) pang@pang-HP:~$ 

当镜像只剩下一个标签的时候就要小心了, 此时再使用docker rmi命令会彻底删除镜像。

4.2 使用镜像ID来删除镜像

当使用docker rmi命令, 并且后面跟上镜像的ID (也可以是能进行区分的部分ID串前缀)时,会先尝试删除所有指向该镜像的标签, 然后删除该镜像文件本身。

如同上节说将,当同一个镜像拥有多个标签的时候,使用ID删除时,因为有多个副本,所以会提示错误。

(base) pang@pang-HP:~$ sudo docker images
REPOSITORY     TAG       IMAGE ID       CREATED        SIZE
hello-world1   latest    feb5d9fea6a5   8 months ago   13.3kB
hello-world    latest    feb5d9fea6a5   8 months ago   13.3kB
(base) pang@pang-HP:~$ 
(base) pang@pang-HP:~$ sudo docker rmi feb5d9fea6a5
Error response from daemon: conflict: unable to delete feb5d9fea6a5 (must be forced) - image is referenced in multiple repositories
(base) pang@pang-HP:~$

此时可以添加-f参数强制删除,但是要注意,此时会将镜像彻底删除包括其多个副本。

(base) pang@pang-HP:~$ sudo docker rmi feb5d9fea6a5 -f
Untagged: hello-world1:latest
Untagged: hello-world:latest
Untagged: hello-world@sha256:80f31da1ac7b312ba29d65080fddf797dd76acfb870e677f390d5acba9741b17
Deleted: sha256:feb5d9fea6a5e9606aa995e879d862b825965ba48de054caab5ef356dc6b3412
Deleted: sha256:e07ee1baac5fae6a26f30cabfe54a36d3402f96afda318fe0a96cec4ca393359
(base) pang@pang-HP:~$ sudo docker images
REPOSITORY   TAG       IMAGE ID   CREATED   SIZE
(base) pang@pang-HP:~$ 

另外注意,当有该镜像创建的容器存在时,镜像文件默认也是无法被删除的。

(base) pang@pang-HP:~$ sudo docker ps -a
CONTAINER ID   IMAGE         COMMAND    CREATED              STATUS                          PORTS     NAMES
3d6f4e669c61   hello-world   "/hello"   About a minute ago   Exited (0) About a minute ago             priceless_lewin
(base) pang@pang-HP:~$ sudo docker rmi hello-world
Error response from daemon: conflict: unable to remove repository reference "hello-world" (must force) - container 3d6f4e669c61 is using its referenced image feb5d9fea6a5
(base) pang@pang-HP:~$ 

使用docker ps -a命令可以看到本机上存在的所有容器。如果有容器是基于某个镜像产生的,如果删除该镜像则会提示如上错误。此时,也可以使用-f参数强制删除该镜像。如:sudo docker rmi -f hello-world。但是一般不支持使用-f,这样会遗留一些问题。

正确的做法是,先删除依赖该镜像的所有容器, 再来删除镜像。

4.3 清理镜像

使用Docker一段时间后,系统中可能会遗留一些临时的镜像文件,以及一些没有被使用的镜像,可以通过docker image prune命令来进行清理。
支待选项包括:

  • -a, -all: 删除所有无用镜像, 不光是临时镜像;
  • -filter filter: 只清理符合给定过滤器的镜像;
  • -f, -force: 强制删除镜像, 而不进行提示确认;

例如, 如下命令会自动清理临时的遗留镜像文件层, 最后会提示释放的存储空间:

$ sudo docker image prune -f
. . .
Total reclaimed space: 1.4 GB

4.4 Untagged 和 Deleted

如果观察上面这几个命令的运行输出信息的话,你会注意到删除行为分为两类,一类是Untagged,另一类是Deleted。我们之前介绍过,镜像的唯一标识是其ID和摘要,而一个镜像可以有多个标签。

因此当我们使用上面命令删除镜像的时候,实际上是在要求删除某个标签的镜像。所以首先需要做的是将满足我们要求的所有镜像标签都取消,这就是我们看到的Untagged的信息。

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

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

除了镜像依赖以外,还需要注意的是容器对镜像的依赖。如果有用这个镜像启动的容器存在(即使容器没有运行),那么同样不可以删除这个镜像。之前讲过,容器是以镜像为基础,再加一层容器存储层,组成这样的多层存储结构去运行的。因此该镜像如果被这个容器所依赖的,那么删除必然会导致故障。如果这些容器是不需要的,应该先将它们删除,然后再来删除镜像。

4.5 用docker image ls命令来配合

像其它可以承接多个实体的命令一样,可以使用docker image ls -q来配合使用docker image rm,这样可以成批的删除希望删除的镜像。第3节介绍的很多过滤镜像列表的方式都可以拿过来使用。

比如,我们需要删除所有仓库名为redis的镜像:

$ docker image rm $(docker image ls -q redis)

或者删除所有在 mongo:3.2 之前的镜像:

$ docker image rm $(docker image ls -q -f before=mongo:3.2)

5 创建镜像

创建镜像的方法有几种:基于已有镜像的容器创建;基于本地模板导入;基于Dockerfile创建。

5.1 基于已有镜像的容器创建

主要是使用docker [container] commit命令,其命令格式为:

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 提交时暂停容器运行

例如:

$ docker run -it ubuntu:18.04 /bin/bash
root@a925cb40b3f0:/# touch test
root@a925cb40b3f0:/# exit
# 记住容器的 ID 为 a925cb40b3£0
$ docker [container] commit -m "Added a new file" -a "Docker Newbee" a925cb40b3f0
test:0.1
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
test 0.1 9e9c814023bc 4 seconds ago 188 MB

5.2 基于本地模板导入

可以直接从一个操作系统模板文件导人一个镜像,主要使用docker [container] import命令。 命令格式为:

docker [image] import [OPTIONS] file|URL|- [REPOSITORY[:TAG ]]

要直接导人一个镜像,可以使用OpenVZ提供的模板来创建,或者用其他已导出的镜像模板来创建。

例如:

$ cat ubuntu-18.04-x86_64-minimal.tar.gz I docker import - ubuntu:lB.04
$ docker images
REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE
ubuntu 18.04 05ac7c0b9383 17 seconds ago 215.5 MB

5.3 基于Dockfile创建

基于Dockerfile创建是最常见的方式。Dockerfile是一个文本文件,其内包含了一条条的指令(Instruction),每一条指令构建一层,因此每一条指令的内容,就是描述该层应当如何构建。

这里使用了docker build命令进行镜像构建。其格式为:

docker build [选项] <上下文路径/URL/->

具体Dockerfile后续讲解,先以简单示例说明:基于debian:stretch-slim镜像安装Python3环境,构成一个新的python:3镜像

  • 首先,创建Dockerfile文件touch Dockerfile,其内容如下:
FROM debian:stretch-slim

LABEL version="1.0" maintainer="docker user <docker_user@github>"

RUN apt-get update && \
   apt-get install -y python3 & \
   apt-get clean && \
   rm -rf /var/lib/apt/lists/*
  • 在Dockerfile所在目录执行
(base) pang@pang-HP:~/dockerfile$ sudo docker build -t python:3 .
Sending build context to Docker daemon  2.048kB
Step 1/3 : FROM debian:stretch-slim
stretch-slim: Pulling from library/debian
73e8e0576286: Pull complete 
Digest: sha256:b57dec331d7fa856af213f861750bbdec85736741d8b81ef72769cfd344739e5
Status: Downloaded newer image for debian:stretch-slim
 ---> a88d8e7bd33c
Step 2/3 : LABEL version="1.0" maintainer="docker user <docker_user@github>"
 ---> Running in 4763edb79756
Removing intermediate container 4763edb79756
 ---> 41180a17a248
Step 3/3 : RUN apt-get update &&    apt-get install -y python3 &    apt-get clean &&    rm -rf /var/lib/apt/lists/*
 ---> Running in 66abe4e23da1
Removing intermediate container 66abe4e23da1
 ---> 763642b839b7
Successfully built 763642b839b7
Successfully tagged python:3
(base) pang@pang-HP:~/dockerfile$
  • 检查当前镜像列表
(base) pang@pang-HP:~/dockerfile$ sudo docker images
REPOSITORY    TAG            IMAGE ID       CREATED         SIZE
python        3              763642b839b7   8 seconds ago   55.4MB
debian        stretch-slim   a88d8e7bd33c   2 weeks ago     55.4MB
hello-world   latest         feb5d9fea6a5   8 months ago    13.3kB
(base) pang@pang-HP:~/dockerfile$ 

6 导出和导入镜像

本小节介绍Docker镜像的saveload子命令 。 用户可以使用docker [image] savedocker [image] load命令来存出和载人镜像。

6.1 导出镜像

如果要导出镜像到本地文件,可以使用docker [image] save命令。 该命令支持-o--output string参数 , 导出镜像到指定的文件中。

(base) pang@pang-HP:~/dockerfile$ sudo docker images
REPOSITORY    TAG            IMAGE ID       CREATED         SIZE
python        3              763642b839b7   8 seconds ago   55.4MB
debian        stretch-slim   a88d8e7bd33c   2 weeks ago     55.4MB
hello-world   latest         feb5d9fea6a5   8 months ago    13.3kB
(base) pang@pang-HP:~/dockerfile$ 
(base) pang@pang-HP:~/dockerfile$ sudo docker save -o hello.tar hello-world
(base) pang@pang-HP:~/dockerfile$ ll
总用量 36
drwxrwxr-x  2 pang pang  4096  6月 14 14:34 ./
drwxr-x--- 72 pang pang  4096  6月 14 14:23 ../
-rw-rw-r--  1 pang pang   204  6月 14 14:23 Dockerfile
-rw-------  1 root root 24064  6月 14 14:34 hello.tar
(base) pang@pang-HP:~/dockerfile$ 

这里的filename可以为任意名称甚至任意后缀名,但文件的本质都是归档文件。

注意:如果同名则会覆盖(没有警告)

若使用gzip压缩:

(base) pang@pang-HP:~/dockerfile$ sudo docker save hello-world | gzip >hello.tar.gz
(base) pang@pang-HP:~/dockerfile$ ll
总用量 40
drwxrwxr-x  2 pang pang  4096  6月 14 14:37 ./
drwxr-x--- 72 pang pang  4096  6月 14 14:23 ../
-rw-rw-r--  1 pang pang   204  6月 14 14:23 Dockerfile
-rw-------  1 root root 24064  6月 14 14:34 hello.tar
-rw-rw-r--  1 pang pang  3523  6月 14 14:37 hello.tar.gz
(base) pang@pang-HP:~/dockerfile$ 

6.2 导入镜像

可以使用 docker [image] load 将导出的 tar 文件再导人到本地镜像库。支持 - Linput string 选项,从指定文件中读人镜像内容。

从文件hello.tar导人镜像到本地镜像列表,如下所示:

$ docker load -i hello.tar

或者:

$ docker load < hello.tar

这将导人镜像及其相关的元数据信息(包括标签等)。 导人成功后,可以使用docker images命令进行查看,与原镜像一致。

结合这两个命令以及ssh甚至pv的话,利用Linux强大的管道,我们可以写一个命令完成从一个机器将镜像迁移到另一个机器,并且带进度条的功能:

docker save <镜像名> | bzip2 | pv | ssh <用户名>@<主机名> 'cat | docker load'

7 上传镜像

可以使用docker push命令上传镜像到仓库,默认上传到DockerHub官方仓库(需要登录)。命令格式为:

docker push NAME [:TAG] | [REGISTRY_HOST [:REGISTRY_PORT]/]NAME[:TAG]

用户在Docker Hub网站注册后可以上传自制的镜像 。

例如,用户user上传本地的test:latest镜像,可以先添加新的标签user/test:latest, 然后用docker [image ] push命令上传镜像 :

$ docker tag test:latest user/test : latest
$ docker push user/test:latest
The push refers to a repository [docker.io/user/test]
Sending image list
Please login prior to push:
Username:
Password:
Email :

第一次上传时,会提示输入登录信息或进行注册,之后登录信息会记录到本地~/.docker目录下。

8 实现原理

Docker 镜像是怎么实现增量的修改和维护的?

每个镜像都由很多层次构成,Docker使用Union FS将这些不同的层结合到一个镜像中去。通常Union FS有两个用途, 一方面可以实现不借助LVM、RAID将多个disk挂到同一个目录下,另一个更常用的就是将一个只读的分支和一个可写的分支联合在一起,Live CD正是基于此方法可以允许在镜像不变的基础上允许用户在其上进行一些写操作。

Docker在OverlayFS上构建的容器也是利用了类似的原理。

 类似资料: