docker 镜像

一、介绍

镜像(Image)可以理解为是一个只读的文件包,其中包含了虚拟环境运行最原始文件系统的内容。但是 Docker 的镜像与虚拟机中的镜像还是有一定区别的。Docker 通过实现 AUFS 了一种增量式的镜像结构,这样做的好处是:每次对镜像内容的修改,Docker 都会将这些修改铸造成一个镜像层,而一个镜像其实就是由其下层所有的镜像层所组成的。当然,每一个镜像层单独拿出来,与它之下的镜像层都可以组成一个镜像。由于这种结构,Docker 的镜像实质上是无法被修改的,因为所有对镜像的修改只会产生新的镜像,而不是更新原有的镜像。

二、镜像打包

与其他虚拟机的镜像管理不同,Docker 将镜像管理纳入到了自身设计之中,也就是说,所有的 Docker 镜像都是按照 Docker 所设定的逻辑打包的,也是受到 Docker Engine 所控制的。

普通的虚拟机镜像,是由发布者用自己的方式打包成镜像文件,而使用则是从网络上下载后回复到虚拟机里面;而 Docker 的镜像必须通过 Docker 来打包,也必须通过 Docker 下载或导入后使用,不能单独直接恢复成容器中的文件系统。

虽然 Docker 镜像的这种打包方式失去了很多灵活性,但是其固定的格式可以在不同的服务器间轻松的传递 Docker 镜像,配合 Docker 自身对镜像的管理功能,在不同的机器中传递和共享 Docker 变得非常方便。

三、镜像id

对于每一个记录文件系统修改的镜像层来说,Docker 都会根据它们的信息生成了一个 Hash 码,这是一个 64 长度的字符串,足以保证全球唯一性,这种编码的形式在 Docker 很多地方都有体现。

由于镜像层都有唯一的编码,那么就能够区分不同的镜像层并能保证它们的内容与编码是一致的,这带来了另一个好处,就是可以在镜像之间共享镜像层。

比如说:Docker 官方提供的镜像 elasticsearch 镜像和 jenkins 镜像都是在 openjdk 镜像之上修改而得,那么在实际使用的时候,这两个镜像是可以共用 openjdk 镜像内部的镜像层的。这带来好处就是让镜像可以共用一些存储空间,达到 1 + 1 < 2 的效果,使得在同一台机器里存放众多镜像提供了可能。

四、查看镜像

镜像是由 Docker 进行管理的,所以它的存储位置和存储方式等并不需要过多的关心,只需要利用 Docker 所提供的一些接口或命令对它们进行控制即可。

如果要查看当前连接的 docker daemon 中存放和管理了哪些镜像,可以使用命令 docker images 来查看:

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
rabbitmq                 3-management        d6558098d04c        2 months ago        177MB
openzipkin/zipkin        latest              b4a4e6e796ee        2 months ago        253MB
wurstmeister/kafka       latest              988f4a6ca13c        4 months ago        421MB
kibana                   7.1.0               714b175e84e8        6 months ago        745MB
elasticsearch            7.1.0               12ad640a1ec0        6 months ago        894MB
wurstmeister/zookeeper   latest              3f43f72cb283        10 months ago       510MB
hello-world              latest              fce289e99eb9        11 months ago       1.84kB

docker images 命令返回的结果中,可以看到镜像ID(IMAGE ID)、构建时间(CREATED)、占用空间(SIZE)等数据。

注意:结果中镜像ID的长度只有12个字符,这和前面说的 64 个字符貌似不一致。其实为了避免屏幕的空间都被太长的镜像 ID 占满,所以 Docker 只显示了镜像 ID 的前 12 个字符,大部分情况下,镜像 ID 的前 12 个字符已经能够让在单一主机中识别出不同的镜像了。

目前不能通过命令行获取镜像在远程仓库中的版本,如果需要获取镜像版本,需要到 docker hub : https://hub.docker.com/ 中查看:

docker 镜像_第1张图片

五、镜像命名

镜像层的 ID 既可以识别每个镜像层,也可以用来直接识别镜像(因为根据最上层镜像能够找出所有依赖的下层镜像,所以最上层进行的镜像层 ID 就能表示镜像的 ID),但是使用这种无意义的超长哈希码显然是违背人性的,所以这里还要介绍镜像的命名,通过镜像名能够更容易的识别镜像。

在 docker images 命令打印出的内容中,有两个与镜像命名有关的数据:REPOSITORY 和 TAG,这两者其实就组成了 docker 对镜像的命名规则。

比如对于前面的 kafka image:

REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
wurstmeister/kafka       latest              988f4a6ca13c        4 months ago        421MB

这个镜像的命名可以分成三个部分:username、repository 和 tag。

  1. username:(REPOSITORY 中斜杠前面部分 wurstmeister)主要用于识别上传镜像的不同用户,与 GitHub 中的用户空间类似。
  2. repository:(REPOSITORY 中斜杠后面部分 kafka)主要用于识别进行的内容,形成对镜像的表意描述。
  3. tag:主要用户表示镜像的版本,方便区分进行内容的不同细节

对于 username 来说,在命令 docker images 的返回结果中,有的镜像有 username 这个部分,而有的镜像是没有的。没有 username 这个部分的镜像,表示镜像是由 Docker 官方所维护和提供的,所以就不单独标记用户了。

而 repository 部分通常采用的是软件名,但是镜像还是镜像,镜像名还是镜像名,其与软件命名其实是独立的。

Docker 中还有一个约定,当在操作中没有具体给出镜像的 tag 时,Docker 会采用 latest 作为缺省 tag。这也就带来了一个共识,也就是绝大多数镜像提供者在提供镜像时,会在 latest 对应的镜像中包含软件最新的版本。这带来了一项小便利,在不需要了解应用程序迭代周期的情况下,可以利用 latest 镜像保持软件最新版本的使用。

六、镜像仓库

在一些编程语言中,都会有统一的依赖包管理,如 java 的 maven,node.js 的 npm等,这些管理工具后面,都至少有一个依赖仓库。

docker 也有镜像仓库,其最大的作用是实现了 Docker 镜像的分发。借助镜像仓库,可以得到一个镜像的中转站,将开发环境上所使用的镜像推送至镜像仓库,并在测试或生产环境上拉取到它们,而这个过程仅需要几个命令,甚至自动化完成。

Docker 官方建立了中央镜像仓库 : Docker Hub ,Docker Hub 除了普通镜像仓库的功能外,它内部还有更加细致的权限管理,支持构建钩子和自动构建,还有一套 Web 操作页面。

七、镜像管理

1、从仓库搜索镜像

可以在界面输入命令行搜索镜像,也可以在命令行输入 : docker search 镜像名 搜索镜像。

$ docker search nginx
NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                             Official build of Nginx.                        12280               [OK]                
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker con…   1696                                    [OK]
richarvey/nginx-php-fpm           Container running Nginx + PHP-FPM capable of…   747                                     [OK]
linuxserver/nginx                 An Nginx container, brought to you by LinuxS…   82                                      
bitnami/nginx                     Bitnami nginx Docker Image                      73                                      [OK]
tiangolo/nginx-rtmp               Docker image with Nginx using the nginx-rtmp…   60                                      [OK]
nginxdemos/hello                  NGINX webserver that serves a simple page co…   33                                      [OK]
jc21/nginx-proxy-manager          Docker container for managing Nginx proxy ho…   31                                      
jlesage/nginx-proxy-manager       Docker container for Nginx Proxy Manager        29                                      [OK]
nginx/nginx-ingress               NGINX Ingress Controller for Kubernetes         22                                      
privatebin/nginx-fpm-alpine       PrivateBin running on an Nginx, php-fpm & Al…   19                                      [OK]
schmunk42/nginx-redirect          A very simple container to redirect HTTP tra…   17                                      [OK]
blacklabelops/nginx               Dockerized Nginx Reverse Proxy Server.          12                                      [OK]
centos/nginx-18-centos7           Platform for running nginx 1.8 or building n…   12                                      
nginxinc/nginx-unprivileged       Unprivileged NGINX Dockerfiles                  11                                      
centos/nginx-112-centos7          Platform for running nginx 1.12 or building …   10                                      
nginx/nginx-prometheus-exporter   NGINX Prometheus Exporter                       9                                       
webdevops/nginx                   Nginx container                                 8                                       [OK]
sophos/nginx-vts-exporter         Simple server that scrapes Nginx vts stats a…   5                                       [OK]
1science/nginx                    Nginx Docker images that include Consul Temp…   5                                       [OK]
mailu/nginx                       Mailu nginx frontend                            5                                       [OK]
pebbletech/nginx-proxy            nginx-proxy sets up a container running ngin…   2                                       [OK]
ansibleplaybookbundle/nginx-apb   An APB to deploy NGINX                          1                                       [OK]
wodby/nginx                       Generic nginx                                   0                                       [OK]
centos/nginx-110-centos7          Platform for running nginx 1.10 or building …   0                                       

其中,OFFICIAL 代表镜像为 Docker 官方提供和维护,相对来说稳定性和安全性较高。STARS 代表镜像的关注人数,这类似 GitHub 的 Stars,可以理解为热度。

2、从仓库拉取镜像

可以使用 docker pull 命令拉取镜像,命令的参数就是前面的镜像仓库名。

sudo docker pull mongo
Using default tag: latest
latest: Pulling from library/mongo
7ddbc47eeb70: Pull complete 
c1bbdc448b72: Pull complete 
8c3b70e39044: Pull complete 
45d437916d57: Pull complete 
e119fb0e0a55: Pull complete 
91f0b9bae1ea: Pull complete 
53e7c2967f11: Pull complete 
69a945568374: Pull complete 
93333bc225a7: Pull complete 
b9c10bd6c9bd: Pull complete 
7f4e3538e99c: Downloading [==================================>                ]  72.45MB/111.8MB
1164b51d180a: Download complete 
a715a7d71f27: Download complete 

在控制台中,可以看到镜像拉取的进度。下载进度会分为几行,其实每一行代表的就是一个镜像层。Docker 首先会拉取镜像所基于的所有镜像层,之后再单独拉取每一个镜像层并组合成这个镜像。如果在本地已经存在相同的镜像层(共享于其他的镜像),Docker 就直接略过这个镜像层的拉取而直接采用本地的内容。

在获取镜像时没有提供镜像标签,Docker 会默认使用 latest 这个标签,使用完整的镜像命名来拉取镜像如下:

$ sudo docker pull openzipkin/zipkin:2.19
2.19: Pulling from openzipkin/zipkin
9ff2acc3204b: Pull complete 
69e2f037cdb3: Pull complete 
0ab175cd7cdc: Pull complete 
3e010093287c: Pull complete 
4a63134ba470: Pull complete 
8f250d77eb0d: Pull complete 
05b9d3576e9f: Pull complete 
ef0fec9b6120: Pull complete 
07f5eb79ad62: Pull complete 
ee88f81d121c: Pull complete 
b8887dc36c2b: Pull complete 
97a2c104c0b4: Pull complete 
Digest: sha256:87fe01472af81fb7e25d2a79eddda7b50bc450b7116b5fabafb4e6f6c66c802f
Status: Downloaded newer image for openzipkin/zipkin:2.19
docker.io/openzipkin/zipkin:2.19

3、查看已经拉取的镜像列表

镜像拉取完成后,可以通过命令 docker images 来查看已经拉取的镜像列表。

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
rabbitmq                 3-management        d6558098d04c        2 months ago        177MB
openzipkin/zipkin        latest              b4a4e6e796ee        2 months ago        253MB
wurstmeister/kafka       latest              988f4a6ca13c        4 months ago        421MB
kibana                   7.1.0               714b175e84e8        6 months ago        745MB
elasticsearch            7.1.0               12ad640a1ec0        6 months ago        894MB
wurstmeister/zookeeper   latest              3f43f72cb283        10 months ago       510MB
hello-world              latest              fce289e99eb9        11 months ago       1.84kB

4、查看已拉取镜像详细信息

可以通过命令 docker inspect 查看已拉取镜像详细信息,比如:

docker inspect openzipkin/zipkin:2.19

docker inspect 的参数除了容器的名称,还可以是镜像id或者容器id。

docker inspect 参数识别

通过镜像名或者镜像ID传递到 docker inspect 或者其他类似的命令(需要指定Docker对象的命令)里,Docker 都会根据传入的内容去寻找与之匹配的内容,只要传入的内容能够找出唯一的镜像,Docker 就会对这个镜像执行给定的操作。如果找不到唯一的镜像,那么操作不会进行,Docker 也会显示错误。

也就是说,只要传入能够唯一识别镜像或容器的信息,即使它短到只有1个字符,Docker 都是可以处理的。

如下:

$ docker images
REPOSITORY               TAG                 IMAGE ID            CREATED             SIZE
rabbitmq                 latest              72469b528c2d        10 days ago         150MB
openzipkin/zipkin        2.19                12ee1ce53834        13 days ago         157MB
rabbitmq                 3-management        d6558098d04c        2 months ago        177MB
openzipkin/zipkin        latest              b4a4e6e796ee        2 months ago        253MB
wurstmeister/kafka       latest              988f4a6ca13c        4 months ago        421MB
kibana                   7.1.0               714b175e84e8        6 months ago        745MB
elasticsearch            7.1.0               12ad640a1ec0        6 months ago        894MB
wurstmeister/zookeeper   latest              3f43f72cb283        10 months ago       510MB
hello-world              latest              fce289e99eb9        11 months ago       1.84kB

# IMAGE ID 前缀为 7 的有两个, 查询 7 会返回错误
$ docker inspect 7
[]
Error response from daemon: Multiple IDs found with provided prefix: 7

# 3 开头的 id 只有一个,运行如下
docker inspect 3
[
    {
        "Id": "sha256:3f43f72cb2832e7a5fbed7f7dbcd0c43004357974d8f32555d101bd53e81e74f",
        "RepoTags": [
            "wurstmeister/zookeeper:latest"
        ],
        "RepoDigests": [
            "wurstmeister/zoo
......................

如图:

docker 镜像_第2张图片

5、本地的 Docker Engine 中移除镜像

可以使用命令 docker rmi 移除本地的镜像,参数是镜像名或者镜像id。

$ sudo docker rmi rabbitmq
Untagged: rabbitmq:latest
Untagged: rabbitmq@sha256:3c0ebabfb9e8b53b18d4ee060019718f47df17dc4a333f1ae1715963216216bd
Deleted: sha256:72469b528c2d9030a1bc3b856c74bda2ba20102243959f5d56fdd90f1feb567a
Deleted: sha256:31961c9940cf1337da82b685c03851d2e9f1c61354be86a3405eddc14142a6d7
Deleted: sha256:3395fce986f2b2181272d43e8d41392540d9d79ad568563b6abec52567b48626
Deleted: sha256:8e3f24605824056f5eca2737711fa84b13ca03e0ef63166c8f7a460b221bdc2a
Deleted: sha256:77c0c1c577c10652620a84a00c287cbc285a847af7e98cda5c8be1405a6d70aa
Deleted: sha256:5d40e9049495908930f2c42beaef612c3fbdccaf232b64c86e57fc0d3c36cbaa
Deleted: sha256:5948e2c971ab5c3c297f781986fcfbbf0a2175d6900c6ec40380fbb08fbcbed5
Deleted: sha256:4fc26b0b0c6903db3b4fe96856034a1bd9411ed963a96c1bc8f03f18ee92ac2a
Deleted: sha256:b53837dafdd21f67e607ae642ce49d326b0c30b39734b6710c682a50a9f932bf
Deleted: sha256:565879c6effe6a013e0b2e492f182b40049f1c083fc582ef61e49a98dca23f7e
Deleted: sha256:cc967c529ced563b7746b663d98248bc571afdb3c012019d7f54d6c092793b8b

删除镜像其实就是删除镜像内的镜像层,在删除镜像命令打印的结果里,可以看到被删除的镜像层以及它们的ID。如果存在两个镜像共用一个镜像层的情况,Docker 是不会删除被共享的那部分镜像层,只有当镜像层只被当前被删除的镜像所引用时,Docker 才会将它们从硬盘空间中移除。

docker rmi 命令也支持同时删除多个镜像,只需要通过空格传递多个镜像 ID 或镜像名即可。

$ sudo docker rmi -f kibana:7.1.0 elasticsearch:7.1.0 
Untagged: kibana:7.1.0
Untagged: kibana@sha256:7a60259ea48715842d88e262cbf58ccc9f847997faf6babda55338a562bcee61
Deleted: sha256:714b175e84e8fa91ceed8b802980efb4017fa75359599cd2b63c87bbc26efe77
Untagged: elasticsearch:7.1.0
Untagged: elasticsearch@sha256:f449aeab752587709b440a9cb9b35ed93bfabdab75fb8ae9e0b330aa0e584a51
Deleted: sha256:12ad640a1ec0484ee7eac455e6b924fb01a1fc88ca01d5a6d90cfa7554ab4568

注意在镜像时可能出现以下错误:

Error response from daemon: conflict: unable to remove repository reference "xxxxxxx" (must force) - container 766113c852d4 is using its referenced image fce289e99eb9

由于 container 依赖该镜像,所以无法删除。处理办法:

1、删除引用容器

使用 sudo docker stop xxx 停止容器,然后使用 sudo docker rm xxx 删除容器,最后使用 sudo docker rmi 镜像名或镜像id 删除镜像即可,如下:

docker 镜像_第3张图片

上面可以使用 docker stop $(docker ps -a -q) 停止所有的container,使用 docker rm $(docker ps -a -q) 删除所有container。

2、强制删除

在命令中加 -f 参数强制删除镜像:sudo docker rmi -f xxx

docker 镜像_第4张图片

你可能感兴趣的:(docker)