• dokcer镜像详解


    镜像是什么

    镜像是一种轻量级、可执行的独立软件保,用来打包软件运行环境和基于运行环境开发的软件,他包含运行某个软件所需的所有内容,包括代码、运行时库、环境变量和配置文件。

    所有应用,直接打包docker镜像,就可以直接跑起来!

    获取镜像的途径

    1.从镜像仓库下载

    2.从镜像压缩包

    3.自己制作的dockerfile

    Docker镜像加载原理

    UnionFs (联合文件系统)

    UnionFs(联合文件系统):Union文件系统(UnionFs)是一种分层、轻量级并且高性能的文件系统,他支持对文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下( unite several directories into a single virtual filesystem)。Union文件系统是 Docker镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像

    特性:一次同时加载多个文件系统,但从外面看起来,只能看到一个文件系统,联合加载会把各层文件系统叠加起来,这样最终的文件系统会包含所有底层的文件和目录。

    Docker镜像加载原理

    docker的镜像实际上由一层一层的文件系统组成,这种层级的文件系统UnionFS。

    boots(boot file system)主要包含 bootloader和 Kernel, bootloader主要是引导加载 kernel, Linux刚启动时会加载bootfs文件系统,在 Docker镜像的最底层是 boots。这一层与我们典型的Linux/Unix系统是一样的,包括bootloader和 Kernel。当boot加载完成之后整个内核就都在内存中了,此时内存的使用权已由 bootfs转交给内核,此时系统也会卸载bootfs。

    image-20200911163123676

    对于个精简的OS, rootfs可以很小,只需要包合最基本的命令、工具和程序库就可以了,因为底层直接用Host的kernel,自己只需要提供rootfs就可以了。由此可见对于不同的Linux发行版, boots基本是一致的, rootfs会有差別,因此不同的发行版可以公用bootfs.

    虚拟机是分钟级别,容器是秒级!

    镜像原理之分层理解

    image-20200911164553431

    为什么docker镜像会采用种方式?

    最大的好处:莫过于资源共享了!比如有多个镜像都从相同的Base镜像构建而来,那么宿主机只需在磁盘上保留一份base镜像,同时内存中也只需要加载一份base镜像,这样就可以为所有的容器服务了,而且镜像的每一层都可以被共享。

    #我们查看下mysql镜像的详细信息
    [root@localhost ~]# docker image inspect mysql
    [
        {
            "Id": "sha256:e1d7dc9731daa2c79858307d65ef35f543daf97457b9c11b681f78bb86f7a158",
            "RepoTags": [
                "mysql:latest"
            ],
            "RepoDigests": [
                "mysql@sha256:e1bfe11693ed2052cb3b4e5fa356c65381129e87e38551c6cd6ec532ebe0e808"
            ],
            "Parent": "",
            "Comment": "",
            "Created": "2020-09-10T06:53:58.046364521Z",
            "Container": "4a20d34c487d787e9094710172924054541f179b2f2082f159ce65e9506252d7",
            "ContainerConfig": {
                "Hostname": "4a20d34c487d",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "3306/tcp": {},
                    "33060/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "GOSU_VERSION=1.12",
                    "MYSQL_MAJOR=8.0",
                    "MYSQL_VERSION=8.0.21-1debian10"
                ],
                "Cmd": [
                    "/bin/sh",
                    "-c",
                    "#(nop) ",
                    "CMD ["mysqld"]"
                ],
                "ArgsEscaped": true,
                "Image": "sha256:145f837222dc7be65e5db56e4ab4d4bcf62fed0902d522732101b21ea681b8d4",
                "Volumes": {
                    "/var/lib/mysql": {}
                },
                "WorkingDir": "",
                "Entrypoint": [
                    "docker-entrypoint.sh"
                ],
                "OnBuild": null,
                "Labels": {}
            },
            "DockerVersion": "18.09.7",
            "Author": "",
            "Config": {
                "Hostname": "",
                "Domainname": "",
                "User": "",
                "AttachStdin": false,
                "AttachStdout": false,
                "AttachStderr": false,
                "ExposedPorts": {
                    "3306/tcp": {},
                    "33060/tcp": {}
                },
                "Tty": false,
                "OpenStdin": false,
                "StdinOnce": false,
                "Env": [
                    "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
                    "GOSU_VERSION=1.12",
                    "MYSQL_MAJOR=8.0",
                    "MYSQL_VERSION=8.0.21-1debian10"
                ],
                "Cmd": [
                    "mysqld"
                ],
                "ArgsEscaped": true,
                "Image": "sha256:145f837222dc7be65e5db56e4ab4d4bcf62fed0902d522732101b21ea681b8d4",
                "Volumes": {
                    "/var/lib/mysql": {}
                },
                "WorkingDir": "",
                "Entrypoint": [
                    "docker-entrypoint.sh"
                ],
                "OnBuild": null,
                "Labels": null
            },
            "Architecture": "amd64",
            "Os": "linux",
            "Size": 544193603,
            "VirtualSize": 544193603,
            "GraphDriver": {
                "Data": {
                    "LowerDir": "/var/lib/docker/overlay2/eac1b28e5eeccf446cf9b122130a0761b1ce19eb50c500f04c69bed0da333521/diff:/var/lib/docker/overlay2/52e8db187192ee8d52b74347809023f4d4989318d517b71ecc39db95b4db717b/diff:/var/lib/docker/overlay2/cc98255084914f1f38518e92c3bd1d69ac316cb8218fac134c47a1dcd51349c2/diff:/var/lib/docker/overlay2/a7937b4cc17e5c19b65d4e9f9ed69ef12f170ef0dbe2693f83628625429cb9f8/diff:/var/lib/docker/overlay2/bdb1d89a22e53bddc97c756f6aa1c7cd1b37e64b7c5e9adb91b358befeb18e57/diff:/var/lib/docker/overlay2/1c854d0a0f91fe80a44b36e4e8a878dddb8a6e3e62379226b3f6d6384c6b572c/diff:/var/lib/docker/overlay2/b563e53761d60fcfc229adcb80c08c38c32ec7bbe1e28579594a3c999eab4a1d/diff:/var/lib/docker/overlay2/f389d58ec12144138c574c483546a5544af85bba51eaf9f877c63c92bec5777a/diff:/var/lib/docker/overlay2/9acaabfed69e8d07fc2b20cbf0b641beb1008e6ff76edf2d6d62d61ada4c2d57/diff:/var/lib/docker/overlay2/0e36e7ad27559688836e84d437e0a0856c047aff62294a2ac0caedeaa728f32c/diff:/var/lib/docker/overlay2/d68cbded916a426e7612c238e7414b4535c0b6abf1fbcf0e697e3c8bd20dfbc3/diff",
                    "MergedDir": "/var/lib/docker/overlay2/4c822dd9bf616bfce6ab26be4a5946630a5464281f948ed9b988fa604b55f5f6/merged",
                    "UpperDir": "/var/lib/docker/overlay2/4c822dd9bf616bfce6ab26be4a5946630a5464281f948ed9b988fa604b55f5f6/diff",
                    "WorkDir": "/var/lib/docker/overlay2/4c822dd9bf616bfce6ab26be4a5946630a5464281f948ed9b988fa604b55f5f6/work"
                },
                "Name": "overlay2"
            },
            "RootFS": {                     
                "Type": "layers",
                "Layers": [
                    "sha256:07cab433985205f29909739f511777a810f4a9aff486355b71308bb654cdc868",
                    "sha256:99f2b905661ad6da61a7daa03441f86868e5dc621ea9a53696f98d40a51361d4",
                    "sha256:705e0a5709e5bfe1bcad6bca71c0677e2088f49b387bc0c070135ab38209b575",
                    "sha256:73b2ff2d449dc8cc7525999a8876aec53f61066bff7649e4b0576a0355631c76",
                    "sha256:18c57f967c0e8c90e26279c89d172b3e84fac30c48fd14066bc1d0481895b161",
                    "sha256:4ff56402c7c53062e1c7aba89dab4779b4929bcc19f21564fcb2b35b3b8d0e63",
                    "sha256:d2055cc0a7aa80c180028c7970c43e09cefc492a0d323de2604e55c98cb398c2",
                    "sha256:e929be3696cafce09e09dc6f62fd48d4e23fe96a6583d1e66d03a78627d79725",
                    "sha256:2a0bd3a9cd29a9c065c946f5df05676a3996abd4c126769d06cbecbc839e62a1",
                    "sha256:d086c9717c2b03114f508febcfca6671f098054c283834731ce78411bfeac42e",
                    "sha256:35864924eb5e64b1fc86db107a241d1bc1e1b713e0faef59f60f88c2699c9b13",
                    "sha256:612c87e75ba549972e70f0224092d8722709304f2b69a91ad6cfb6315654a273"
                ]
            },
            "Metadata": {
                "LastTagTime": "0001-01-01T00:00:00Z"
            }
        }
    ]
    

    理解:

    所有的 Docker镜像都起始于一个基础镜像层,当进行修改或培加新的内容时,就会在当前镜像层之上,创建新的镜像层。

    举一个简单的例子,假如基于 Ubuntu Linux16.04创建一个新的镜像,这就是新镜像的第一层;如果在该镜像中添加 Python包,就会在基础镜像层之上创建第二个镜像层;如果继续添加一个安全补丁,就会创建第三个镜像层。

    该镜像当前已经包含3个镜像层,如下图所示(这只是一个用于演示的很简单的例子)。

    img

    在添加额外的镜像层的同时,镜像始终保持是当前所有镜像的组合,理解这一点非常重要。下图中举了一个简单的例子,每个镜像层包含3个文件,而整体的大镜像包含了来自两个镜像层的6个文件。

    img

    上图中的镜像层跟之前图中的略有区別,主要目的是便于展示文件。

    下图中展示了一个稍微复杂的三层镜像,在外部看来整个镜像只有6个文件,这是因为最上层中的文件7是文件5的一个更新版。

    img

    这种情況下,上层镜像层中的文件覆盖了底层镜像层中的文件。这样就使得文件的更新版本作为一个新镜像层添加到镜像当中。

    Docker通过存储引擎(新版本采用快照机制)的方式来实现镜像层堆栈,并保证多镜像层对外展示为统一的文件系统。

    Linux上可用的存储引撃有AUFS、 Overlay2、 Device Mapper、Btrfs以及ZFS。顾名思义,每种存储引擎都基于 Linux中对应的文件系统或者块设备技术,井且每种存储引擎都有其独有的性能特点。

    Docker在 Windows上仅支持 windowsfilter 一种存储引擎,该引擎基于NTFS文件系统之上实现了分层和CoW [1]。

    特点

    Docker 镜像都是只读的,当容器启动时,一个新的可写层加载到镜像的顶部!

    这一层就是我们通常说的容器层,容器之下的都叫镜像层!img

    Commit 镜像

    docker commit #将一个容器提交成一个新的标签
    docker commit -m="描述信息" -a="作者" 容器id 目标镜像名:[版本TAG]
    

    实例演示:

    1.运行一个tomcat容器
    docker run -d -it --name=tomcat01 -p 8080:8080 tomcat
    2.发现没有页面
    3.我们添加一个页面
    [root@localhost ~]# docker exec -it tomcat01 /bin/bash
    root@a711ca484d49:/usr/local/tomcat# cp -r webapps.dist/* webapps
    root@a711ca484d49:/usr/local/tomcat# 
    4.使用docker commit 将容器提交成一个新的镜像
    [root@localhost ~]# docker commit -m="copy webapps.dis/* to webapps " -a="martin<123@qq.com>" tomcat01 martin/tomcat02:0.1
    sha256:75448ab287079920a9fca99a2de91a893a4da4443702f8ed16870fb45c504321
    [root@localhost ~]# docker images
    REPOSITORY               TAG                 IMAGE ID            CREATED                  SIZE
    martin/tomcat02          0.1                 75448ab28707        6 seconds ago            652MB
    
    [root@localhost ~]# docker run -d -it --name=tomact02 -p 8081:8080 martin/tomcat02:0.1
    

    image-20200911171240296

    *************** 当你发现自己的才华撑不起野心时,就请安静下来学习吧!***************
  • 相关阅读:
    【转】浮点数与IEEE 754
    最小二乘
    黑科技!两行代码完美解决:同时设置overflow-x:hidden,overflow-y:visible无效的问题
    js过滤html标签
    react native 项目版本升级
    react-native中显示手机本地图片/视频
    SourceTree推送分支时遇到ArgumentException encountered错误的解决办法
    开发自己的react-native组件并发布到npm[转]
    react native 中实现个别页面禁止截屏
    JS数字转中文
  • 原文地址:https://www.cnblogs.com/martin-huang/p/13683539.html
Copyright © 2020-2023  润新知