docker存储-overlayfs.镜像底层原理/volume原理

本文介绍了联合文件系统OverlayFS,它依赖于其他文件系统,将不同目录合并。阐述了相关命令、操作规则,如合并、读写规则等。还说明了在Docker中的使用,包括镜像层、容器层的构成,以及volume原理,指出volume可绕过OverlayFS。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.介绍

联合文件系统,overlayFs依赖并建立在其它的文件系统之上(例如ext4fs和xfs等等),并不直接参与磁盘空间结构的划分,仅仅将原来底层文件系统中不同的目录进行“合并”.

2.命令

mount -t overlay overlay -o lowerdir=lower1:lower2:lower3,upperdir=upper,workdir=work merged

1)lowerdir=xxx:指定用户需要挂载的lower层目录(支持多lower,最大支持500层);
2)upperdir=xxx:指定用户需要挂载的upper层目录;
3)workdir=xxx:指定文件系统的工作基础目录,挂载后内容会被清空,且在使用过程中其内容用户不可见;
4)  merged:  最后merge到哪个目录

  • 对用户来说,他只知道有一个merge目录,merge下的文件来自哪个lower,哪个upper,他都不知道.
  • merge规则:如果存在同名文件,那么upper>lower[n]>lower[n+1].如果存在同名目录,那么取并集.
  • 读写规则:
  1. 对merge文件的操作:如果操作的文件原属于upper目录,那么会直接造成对源文件的修改;如果操作的文件原属于lower目录,那么会复制一份到upper目录.从此原lower中的文件与merge目录没有任何关系,有关系的是upper下的同名文件.
  2. 对原文件的操作:对原文件的操作,均会影响merged文件的内容,因为他们本身就是映射的.

 

3.实际操作:

创建一些目录以及文件.

[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│   ├── l1-1
│   └── l1-2
├── l2
│   ├── l2-1
│   └── l2-2
├── result
├── u
│   └── u1
└── work

执行mount操作

[root@tv2-callchain-tool-02 testAufs]# mount -t overlay overlay -o lowerdir=l1:l2,upperdir=u,workdir=work result

查看当前结构

[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│   ├── l1-1
│   └── l1-2
├── l2
│   ├── l2-1
│   └── l2-2
├── result
│   ├── l1-1
│   ├── l1-2
│   ├── l2-1
│   ├── l2-2
│   └── u1
├── u
│   └── u1
└── work
    └── work

由此可见: l1,l2,u目录下的文件全部merge到了 result目录.下面做一些测试

3.1.修改原文件,看是否merge后的文件也会改.

[root@tv2-callchain-tool-02 testOverlay]# echo "old l1">l1/l1-1
[root@tv2-callchain-tool-02 testOverlay]# cat l1/l1-1
old l1
[root@tv2-callchain-tool-02 testOverlay]# cat result/l1-1
old l1

可见,文件已经改了

3.2.修改result中的文件.修改原本属于upper的文件

[root@tv2-callchain-tool-02 testOverlay]# echo "upper txt">result/u1
You have new mail in /var/spool/mail/root
[root@tv2-callchain-tool-02 testOverlay]# cat result/u1
upper txt
[root@tv2-callchain-tool-02 testOverlay]# cat u/u1
upper txt
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│   ├── l1-1
│   └── l1-2
├── l2
│   ├── l2-1
│   └── l2-2
├── result
│   ├── l1-1
│   ├── l1-2
│   ├── l2-1
│   ├── l2-2
│   └── u1
├── u
│   └── u1
└── work
    └── work

3.3.修改result下原本属于lower层的文件.

[root@tv2-callchain-tool-02 testOverlay]# echo "result/lower txt">result/l2-1
[root@tv2-callchain-tool-02 testOverlay]# cat result/l2-1
result/lower txt
[root@tv2-callchain-tool-02 testOverlay]# cat l2/l2-1
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│   ├── l1-1
│   └── l1-2
├── l2
│   ├── l2-1
│   └── l2-2
├── result
│   ├── l1-1
│   ├── l1-2
│   ├── l2-1
│   ├── l2-2
│   └── u1
├── u
│   ├── l2-1
│   └── u1
└── work
    └── work

注意这里:

result/l2-1 内容变了,但是原本目录下 l2/l2-1没变,因为是只读层, upper层下多了l2-1文件.此时数据是更改的内容.此时upper下的同名文件隐藏掉lower下的文件.你再修改lower下的文件,result的内容也不会变了.

3.4.动态添加一个文件

3.4.1 添加到 lower,在upper无同名./添加到upper,lower无同名

[root@tv2-callchain-tool-02 l1]# touch l1-add
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│   ├── l1-1
│   ├── l1-2
│   └── l1-add
├── l2
│   ├── l2-1
│   └── l2-2
├── result
│   ├── l1-1
│   ├── l1-2
│   ├── l1-add
│   ├── l2-1
│   ├── l2-2
│   └── u1
├── u
│   ├── l2-1
│   └── u1
└── work
    └── work


######添加到upper,lower无同名#########
[root@tv2-callchain-tool-02 testOverlay]# tree .
.
├── l1
│   ├── l1-1
│   ├── l1-2
│   └── l1-add
├── l2
│   ├── l2-1
│   └── l2-2
├── result
│   ├── l1-1
│   ├── l1-2
│   ├── l1-add
│   ├── l2-1
│   ├── l2-2
│   └── u4
├── u
│   ├── l1-2
│   ├── l2-1
│   └── u4
└── work
    └── work

多会合并的

4.2 添加lower,且upper有同名/ 添加upper,且lower有同名/添加upper,在lower有同名,都不行

###添加lower,在upper有同名####肯定无效
[root@tv2-callchain-tool-02 testOverlay]# touch l1/u4
You have new mail in /var/spool/mail/root
[root@tv2-callchain-tool-02 testOverlay]# echo "11">l1/u4
[root@tv2-callchain-tool-02 testOverlay]# cat result/
l1-1    l1-2    l1-add  l2-1    l2-2    u4
[root@tv2-callchain-tool-02 testOverlay]# cat result/u4

###添加lower,在lower有同名####  无效
[root@tv2-callchain-tool-02 testOverlay]# echo "l1 add">l1/l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l
l1-1    l1-2    l1-add  l2-1    l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l
l1-1    l1-2    l1-add  l2-1    l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l
l1-1    l1-2    l1-add  l2-1    l2-2
[root@tv2-callchain-tool-02 testOverlay]# cat result/l2-2


###添加upper,在lower有同名####  无效

 

3.5.删除呢??

删除需要考虑到几种场景.

a删除的文件是upper层,且lower层没有同名文件,很好办.直接删除就行了

b删除lower文件,并且upper没有同名文件名.

有点难搞,要保证lower原文件不能删除,又要保证用户见不到该文件. overlayFs使用了障眼法.Whiteout文件.Whiteout文件在用户删除文件时创建,用于屏蔽底层的同名文件,同时该文件在merge层是不可见的

类似一个黑名单

当用户在merge层通过ls命令(将通过readddir系统调用)检查父目录的目录项时,overlayfs会自动过过滤掉和whiteout文件自身以及和它同名的lower层文件和目录,达到了隐藏文件的目的,让用户以为文件已经被删除了

c要删除的文件是upper层覆盖lower层的文件,要删除的目录是上下层合并的目录

要把upper层的删除,并且屏蔽掉lower层文件

 

3.6.创建一个文件或目录

3.7.rename文件/目录

 

4.docker怎么使用的

[root@tv2-callchain-tool-02 data]# mount|grep overlay
overlay on /var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/AYCIYBZZOU2SBB7HAWWC53G5MV:/var/lib/docker/overlay2/l/7AC2GBWZ3VYQGR2IW6FVGTJELH,upperdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/diff,workdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/work)
overlay on /data/dockerTest/testAufs/merged type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=result)
overlay on /data/dockerTest/testOverlay/result type overlay (rw,relatime,lowerdir=l1:l2,upperdir=u,workdir=work)
overlay on /data/dockerTest/testOverlay/m type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=work)


后面三个是我们测试时用的

第一个是当前docker启动的容器用的

可以看到:

1.lower是/var/lib/docker/overlay2/l/  文件夹下的某几个文件

只读层,这些文件一起构成了某个镜像.例如 Ubuntu+java+tomcat+nginx+webApp构成了整个应用的镜像

Dockerfile 中的每个原语执行后,都会生成一个对应的镜像层.即使原语本身并没有明显地修改文件的操作(比如,ENV 原语),它对应的层也会存在。只不过在外界看来,这个层是空的

2.upper是upperdir=/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/diff 文件

这个是读写层.容器就是一个读写层,我们在容器里增删改操作会都是写在这里.

一旦我们容器运行时,提交成为一个镜像.那么  会把该读写层,变为只读层!!主要:容器是可写,镜像是只读!

3.merge文件是/var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged  这不就是操作系统吗??

[root@tv2-callchain-tool-02 merged]# ll /var/lib/docker/overlay2/44f8d7c28f545bd10acaea67d7138774445389171a66b418dae0d83469c8e29b/merged
total 48
drwxr-xr-x 2 root      root      12288 Oct 13 07:47 bin
drwxr-xr-x 1 root      root       4096 Nov 25 12:49 dev
drwxr-xr-x 1 root      root       4096 Nov 25 12:49 etc
drwxr-xr-x 2 nfsnobody nfsnobody  4096 Oct 13 07:47 home
drwxr-xr-x 2 root      root       4096 Nov 25 12:49 proc
drwx------ 2 root      root       4096 Oct 13 07:47 root
drwxr-xr-x 2 root      root       4096 Nov 25 12:49 sys
drwxrwxrwt 2 root      root       4096 Oct 13 07:47 tmp
drwxr-xr-x 3 root      root       4096 Oct 13 07:47 usr
drwxr-xr-x 4 root      root       4096 Oct 13 07:47 var

 

容器创建成功后,会添加一个upper层,运行时的修改都是在针对 upper层操作.如果要修改lower层呢??那么需要写时复制了,就是把lower层复制到upper层,然后你就可以修改了.

如果容器退出,那么upper层会删除掉,之前的lower层不会变,你再用同样的镜像去生成一个容器,还是使用同样的lower层.

5.volume原理

刚刚我们分析了docker的存储层的原理.在此总结下:docker的镜像是又多个只读层叠加的.容器是这些只读层+读写层.如果运行的时候,对文件作出了修改,那么会使用cow机制,将lower层数据拷贝到upper层.当删除容器后,读写层也会删除.

1.启动一个容器,使用volume  

docker run -it --name volume-test -h CONTAINER -v /data/testvolume busybox /bin/sh

2.查看容器中的数据.啥都没有

/data/testvolume # ls /data/testvolume/
/data/testvolume #

3.查看

[root@tv2-callchain-tool-02 data]# docker inspect volume-test|grep volume
        "Name": "/volume-test",
                "Type": "volume",
                "Source": "/var/lib/docker/volumes/c40fae3cefad3ffb1eac6fa584a131551ff7c3e5723b15a153a9ca9332316af3/_data",
                "Destination": "/data/testvolume",
                "/data/testvolume": {}

说明/data/testvolume 映射在了/var/lib/docker/volumes/c40fae3cefad3ffb1eac6fa584a131551ff7c3e5723b15a153a9ca9332316af3/_data

注意,这里是docker volumes目录,说明volume已经绕过了overlayfs.我们在_data下新增一个文件

[root@tv2-callchain-tool-02 ~]# cd /var/lib/docker/volumes/e124d9f2cf43d41f6c2882bac080db974636c6cbbcd01f28aaf3ffe553b4514b/_data
[root@tv2-callchain-tool-02 _data]# touch testhh

查看容器

/data/testvolume # ls /data/testvolume/
testhh

没有问题

我们在容器里创建

/data/testvolume # touch /data/testvolume/testhh2

在宿主机的目录上
[root@tv2-callchain-tool-02 _data]# ls /var/lib/docker/volumes/e124d9f2cf43d41f6c2882bac080db974636c6cbbcd01f28aaf3ffe553b4514b/_data
testhh  testhh2

 

 

我们再看下mount

[root@tv2-callchain-tool-02 data]# mount|grep overlay
overlay on /data/dockerTest/testAufs/merged type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=result)
overlay on /data/dockerTest/testOverlay/result type overlay (rw,relatime,lowerdir=l1:l2,upperdir=u,workdir=work)
overlay on /data/dockerTest/testOverlay/m type overlay (rw,relatime,lowerdir=a:b,upperdir=c,workdir=work)
overlay on /var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/merged type overlay (rw,relatime,lowerdir=/var/lib/docker/overlay2/l/ZOOVPE6ITB5JBEWQW3AIQBLXTE:/var/lib/docker/overlay2/l/7AC2GBWZ3VYQGR2IW6FVGTJELH,upperdir=/var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/diff,workdir=/var/lib/docker/overlay2/d95533f356ba958c012a197d35cc8fa8e36c56d1d852ce731b2f5c847b65136a/work)

确实没有使用overlayfs

 

 

参考:https://blog.csdn.net/luckyapple1028/article/details/78075358 这个文章写得很好

https://zhuanlan.zhihu.com/p/41958018

<think>我们遇到了一个错误:尝试重命名一个不存在的镜像。错误信息表明本地没有这个镜像。用户之前可能已经尝试过拉取这个镜像,但失败了(如上一个问题所示),所以现在本地没有这个镜像,因此无法重命名。解决方案步骤:1.首先需要确认该镜像确实存在于本地。使用 `docker images`查看。2.如果不存在,需要先拉取镜像。但之前拉取失败,所以可能需要先解决拉取问题(如上一个回答所述)。3.如果镜像存在,但名称输入有误,需要修正名称。根据错误信息,当前本地没有该镜像,因此我们需要先拉取镜像,或者确认镜像的正确名称。具体步骤:-检查镜像名称是否正确(包括大小写、特殊字符等) -尝试拉取镜像:`dockerpull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0`-如果拉取失败,参考上一个问题的解决方案(登录仓库、检查网络、确认仓库是否存在等) -拉取成功后,再执行重命名操作如果用户已经确认镜像不存在,并且拉取失败,那么可能需要从其他途径获取镜像(如构建镜像)。因此,回答将包含以下内容:1.错误原因分析:镜像不存在于本地。2.解决步骤:先拉取镜像,再重命名。3.如果拉取失败的处理建议。注意:由于用户是在Windows的cmd下操作,命令格式相同。同时,根据规则,最后必须提出3-5个相关问题。</think>### Docker镜像重命名错误分析与解决 您遇到的错误 `Error response from daemon: No such image` 表明Docker在本地找不到指定的原镜像。以下是详细分析和解决方案: #### 错误原因: 1. **镜像不存在于本地**: - 您尚未拉取 `swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0` 到本地 -镜像名称/标签输入有误(大小写、特殊字符等) 2. **镜像列表验证**: ```bash docker images # 检查完整镜像列表 docker images | findstr "openharmony" # Windows搜索 ``` #### 解决方案: 1. **先拉取镜像再重命名**: ```bash docker pull swr.cn-south-1.myhuaweicloud.com/openharmony-docker/openharmony-docker:1.0.0 docker tag swr...1.0.0 openharmony-docker:1.0.0 ``` 2. **使用镜像ID替代名称**(如果已存在其他标签): ```bash # 获取镜像ID docker images # 通过ID重命名 docker tag e530b8d2 openharmony-docker:1.0.0 ``` 3. **名称修正技巧**: - 使用Tab键自动补全(PowerShell/CMD支持) - 复制粘贴镜像全称避免手误 - 检查特殊字符:`/`、`:`、`.` 需完整保留 4. **仓库登录验证**(如果是私有镜像): ```bash docker login swr.cn-south-1.myhuaweicloud.com ``` #### 操作验证: ```bash docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}" ``` 应显示新旧两个镜像标签指向相同镜像ID
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值