docker理解

目录

起因

docker镜像

docker容器

overlay2文件系统

docker命令对应的操作

问题分析及解决方法


起因

起因是我在删除本地容器的时候报了如下错误,尝试了各种方法,最后debugfs从文件系统的角度去删除文件才解决。尝试过程中对docker镜像,容器有了更深入的理解。

复制代码
Error response from daemon: driver "overlay2" failed to remove root filesystem
Error response from daemon: open /mnt/docker/overlay2/.../diff/var/tmp/.OCularSD: permission denied

docker镜像

首先关于docker镜像,本质上是一堆只读层,即镜像就是多个只读层的栈。用Dockerfile举例,每个 RUN、COPY、ADD 都会产生一个新的只读层。每层里只记录自己新增/修改的文件(不是完整文件系统的快照)。

复制代码
`dockerfile                                                                                                                                                                
  FROM ubuntu:22.04               # 层1:基础层 ~80MB                                                                                                                         
  apt install -y python3          # 层2:安装 python ~150MB 新增                                                                                                   
  COPY app.py /app/               # 层3:复制文件 ~1KB 新增                                                                                                                  
  RUN pip install torch           # 层4:装 torch ~2GB 新增     


镜像(只读层栈)                                                                                                                                                         
    ┌──────────┐                                                                                                                                                             
    │  层4     │ ─── pip install torch(只读)                                                                                                                               
    ├──────────┤                                                                                                                                                             
    │  层3     │ ─── COPY app.py(只读)                                                                                                                                     
    ├──────────┤                                                                                                                                                             
    │  层2     │ ─── apt install python3(只读)                                                                                                                             
    ├──────────┤                                                                                                                                                             
    │  层1     │ ─── ubuntu:22.04(只读)                                                                                                                                    
    └──────────┘                           

docker容器

在基于镜像运行某个容器时,docker在镜像的只读层栈顶上加一层可写层,所有在容器里的修改都被保存在可写层里。容器被删除时,可写层被清理,下层的只读层不变

复制代码
 容器                                                                                                                                                                     
    ┌──────────┐                                                                                                                                                             
    │ RW 层    │ ← 容器的可写层(你在容器里改的任何东西都在这层)                                                                                                            
    ├──────────┤                                                                                                                                                             
    │  层4     │ ─── pip install torch(只读)                                                                                                                               
    ├──────────┤                                                                                                                                                             
    │  层3     │ ─── COPY app.py(只读)                                                                                                                                     
    ├──────────┤                                                                                                                                                             
    │  层2     │ ─── apt install python3(只读)                                                                                                                             
    ├──────────┤                                                                                                                                                             
    │  层1     │ ─── ubuntu:22.04(只读)                                                                                                                                    
    └──────────┘                                

overlay2文件系统

overlay2是一个文件系统,**其实就是docker镜像和容器的文件化的表达。是docker镜像和容器概念的具体实现。**具体如下:

复制代码
 overlay2 的结构                                                                                                                                                            
  /mnt/docker/overlay2/                                                                                                                                                      
  ├── <layer_hash_1>/           ← 层1(只读层)                                                                                                                              
  │   ├── diff/                 ← 这一层的实际文件                                                                                                                           
  │   └── link                                                                                                                                                               
  ├── <layer_hash_2>/           ← 层2(只读层)                                                                                                                              
  │   ├── diff/                                                                                                                                                              
  │   └── link                                                                                                                                                               
  ├── ...                                                                                                                                                                    
  ├── <container_layer_hash>/   ← RW 可写层                                                                                                                                  
  │   ├── diff/                 ← 这里就是 OCularSD 文件所在                                                                                                                 
  │   │   └── var/tmp/.OCularSD/                                                                                                                                             
  │   ├── merged/               ← 所有层合并后的视图(容器看到的完整 fs)                                                                                                    
  │   └── work/                                                                                                                                                              
  └── l/                        ← 符号链接索引(较短路径名)               

docker命令对应的操作

|---------------|------------------------------------------|
| 操作命令 | 对应操作 |
| docker commit | RW 可写层打包 → 变成一个只读层,加到镜像栈顶 |
| docker save | 导出整个镜像(所有只读层),不做 CoW,逐层校验 checksum |
| docker export | 只导 RW 可写层的 merged 视图(完整的目当前文件系统快照),丢弃历史层 |
| docker import | 把一个文件系统快照作为一个只读层导入 → 创建不完整的镜像(只有一层,无历史) |
| docker rm | 清理 RW 可写层 + merged/ + work/ |
| docker rmi | 清理镜像的所有只读层(如果没被其他镜像引用的话) |

问题分析及解决方法

我碰到的问题,就是在我试图清理一个容器,即清理overlay2文件系统下的可写层的文件时,报了权限错误。而这个文件var/tmp/.OCularSD不在只读层(即不是镜像带来的),那么说明是我的容器写入的,且赋予了极高的权限。

经过一系列查询,这个文件是在容器启动时,宿主机上的 nvidia-container-toolkit 钩子 会在每个使用了 --gpus all 的容器中都触发 OCularSD 的初始化。这些目录和文件具有特殊的保护属性------即使是 root 也无法删除或修改(chattr +i immutable flag 或类似底层的保护机制),这是 NVIDIA 有意为之的 DRM 防篡改设计。

解决方法是,将这个路径挂载为临时的内存文件系统,容器停止就会自动释放。

复制代码
docker run \
  --gpus all \
  --tmpfs /var/tmp:noexec,nosuid,size=1G \
  ... 其他参数 ...
相关推荐
用户3126874877206 小时前
线程池到底怎么管理线程的?从 ThreadPoolExecutor 到拒绝策略全链路拆解
java
cpolar技术支持6 小时前
Kafka Streams 窗口统计怎么验收:本地跑订单流聚合,用 cpolar 给同事看只读结果页
java·docker·kafka·cpolar·kafka streams
爱读源码的大都督6 小时前
DeepSeek面试官问:生产RAG系统回答不准确,该如何定位和优化?这样回答,能让面试官当场给你Offer!
java·后端·python
杨运交7 小时前
[069][公共模块]Spring Boot 全局异常处理与参数校验实战(下):校验异常精细化处理与 WebFlux 适配
java·spring boot·后端
广州灵眸科技有限公司7 小时前
瑞芯微(EASY EAI)RV1126B 星闪使用
运维·人工智能·科技·docker·容器
努力努力再努力wz7 小时前
【Docker入门系列】:从 Namespace 到 CGroup:一文理解容器资源控制、cgroup v2 与 Memory Controller 实战
运维·docker·容器
玉&心7 小时前
通过helm在k8s上面一键部署前端和后端代码
云原生·容器·kubernetes·helm
Raas1007 小时前
MAI Gateway(魔芋企业级AI网关)对比分析:AI网关和OpenRouter区别?企业级能力差距一览
java·服务器·网络·人工智能·gateway·ai网关·mai gateway
APItesterCris7 小时前
告别人工盯品!借助 Open‑Claw 快速搭建电商商品全自动监控与数据分析系统(完整实操代码)
java·大数据·前端·数据库
青山木7 小时前
Hot 100 --- 跳跃游戏 II
java·数据结构·算法·leetcode·贪心算法