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 \
  ... 其他参数 ...
相关推荐
codingPower1 小时前
JAVA后端安全进阶:基于HMAC-SHA256+Nonce+Timestamp的API防重放攻击方案
java·开发语言·spring boot·安全
寂夜了无痕1 小时前
IntelliJ IDEA 高效配置:新建文件自动生成作者与时间注释
java·ide·intellij-idea
leonidZhao2 小时前
Java 25新特性:模块导入申明
java
tellmewhoisi2 小时前
Docker Compose最巧妙的设计之一——内置的服务发现机制
docker·服务发现
AI服务老曹2 小时前
解耦异构算力:基于 Docker 与 GB28181/RTSP 的边缘计算 AI 视频管理平台架构设计(支持源码交付)
人工智能·docker·边缘计算
weixin_489690022 小时前
【IDEA 2025.2.4】 Maven 仅能手动 Reload All Maven Projects 问题解决
java·maven·intellij-idea
雨辰AI2 小时前
MySQL 迁移至达梦 DM9 完整改造指南|99% SQL 零改动
java·开发语言·数据库·sql·mysql·政务
golang学习记2 小时前
Intellij IDEA 2026重磅更新!开发体验大升级
java·ide·intellij-idea
弹简特2 小时前
【Java项目-轻聊】05-AI赋能设计接口文档
java·开发语言