Docker笔记(四):Docker镜像管理

原文地址:http://blog.jboost.cn/docker-4.htmlphp

 

在Docker中,应用是经过容器来运行的,而容器的运行是基于镜像的,相似面向对象设计中类与对象的关系——没有类的定义就谈不上实例的建立与使用,没有镜像的定义就谈不上容器的建立与运行。

html

1. 获取镜像

镜像从哪里来,通常两个途径,一是公共镜像库,如官方镜像库Docker Hub,上面有大量的高质量的镜像直接可拿来用;二是自定义,咱们可基于一个已有镜像,在其基础上增长一些层(还记得镜像的分层存储特性吧),而后构建造成本身的镜像。mysql

若是咱们知道某个镜像的名称,则可直接经过docker pull来下载镜像到本地,如ubuntu、redis、nginx等,docker pull命令的格式以下(中括号表示可有可没有)linux

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

 

其中选项可设置: nginx

  • -a, –all-tags:下载仓库中全部标签(通常指版本)的镜像
  • –disable-content-trust:跳过镜像验证,默认为true

Docker Registry的地址即镜像仓库地址,通常为域名或IP加端口号,若是不指定则默认为Docker Hub;仓库名包含两部分,<用户名>/<软件名>,对于Docker Hub,若是不给出用户名,则默认为library,表示官方提供;标签通常是对应软件的版本号,若是不指定则默认为latest。web

好比咱们要下一个nginx镜像,则可执行以下命令redis

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker pull nginx
Using default tag: latest
latest: Pulling from library/nginx
fc7181108d40: Already exists 
d2e987ca2267: Pull complete 
0b760b431b11: Pull complete 
Digest: sha256:48cbeee0cb0a3b5e885e36222f969e0a2f41819a68e07aeb6631ca7cb356fed1
Status: Downloaded newer image for nginx:latest

这里咱们没有指定选项,也没有指定镜像仓库地址,那么默认会从Docker Hub获取镜像(但Docker Hub因为在国外,速度比较慢,因此通常要设置国内加速器,参考Docker笔记(三):Docker安装与配置第二部分:配置国内镜像),也没有给出用户名,因此默认是library(第三行),没有指定标签,因此默认是latest(第二行),由第四至第六行可见,这个镜像包含三个层,而且第一个层已经存在了(以前下载的镜像已经包含了这个层, 直接复用),镜像分层的概念及层的复用,应该已经理解了。sql

 

若是咱们不知道镜像的完整名称怎么办,那就搜索一下,有两个途径,一是经过命令,假设咱们记不起nginx全称了, 只记得ngi,则可经过以下命令搜索docker

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker search ngi
NAME                              DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
nginx                             Official build of Nginx.                        11693               [OK]                
jwilder/nginx-proxy               Automated Nginx reverse proxy for docker con…   1628                                    [OK]
richarvey/nginx-php-fpm           Container running Nginx + PHP-FPM capable of…   726                                     [OK]
bitnami/nginx                     Bitnami nginx Docker Image                      69                                      [OK]
linuxserver/nginx                 An Nginx container, brought to you by LinuxS…   69                                      
tiangolo/nginx-rtmp               Docker image with Nginx using the nginx-rtmp…   48                                      [OK]
nginx/nginx-ingress               NGINX Ingress Controller for Kubernetes         20                                      
nginxdemos/hello                  NGINX webserver that serves a simple page co…   18                                      [OK]
jlesage/nginx-proxy-manager       Docker container for Nginx Proxy Manager        17                                      [OK]
schmunk42/nginx-redirect          A very simple container to redirect HTTP tra…   17                                      [OK]
crunchgeek/nginx-pagespeed        Nginx with PageSpeed + GEO IP + VTS + more_s…   13                                      
blacklabelops/nginx               Dockerized Nginx Reverse Proxy Server.          12                                      [OK]
...

该命令会从Docker Hub搜索镜像名包含ngi的镜像,其中STARS表示收藏用户数,OFFICIAL为[OK]表示官方提供的镜像,AUTOMATED [OK]表示由自动构建生成,通常选择STARS最多,官方提供的镜像。 ubuntu

这种方式获取到的信息有限,好比具体包含哪些版本不知道。还有一个途径是直接在Docker Hub网站上搜索,打开 https://hub.docker.com , 在搜索框输入ngi,以下图

docker-hub

 

则会列出全部知足条件的镜像,点开nginx结果连接,能够看到提供的版本(经过版本连接能够查看定义对应镜像的Dockerfile),及相应的文档说明。这种方式获取的信息更加全面,因此推荐这种方式!

 

另外,当咱们没有执行docker pull,直接经过docker run xx来运行一个容器时,若是没有对应的镜像,则会先自动下载镜像,再基于镜像启动一个容器,好比咱们在Docker笔记(三):Docker安装与配置中检验docker是否安装成功时运行的hello-world
hello-docker

 

2. 管理本地镜像

将镜像下载到本地后,咱们能够基于镜像来建立、运行容器,及对镜像进行管理。

查看本地镜像

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker image ls
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
nginx               latest              f68d6e55e065        2 weeks ago         109MB
mysql               latest              c7109f74d339        5 weeks ago         443MB
hello-world         latest              fce289e99eb9        6 months ago        1.84kB

上面各列依次列出了镜像名称、标签(版本)、镜像ID、建立时间、镜像大小。镜像能够拥有多个标签(版本)。镜像的大小总和通常要大于实际的磁盘占有量,为何?回忆一下镜像的分层存储概念,层是能够复用的,某个层其中一个镜像有了,另外一个镜像就不会再下载了。口说无凭,咱们来验证下,docker system df可列出镜像、容器、数据卷所占用的空间

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker system df
TYPE                TOTAL               ACTIVE              SIZE                RECLAIMABLE
Images              3                   1                   497.1MB             497.1MB (99%)
Containers          1                   0                   0B                  0B
Local Volumes       0                   0                   0B                  0B
Build Cache         0                   0                   0B                  0B

经过docker image ls列出的各镜像大小总共约552MB,但这里列出的镜像大小只有约497MB,这下有凭有据了吧。

 

根据条件列出镜像

docker image ls nginx # 根据名称列出镜像
docker image ls nginx:latest # 根据名称与标签列出镜像
docker image ls -f since=hello-world:latest # -f 是--filter的缩写,过滤器参数,列出在hello-world:latest以后创建的镜像,before=hello-world:latest则查看以前创建的镜像

 

指定显示格式 

docker image ls -q # 只显示镜像ID
docker image ls --digests # 列出镜像摘要

docker image ls --format "{{.ID}}: {{.Repository}}"  # 使用Go的模板语法格式化显示,这里显示格式为 镜像ID:镜像名称
docker image ls --format "table {{.ID}}\t{{.Repository}}\t{{.Tag}}" # 本身定义表格格式

 

虚悬镜像 

有时候会看到某些镜像既没有仓库名,也没有标签,均为 <none>。这些镜像本来是有镜像名和标签的,随着官方镜像维护,发布了新版本后(新版本会复用以前的镜像名称与标签,通常是bug修复版),从新docker pull xx 时, 这个镜像名被转移到了新下载的镜像身上,而旧的镜像上的这个名称则被取消,从而成为了<none> 。除了docker pull可能致使这种状况, docker build也一样能够致使这种现象。因为新旧镜像同名,旧镜像名称被取消,从而出现仓库名、标签均为 <none> 的镜像。这类无标签镜像被称为虚悬镜像(dangling image) ,能够用下面的命令专门显示这类镜像:

docker image ls -f dangling=true

通常虚悬镜像没什么意义了,能够经过以下命令删除 

docker image prune

 

中间层镜像 

为了加速镜像构建、重复利用资源,Docker会利用中间层镜像。因此在使用一段时间后,可能会看到一些依赖的中间层镜像。默认的docker image ls列表中只会显示顶层镜像,若是但愿显示包括中间层镜像在内的全部镜像的话,能够加 -a

$ docker image ls -a

这样会看到不少无标签的镜像,与虚悬镜像不一样,这些无标签的镜像不少都是中间层镜像,是其它镜像所依赖的镜像。这些无标签镜像不该该删除,不然会致使上层镜像由于依赖丢失而出错。实际上,这些镜像也不必删除,由于相同的层只会存一遍,而这些镜像是别的镜像的依赖,所以并不会由于它们被列出来而多存了一份,不管如何你也会须要它们。只要删除那些依赖它们的镜像后,这些依赖的中间层镜像也会被连带删除。 

 

删除镜像
删除镜像命令格式

docker image rm [选项] <镜像1> [<镜像2> ...]

选项能够设置: 

  • -f, –force 强制删除镜像
  • –no-prune 不删除没有标签的父镜像

<镜像1>、<镜像2> 等能够是镜像的名称,镜像的全ID,也能够是镜像ID的前面几个数字(只要与其它镜像区分开来就行),或者是镜像摘要。 如删除镜像名称为mysql的镜像

[root@iZwz9dbodbaqxj1gxhpnjxZ ~]# docker image rm mysql
Untagged: mysql:latest
Untagged: mysql@sha256:415ac63da0ae6725d5aefc9669a1c02f39a00c574fdbc478dfd08db1e97c8f1b
Deleted: sha256:c7109f74d339896c8e1a7526224f10a3197e7baf674ff03acbab387aa027882a
Deleted: sha256:35d60530f024aa75c91a123a69099f7f6eaf5ad7001bb983f427f674980d8482
Deleted: sha256:49d8bb533eee600076e3a513a203ee24044673fcef0c1b79e088b2ba43db2c17
...

由上面命令的执行结果可见,删除镜像包括另个行为:UntaggedDeleted。 

当咱们使用上面命令来删除镜像的时候,其实是在要求删除某个/某些标签的镜像。因此首先须要作的是将知足要求的全部镜像标签都取消,这就是Untagged的行为。一个镜像能够对应多个标签,所以当咱们删除了所指定的标签后,可能还有别的标签指向了这个镜像,若是是这种状况,那么Delete行为就不会发生,仅仅是取消了这个镜像的符合要求的全部标签。因此并不是全部的docker image rm都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。

当该镜像全部的标签都被取消了,该镜像极可能就失去了存在的意义,所以会触发删除行为。镜像是多层存储结构,所以在删除的时候也是从上层向基础层方向依次进行判断删除。若是某个其它镜像正依赖于当前镜像的某一层,这种状况,依旧不会触发删除该层的行为。直到没有任何镜像依赖当前层时,才会真实的删除当前层。

另外还须要注意是容器对镜像的依赖。若是基于镜像启动的容器存在(即便容器没有运行处于中止状态) ,一样不能够删除这个镜像。咱们以前说了容器是以镜像为基础,再加一层容器存储层组成的多层存储结构去运行的。因此若是这些容器是不须要的,应该先将它们删除,而后再来删除镜像。

 

经过组合命令来删除

docker image rm $(docker image ls -q nginx) # 删除镜像名称为nginx的全部镜像
docker image rm $(docker image ls -q -f since=hello-world:latest) # 删除全部在hello-world:latest以后创建的镜像

 

3. 总结 

本文对镜像的获取及本地镜像的基本管理作了介绍,本文镜像的获取途径都是从镜像仓库直接获取,镜像的另外一个获取途径即是自定义,接下来会经过实例来进行介绍,欢迎关注。


个人我的博客地址:http://blog.jboost.cn
个人微信公众号:jboost-ksxy (一个不仅有技术干货的公众号,欢迎关注,及时获取更新内容)
———————————————————————————————————————————————————————————
微信公众号

相关文章
相关标签/搜索