欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

docker 镜像

程序员文章站 2022-03-05 22:12:43
...

一、介绍

镜像(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 镜像

五、镜像命名

镜像层的 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 镜像

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

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

$ sudo docker rmi rabbitmq
Untagged: rabbitmq:latest
Untagged: aaa@qq.com: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: aaa@qq.com:7a60259ea48715842d88e262cbf58ccc9f847997faf6babda55338a562bcee61
Deleted: sha256:714b175e84e8fa91ceed8b802980efb4017fa75359599cd2b63c87bbc26efe77
Untagged: elasticsearch:7.1.0
Untagged: aaa@qq.com: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 镜像

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

2、强制删除

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

docker 镜像

相关标签: docker