docker的联合文件系统 UnionFS《深入docker底层原理》

这篇具有很好参考价值的文章主要介绍了docker的联合文件系统 UnionFS《深入docker底层原理》。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

介绍

docker最大的贡献就是定义了容器镜像的分层的存储格式,docker镜像技术的基础是联合文件系统(UnionFS),其文件系统是分层的。这样既可以充分利用共享层,又可以减少存储空间占用。

联合挂载系统的工作原理:读:如果文件在upperdir(容器)层,直接读取文件;如果文件不在upperdir(容器)层,则从镜像层(lowerdir)读取。

目前docker支持的联合文件系统有很多种,包括:AUFS、overlay、overlay2、DeviceMapper、VSF等。

当选择Docker的存储驱动时,有几个常用的选项可供选择,包括AUFS, Overlay, Overlay2, DeviceMapper和VFS。下面是它们的对比:

  1. AUFS (Advanced Multi-Layered Unification Filesystem):AUFS是一种基于union mount技术的存储驱动,它允许将多个文件系统合并为一个只读的虚拟文件系统。AUFS在多个容器之间共享基础镜像的文件,并在每个容器中提供一个可写的层。然而,AUFS对于大型镜像和多层容器的性能可能有一些负面影响。此外,AUFS在最新的Linux内核版本中已不再被广泛支持。

  2. Overlay:Overlay是一种较新的存储驱动,它通过在底层文件系统上创建一个只读的基础镜像并叠加一个可写的层来实现容器的文件系统。Overlay相对于AUFS有更好的性能,而且它在最新的Linux内核中得到了更广泛的支持。然而,Overlay的缺点是不支持在同一个文件中存储大型镜像。

  3. Overlay2:Overlay2是Overlay的改进版,它在Overlay的基础上解决了一些性能和功能的问题。Overlay2使用一个单独的只读层来存储基础镜像,并且可以支持更大的镜像。它是Docker默认的存储驱动,因为它在大多数情况下都提供了更好的性能和可靠性。

  4. DeviceMapper:DeviceMapper是一种成熟的Linux存储驱动,它利用LVM(逻辑卷管理器)提供了高级功能,如快照和克隆。DeviceMapper是Docker支持的可插拔的存储后端之一,并被广泛用于可靠和复杂的存储需求。

  5. VFS (Virtual File System):VFS是Docker的默认存储驱动,它直接在宿主机上操作文件。VFS基于操作系统的本地文件系统,但在性能和可扩展性方面不如其他驱动。它适用于开发和测试环境,但不适合生产环境。

综上所述,当选择Docker存储驱动时,Overlay2是最常见和推荐的选择,因为它提供了较好的性能和可靠性。另外,如果需要高级功能和复杂的存储需求,可以考虑使用DeviceMapper。

查看docker容器使用的文件系统使用的命令如下,其中Storage Driver: overlay2代表使用的是overlay2联合文件系统。

[root@home]# docker info
Client:
 Context:    default
 Debug Mode: false
 Plugins:
  app: Docker App (Docker Inc., v0.9.1-beta3)
  buildx: Docker Buildx (Docker Inc., v0.9.1-docker)
  scan: Docker Scan (Docker Inc., v0.21.0)

Server:
 Containers: 2
  Running: 1
  Paused: 0
  Stopped: 1
 Images: 17
 Server Version: 20.10.21
 Storage Driver: overlay2
  Backing Filesystem: xfs
  Supports d_type: true
  Native Overlay Diff: true
  userxattr: false
 Logging Driver: json-file
 Cgroup Driver: cgroupfs
 Cgroup Version: 1
 Plugins:
  Volume: local
  Network: bridge host ipvlan macvlan null overlay
  Log: awslogs fluentd gcplogs gelf journald json-file local logentries splunk syslog
 Swarm: inactive
 Runtimes: io.containerd.runc.v2 io.containerd.runtime.v1.linux runc
 Default Runtime: runc
 Init Binary: docker-init
 containerd version: 1c90a442489720eec95342e1789ee8a5e1b9536f
 runc version: v1.1.4-0-g5fd4c4d
 init version: de40ad0
 Security Options:
  seccomp
   Profile: default
 Kernel Version: 3.10.0-957.el7.x86_64
 Operating System: CentOS Linux 7 (Core)
 OSType: linux
 Architecture: x86_64
 CPUs: 2
 Total Memory: 3.701GiB
 Name: 10-6-9-59
 ID: XISV:HHG5:YV5H:AQIM:WE4G:6IXJ:2N2Q:SZOM:XBCP:BTGB:HI7P:4W7O
 Docker Root Dir: /var/lib/docker
 Debug Mode: false
 Registry: https://index.docker.io/v1/
 Labels:
 Experimental: false
 Insecure Registries:
  harbor.lys.site
 Registry Mirrors:
  https://harbor.lys.site/
  https://vre6wzor.mirror.aliyuncs.com/
 Live Restore Enabled: false

修改

修改对应文件系统,可以通过/etc/docker/daemon.json文件的 “storage-driver”:参数

[root@home]# cat /etc/docker/daemon.json 
{
  "registry-mirrors": ["https://vre6wzor.mirror.aliyuncs.com"],
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}

原理实践

overlay2

docker的联合文件系统 UnionFS《深入docker底层原理》,docker,docker,eureka,容器
如上图所示,OverlayFS将单个Linux主机上的两个目录合并成一个目录,这些目录被称为层,统一过程被称为联合挂载。OverlayFS关联的底层目录称为lowerdir,lowerdir是只读的镜像层(image layer),其中就包含bootfs/rootfs层,bootfs(boot file system)主要包含bootloader和kernel,bootloader主要是引导加载kernel,当boot成功 kernel 被加载到内存中,bootfs就被umount了,rootfs(root file system)包含的就是典型Linux系统中的/dev、/proc、/bin、/etc等标准目录。lowerdir是可以分很多层的,除了bootfs/rootfs层以外,还可以通过Dockerfile建立很多image层。

对应的高层目录upperdir层是lowerdir的上一层,只有这一层可读可写的,其实就是Container层,在启动一个容器的时候会在最后的image层的上一层自动创建,所有对容器数据的更改都会发生在这一层。

联合挂载后merged层就是联合挂载层,也就是给用户暴露的统一视觉,将image层和container层结合,就如最上边的图中描述一致,同一文件,在此层会展示离它最近的层级里的文件内容,或者可以理解为,只要container层中有此文件,便展示container层中的文件内容,若container层中没有,则展示image层中的。

如下容器的整体结构

docker的联合文件系统 UnionFS《深入docker底层原理》,docker,docker,eureka,容器
在centos操作系统下,对应联合文件系统overlay2目录是:/var/lib/docker/overlay2,使用docker inspect [容器ID]就可以看到这几个层所在的位置。示例

docker inspect 03cf6fafe267
[
    {
        "Id": "03cf6fafe26723252ba50f559354575c9ee8518af9c94380f2286a7ded7fe5d2",
        "Created": "2023-06-30T10:07:07.228528513Z",
        "Path": "/portainer",
        "Args": [],
        "State": {
            "Status": "running",
            "Running": true,
            "Paused": false,
            "Restarting": false,
            "OOMKilled": false,
            "Dead": false,
            "Pid": 3670,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-06-30T10:07:07.822465986Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },
        "Image": "sha256:580c0e4e98b06d258754cf28c55f21a6fa0dc386e6fe0bf67e453c3642de9b8b",
        "ResolvConfPath": "/var/lib/docker/containers/03cf6fafe26723252ba50f559354575c9ee8518af9c94380f2286a7ded7fe5d2/resolv.conf",
        "HostnamePath": "/var/lib/docker/containers/03cf6fafe26723252ba50f559354575c9ee8518af9c94380f2286a7ded7fe5d2/hostname",
        "HostsPath": "/var/lib/docker/containers/03cf6fafe26723252ba50f559354575c9ee8518af9c94380f2286a7ded7fe5d2/hosts",
        "LogPath": "/var/lib/docker/containers/03cf6fafe26723252ba50f559354575c9ee8518af9c94380f2286a7ded7fe5d2/03cf6fafe26723252ba50f559354575c9ee8518af9c94380f2286a7ded7fe5d2-json.log",
        "Name": "/prtainer-test",
        "RestartCount": 0,
        "Driver": "overlay2",
        "Platform": "linux",
        "MountLabel": "",
        "ProcessLabel": "",
        "AppArmorProfile": "",
        "ExecIDs": null,
        "HostConfig": {
            "Binds": [
                "/var/run/docker.sock:/var/run/docker.sock"
            ],
            "ContainerIDFile": "",
            "LogConfig": {
                "Type": "json-file",
                "Config": {}
            },
            "NetworkMode": "default",
            "PortBindings": {
                "9000/tcp": [
                    {
                        "HostIp": "",
                        "HostPort": "9000"
                    }
                ]
            },
            "RestartPolicy": {
                "Name": "always",
                "MaximumRetryCount": 0
            },
            "AutoRemove": false,
            "VolumeDriver": "",
            "VolumesFrom": null,
            "CapAdd": null,
            "CapDrop": null,
            "CgroupnsMode": "host",
            "Dns": [],
            "DnsOptions": [],
            "DnsSearch": [],
            "ExtraHosts": null,
            "GroupAdd": null,
            "IpcMode": "private",
            "Cgroup": "",
            "Links": null,
            "OomScoreAdj": 0,
            "PidMode": "",
            "Privileged": false,
            "PublishAllPorts": false,
            "ReadonlyRootfs": false,
            "SecurityOpt": null,
            "UTSMode": "",
            "UsernsMode": "",
            "ShmSize": 67108864,
            "Runtime": "runc",
            "ConsoleSize": [
                0,
                0
            ],
            "Isolation": "",
            "CpuShares": 0,
            "Memory": 0,
            "NanoCpus": 0,
            "CgroupParent": "",
            "BlkioWeight": 0,
            "BlkioWeightDevice": [],
            "BlkioDeviceReadBps": null,
            "BlkioDeviceWriteBps": null,
            "BlkioDeviceReadIOps": null,
            "BlkioDeviceWriteIOps": null,
            "CpuPeriod": 0,
            "CpuQuota": 0,
            "CpuRealtimePeriod": 0,
            "CpuRealtimeRuntime": 0,
            "CpusetCpus": "",
            "CpusetMems": "",
            "Devices": [],
            "DeviceCgroupRules": null,
            "DeviceRequests": null,
            "KernelMemory": 0,
            "KernelMemoryTCP": 0,
            "MemoryReservation": 0,
            "MemorySwap": 0,
            "MemorySwappiness": null,
            "OomKillDisable": false,
            "PidsLimit": null,
            "Ulimits": null,
            "CpuCount": 0,
            "CpuPercent": 0,
            "IOMaximumIOps": 0,
            "IOMaximumBandwidth": 0,
            "MaskedPaths": [
                "/proc/asound",
                "/proc/acpi",
                "/proc/kcore",
                "/proc/keys",
                "/proc/latency_stats",
                "/proc/timer_list",
                "/proc/timer_stats",
                "/proc/sched_debug",
                "/proc/scsi",
                "/sys/firmware"
            ],
            "ReadonlyPaths": [
                "/proc/bus",
                "/proc/fs",
                "/proc/irq",
                "/proc/sys",
                "/proc/sysrq-trigger"
            ]
        },
        "GraphDriver": {
            "Data": {
                "LowerDir": "/var/lib/docker/overlay2/840faba1dd5726eec55029b0da956195e2234853313e3c78e8f3f96e51244401-init/diff:/var/lib/docker/overlay2/0b1f62ad330df70a06a47e85689eedbb1c59f48df4b775c166468286f6aa3198/diff:/var/lib/docker/overlay2/5d83a80e080ae21964392ebfb9868e217bc223f9b5b70018042765b7a9ea3995/diff:/var/lib/docker/overlay2/fce6d44bff996fcd898fb8cc182389be24c9798d2cef20ecf0caa7eac428a316/diff",
                "MergedDir": "/var/lib/docker/overlay2/840faba1dd5726eec55029b0da956195e2234853313e3c78e8f3f96e51244401/merged",
                "UpperDir": "/var/lib/docker/overlay2/840faba1dd5726eec55029b0da956195e2234853313e3c78e8f3f96e51244401/diff",
                "WorkDir": "/var/lib/docker/overlay2/840faba1dd5726eec55029b0da956195e2234853313e3c78e8f3f96e51244401/work"
            },
            "Name": "overlay2"
        },
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/var/run/docker.sock",
                "Destination": "/var/run/docker.sock",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            },
            {
                "Type": "volume",
                "Name": "e77fbc451ca1b8366c10a52dc30d87aa6b482f78e48c52f8082e607e316128f0",
                "Source": "/var/lib/docker/volumes/e77fbc451ca1b8366c10a52dc30d87aa6b482f78e48c52f8082e607e316128f0/_data",
                "Destination": "/data",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
        "Config": {
            "Hostname": "03cf6fafe267",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "ExposedPorts": {
                "9000/tcp": {}
            },
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": null,
            "Image": "portainer/portainer",
            "Volumes": {
                "/data": {}
            },
            "WorkingDir": "/",
            "Entrypoint": [
                "/portainer"
            ],
            "OnBuild": null,
            "Labels": {}
        },
        "NetworkSettings": {
            "Bridge": "",
            "SandboxID": "3a7037ed8c5eee246cc4cee7a525bca0fad7dfc3f3aa455d34e2333c58e460b8",
            "HairpinMode": false,
            "LinkLocalIPv6Address": "",
            "LinkLocalIPv6PrefixLen": 0,
            "Ports": {
                "9000/tcp": [
                    {
                        "HostIp": "0.0.0.0",
                        "HostPort": "9000"
                    },
                    {
                        "HostIp": "::",
                        "HostPort": "9000"
                    }
                ]
            },
            "SandboxKey": "/var/run/docker/netns/3a7037ed8c5e",
            "SecondaryIPAddresses": null,
            "SecondaryIPv6Addresses": null,
            "EndpointID": "7eee2f172e17fe50813a1ba82b76a0b32cdd9b8011eb3337ac530d73dcac9b5f",
            "Gateway": "172.17.0.1",
            "GlobalIPv6Address": "",
            "GlobalIPv6PrefixLen": 0,
            "IPAddress": "172.17.0.2",
            "IPPrefixLen": 16,
            "IPv6Gateway": "",
            "MacAddress": "02:42:ac:11:00:02",
            "Networks": {
                "bridge": {
                    "IPAMConfig": null,
                    "Links": null,
                    "Aliases": null,
                    "NetworkID": "5c0d2dd61ef719f9e167485e3f80151c47c60e973d16b8ec40f41367adb4cf91",
                    "EndpointID": "7eee2f172e17fe50813a1ba82b76a0b32cdd9b8011eb3337ac530d73dcac9b5f",
                    "Gateway": "172.17.0.1",
                    "IPAddress": "172.17.0.2",
                    "IPPrefixLen": 16,
                    "IPv6Gateway": "",
                    "GlobalIPv6Address": "",
                    "GlobalIPv6PrefixLen": 0,
                    "MacAddress": "02:42:ac:11:00:02",
                    "DriverOpts": null
                }
            }
        }
    }
]

overlay的模拟实践

1.显示已挂载的Overlay文件系统

[root@newhostname to]# mount | grep overlay
overlay on /var/lib/docker/overlay2/083352f2addd2a15848f6f2742595c7706d74721b688f2665766c2397690febb/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/RFCU37H7W5QLVKZQYWK4WKS2ZR:/var/lib/docker/overlay2/l/A2GRPWBIX7ETOJISQK6HBFAXDR:/var/lib/docker/overlay2/l/722WJHOAIK2L42LBVVRQAKDSA4:/var/lib/docker/overlay2/l/M6XHLB5ZALNKEPMJBDGUAZ5LTG,upperdir=/var/lib/docker/overlay2/083352f2addd2a15848f6f2742595c7706d74721b688f2665766c2397690febb/diff,workdir=/var/lib/docker/overlay2/083352f2addd2a15848f6f2742595c7706d74721b688f2665766c2397690febb/work)

请按照以下步骤进行操作:

2. 创建一个存在的目录作为挂载点:

sudo mkdir /path/to/mount/point

3. 使用overlay文件系统挂载:

sudo mount -t overlay overlay -o lowerdir=/path/to/lower,upperdir=/path/to/upper,workdir=/path/to/work /path/to/mount/point

请将/path/to/lower替换为底层目录的实际路径,将/path/to/upper替换为上层目录的实际路径,将/path/to/work替换为工作目录的实际路径。

4. 卸载Overlay文件系统时,请使用以下命令:

sudo umount /path/to/mount/point

请注意修改命令中的路径以正确适配您的系统配置,确保目录的存在和权限设置正确。文章来源地址https://www.toymoban.com/news/detail-543941.html

到了这里,关于docker的联合文件系统 UnionFS《深入docker底层原理》的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 深入剖析 Git 对象底层原理

    在我们日常使用 Git 时,通常的操作是: 在写完一段代码后,执行 git add 命令,将这段代码添加到暂存区中 然后再执行 git commit 和 git push 命令,将 本地 Git 版本库中的提交同步到服务器中的版本库中 Git 在中间做了什么,它如何存储不同的文件和内容,以及如何区分不同分支

    2024年01月20日
    浏览(30)
  • 深入探讨Eureka的三级缓存架构与缓存运行原理

    在当今的软件开发领域,分布式系统已经成为了必 不可少的一部分。而在分布式系统中,服务的注册与发现是其中的重要组成部分之一。Netflix开源的Eureka便是一款优秀的服务发现框架,它采用了三级缓存架构来提供高效的服务发现与注册功能。本文将深入探讨Eureka的三级缓

    2024年02月11日
    浏览(22)
  • Innodb底层原理与Mysql日志机制深入剖析

    大体来说,MySQL 可以分为 Server 层和存储引擎层两部分。 主要包括连接器、查询缓存、分析器、优化器、执行器等,涵盖 MySQL 的大多数核心服务功能,以及所有的内置函数(如日期、时间、数学和加密函数等),所有跨存储引擎的功能都在这一层实现,比如存储过程、触发器

    2024年02月21日
    浏览(27)
  • 【Spring Cloud】深入理解 Eureka 注册中心的原理、服务的注册与发现

    在微服务架构中,服务的注册与发现是至关重要的一环。为了实现这一目标,Eureka 注册中心应运而生。在本篇文章中,我们将深入理解 Eureka 注册中心的原理,以及探讨服务的注册与发现机制。 在微服务的协作中,服务之间的远程调用是常见的需求。然而,使用传统的 Rest

    2024年02月08日
    浏览(30)
  • 【JUC系列-01】深入理解JMM内存模型的底层实现原理

    JUC系列整体栏目 内容 链接地址 【一】深入理解JMM内存模型的底层实现原理 https://zhenghuisheng.blog.csdn.net/article/details/132400429 【二】深入理解CAS底层原理和基本使用 https://blog.csdn.net/zhenghuishengq/article/details/132478786 【三】熟练掌握Atomic原子系列基本使用 https://blog.csdn.net/zhenghuis

    2024年02月12日
    浏览(29)
  • Docker 魔法解密:探索 UnionFS 与 OverlayFS

    本文主要介绍了 Docker 的另一个核心技术:Union File System。主要包括对 overlayfs 的演示,以及分析 docker 是如何借助 ufs 实现容器 rootfs 的。 如果你对云原生技术充满好奇,想要深入了解更多相关的文章和资讯,欢迎关注微信公众号。 搜索公众号【 探索云原生 】即可订阅 Unio

    2024年01月19日
    浏览(24)
  • [深入理解NAND Flash (原理篇)] Flash(闪存)存储器底层原理 | 闪存存储器重要参数

    传送门 总目录  所在专栏   《 深入理解SSD》 个人辛苦整理,付费内容,禁止转载。 内容摘要 从底层物理原理上了解 Nand Flash。 现代计算机构想是基于冯 · 诺依曼架构的图灵计算机设备,图灵从理论上去论证了现代计算机可以实现,也就是给现代计算机注入了灵魂,而冯

    2024年02月06日
    浏览(31)
  • Docker底层原理

    Docker的架构和组件包括Docker Engine、Docker CLI、Docker Image、Docker Container等 。 Docker采用的是C/S(Client-Server,客户端-服务器)架构,其中主要包含以下几个核心组件: Docker客户端(Client) :它是用户与Docker交互的界面,通过命令行工具(CLI)向Docker守护进程发送请求。 Docker守护

    2024年03月10日
    浏览(75)
  • docker的底层原理

    概述 :Docker的底层原理基于 容器化技术,通过使用命名空间和控制组等技术实现资源的隔离与管理 。 底层原理: 客户端-服务器架构 :Docker采用的是Client-Server架构,其中Docker守护进程(daemon)运行在主机上,并通过Socket连接接受来自客户端的命令和管理容器。 容器运行时

    2024年02月21日
    浏览(24)
  • 【深入浅出RocketMQ原理及实战】「底层原理挖掘系列」透彻剖析贯穿RocketMQ的消息消费长轮训机制体系的原理分析

    使用系统控制读取操作的DefaultMQPushConsumer可以自动调用传入的处理方法来处理收到的消息。通过设置各种参数和传入处理消息的函数,使用DefaultMQPushConsumer的主要目的是方便配置和处理消息。在收到消息后,系统会自动保存Offset,并且如果加入了新的DefaultMQPushConsumer,系统会

    2024年02月11日
    浏览(26)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包