理解Docker镜像

理解Docker镜像

Docker image概念介绍

简单来说,Docker image是用来启动容器的只读模板,是容器启动所需要的rootfs,类似于虚拟机所使用的镜像。首先需要通过一定的规则和方法Docker image。

Remote-dockerhub.com/namespace/bar:latest

Docker镜像的表示方式,可以看到其被’/'分成三个部分,其中每部分都可以类比Github中的概念。

  • Remote docker hub:集中存储镜像的Web服务器地址。该部分的存在使得可以区分从不同镜像库中拉取的镜像。若Docker的镜像表示中缺少该部分,说明使用的是默认镜像库,即Docker官方镜像库。
  • Namespace:类似于Github中的命名空间,是一个用户或组织中所有镜像的集合。
  • Repository:类似于Git仓库,一个仓库可以有多个镜像,不同镜像通过tag来区分。
  • Tag:类似Git仓库中的tag,一般用来区分同一类镜像的不同版本。
  • Layer:镜像由一系列层组成,每层都用64位的十六进制数表示,非常类似于Git仓库中的commit。
  • Image ID:镜像最上层的layer ID就是该镜像的ID,Repo:tag提供了易于人类识别的名字,而ID便于脚本处理、操作镜像。
    镜像库是Docker公司最先提出的概念,非常类似应用市场的概念。用户可以发布自己的镜像,也可以使用别人的镜像。Docker开源了镜像存储部分的源代码(Docker Registry以及Distribution),但是这些开源组件并不适合独立地发挥功能,需要使用Nginx等代理工具添加基本的鉴权功能,才能搭建出私有镜像仓库。本地镜像则是已经下载到本地的镜像,可以使用docker images等命令进行管理。这些镜像默认存储在/var/lib/docker路径下,该路径也可以使用docker daemon -g参数在Daemon时指定。

使用Docker image

Docker内嵌了一系列命令制作、管理、上传和下载镜像。可以调用REST API给Docker daemon发送相关命令,也可以使用client端提供的CLI命令完成操作。

列出本机的镜像

docker images

在这里插入图片描述
其中,--filter用于过滤docker images的结果,过滤器采用key=value的这种形式。目前支持的过滤器为dangling和label。--filter "dangling=true"会显示所有’悬挂’镜像。‘悬挂’镜像没有对应的名称和tag,并且其最上层不会被任何镜像所依赖。docker commit在一些情况下会产生这种’悬挂’镜像。下面第一条命令产生了一个悬挂镜像,第二条命令根据其特点过滤出该镜像了。
在这里插入图片描述
在上面的命令中,–no-trunc参数可以列出完整长度的image ID。若添加参数-q则会只输出Image ID,该参数在管道命令中很有用处。一般来说悬挂镜像并不总是我们所需要的,并且会浪费磁盘空间。可以使用如下命令删除所有悬挂镜像。

docker images --filter "dangling=true" -q | xargs docker rmi

在这里插入图片描述
Docker只会保留最核心的image相关命令和功能,因此哪些非核心功能就会被删除。比如–tree和–dot已经从Docker1.7中删除。官方推荐使用dockerviz工具分析Docker image。
安装dockerviz

wget https://github.com/justone/dockviz/releases/download/v0.6.0/dockviz_linux_amd64 -O /usr/bin/dockviz

chmod +x /usr/bin/dock

树状图

 dockviz images -t

在这里插入图片描述

Build:创建一个镜像

创建镜像是一个很常用的功能,即可以从无到有地创建镜像,也可以以现有的镜像为基础进行增量开发,还可以把容器保存为镜像。
1、直接下载镜像
我们可以从镜像仓库下载一个镜像,比如,以下为下载busybox镜像的实例。

docker pull busybox

在这里插入图片描述
2、导入镜像
还可以导入一个镜像,对此,Docker提供了两个可用的命令docker import和docker load。docker load一般只用于导入由docker save导出的镜像,导入后的镜像跟原镜像完全一样,包括拥有相同的镜像ID和分层等内容。下面的第一行命令可以导出busybox为busybox.tar,第二条命令则是导入该镜像。

docker save -o busybox.tar busybox
docker load -i busybox.tar 

在这里插入图片描述
不同于docker load,docker import不能用于导入标准的Docker 镜像,而是用于导入包含跟文件系统的归档,并将之变成Docker镜像。
3、制作新的镜像
前面说过,docker import用于导入包括跟文件系统的归档,并将之变成Docker镜像。因此,docker import常用来制作Docker基础镜像。与此相对,docker export则是把一个镜像导出为根文件系统的归档。
Docker提供的docker commit命令可以增量地生成一个镜像,该命令可把容器保存为一个镜像,还能注明作者信息和镜像名称,这与git commit类似。当镜像命令为空时,就会形成"悬挂"镜像。当然,使用这种方式每新增加一层都需要数个步骤(比如,启动容器、修改、保存修改等),所以效率是比较低的,因此这种方式适合正式制作镜像前的舱室,当最终确定制作步骤后,可以使用docker build,通过Dockerfile文件生成镜像。

Ship:传输一个镜像

镜像传输是连接开发和部署的桥梁。可以使用Docker镜像仓库做中转传输,还可以使用docker export/docker save生成的tar包来实现,或者使用Docker镜像的模板文件Dockerfile做间接传输。

Run:以image为模板启动一个容器

启动容器时,可以使用docker run命令。

Docker image的组织结构

数据的内容

Docker image包含着数据及必要的元数据。数据由一层层的image layer组成,元数据则是一些JSON文件,用来描述数据之间的关系以及容器的一些配置信息。下面使用overlay存储驱动对Docker image的组织结构进行分析,首先需要启动Docker daemon

docker daemon -D -s overlay -g /var/lib/docker

下载busybox用作分析,由于前面已经下载过了,所以这里并没有重新下载,而只是做了简单的校验。可以看到Docker对镜像进行了完整性检验,这种完整性凭证是由镜像仓库提供的。

docker pull busybox

在这里插入图片描述

docker history busybox

在这里插入图片描述

数据的组织

 docker inspect busybox
[
    {
        "Id": "sha256:7138284460ffa3bb6ee087344f5b051468b3f8697e2d1427bac1a20c8d168b14",
        "RepoTags": [
            "busybox:latest"
        ],
        "RepoDigests": [
            "busybox@sha256:e7157b6d7ebbe2cce5eaa8cfe8aa4fa82d173999b9f90a9ec42e57323546c353"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-11-11T19:19:37.862545075Z",
        "Container": "8afe392526b6fa99a3498001c95812b187123968e5a14802c9e837e1cd06d02b",
        "ContainerConfig": {
            "Hostname": "8afe392526b6",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"sh\"]"
            ],
            "Image": "sha256:d39a5c18a94ca076b3f9fad5b104d1b5555697280b61cbabd1eec6d89908b1b6",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "20.10.7",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "sh"
            ],
            "Image": "sha256:d39a5c18a94ca076b3f9fad5b104d1b5555697280b61cbabd1eec6d89908b1b6",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 1239828,
        "VirtualSize": 1239828,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/0dc6a08c999348a3846199f15431a21624b766eb60377fd5aa41cf166e61abd9/merged",
                "UpperDir": "/var/lib/docker/overlay2/0dc6a08c999348a3846199f15431a21624b766eb60377fd5aa41cf166e61abd9/diff",
                "WorkDir": "/var/lib/docker/overlay2/0dc6a08c999348a3846199f15431a21624b766eb60377fd5aa41cf166e61abd9/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:d94c78be13527d00673093f9677f9b43d7e3a02ae6fa0ec74d3d98243b5b40e4"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]
  • id:Image的ID。image ID实际上只是最上层的layer ID,所以docker inspect也适用于任意一层layer
  • Parent:该layer的父层,可以递归地获得某个image的所有layer信息。
  • Comment:非常类似于Git的commit message,可以为该层做一些历史记录,方便理解。
  • Container:这个条目比较有意思,其中包括哲学的味道。比如前面提到容器的启动需要以image为模板。但又可以把该容器保存为镜像,所以一般来说image的每个layer都保存自一个容器,所以该容器可以说是image layer的“模板”
  • Config:包含了该image的一些配置信息,其中比较重要的是:"env"容器启动时会作为容器的环境变量,“Cmd”作为容器启动时的默认命令,“Labels”参数可以用于docker images命令过滤。
  • Architecture:该image对应的CPU体系结构。

拓展

联合挂载

联合文件系统这种思想由来已久,这些文件系统会把多个目录挂载到同一个目录,对外呈现这些目录的联合。

写时复制

当父进程fork子进程时,内核并没有为子进程分配内存,而是让父子进程共享内存。当两者之一修改共享内存时,会触发一次缺页异常导致真正的内存分配。这样做既加速了子进程的创建速度,又减少了内存的消耗。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: Docker镜像、容器和仓库之间有着密切的关系。仓库是集中存放镜像的地方,可以是公共的,例如 Docker Hub,也可以是自己搭建的私有仓库,如Docker Registry、Artifactory或Nexus等。镜像Docker的基本构建块,它是一个轻量级、可执行的独立软件包,包含了运行应用程序所需的所有文件和依赖关系。当我们使用Docker命令从仓库中获取一个镜像时,实际上是从仓库中下载该镜像的副本到本地。而容器是基于镜像创建的运行实例,它可以被启动、停止、删除和重启。一个容器可以使用一个或多个镜像来构建,并且可以通过对镜像进行修改来满足应用程序的需求。容器之间是相互隔离的,每个容器都具有自己独立的文件系统、进程空间和网络空间。所以,可以说镜像是仓库中存放的软件包,而容器则是基于镜像创建的运行实例。123 #### 引用[.reference_title] - *1* [面向对象视角下,理解Docker 镜像容器和仓库](https://blog.csdn.net/m0_53321320/article/details/126283645)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] - *2* *3* [Docker中仓库、镜像和容器用法详解](https://blog.csdn.net/weixin_44799217/article/details/127723211)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值