容器内使用Python Docker SDK构建Docker镜像报OSError如何解决
问题原因
Python Docker SDK 执行镜像构建时,会先在**运行SDK代码的当前环境(也就是你现在跑Python的容器内部)**遍历path参数指定目录下的所有文件,将这些文件打包为tar格式的构建上下文,再发送给Docker daemon。遍历过程中SDK会尝试读取路径下的每一个文件,没有做虚拟文件系统的自动跳过逻辑。
你遇到的/proc/1/mem是procfs虚拟文件系统下PID为1的进程内存映射文件,属于内核暴露的虚拟文件,普通进程没有读取权限,SDK尝试读取时就会抛出OSError。
触发这个问题的常见前置场景:
- 代码里传入的
path="."对应的当前工作目录就是容器根目录/,遍历上下文时自然会扫到/proc下的虚拟文件 - 启动运行Python代码的容器时,将宿主机/容器自身的
/proc、/sys这类系统虚拟目录挂载到了构建上下文路径的子目录下,被SDK遍历到 - 没有配置
.dockerignore排除规则,构建上下文没有做路径裁剪,把无关的系统路径包含了进去
注意:如果你是用挂载/var/run/docker.sock的Docker-out-of-Docker(DooD)模式跑构建,不要误以为构建上下文是在Docker daemon侧读取的——上下文打包逻辑始终在运行SDK客户端的环境里执行,和daemon在哪没有关系。
排查步骤
- 在运行Python代码的容器内执行
pwd,确认代码里path="."对应的绝对路径,检查该路径下是否包含/proc、/sys、/dev这类系统虚拟目录 - 核对启动该容器的run参数、compose配置,检查是否存在把宿主机根目录、系统目录挂载到容器内构建上下文路径下的配置
- 在构建上下文路径下执行
ls -la,梳理目录结构,确认是否存在不需要参与镜像构建的系统路径、大体积目录、敏感文件目录
修复方案
- 最优方案:新建一个专用的构建目录,只把
my.Dockerfile和镜像构建需要的业务文件、依赖文件放到这个目录下,SDK调用时把path参数指向这个专用目录,不要直接用通用工作目录.作为构建路径,从根源上避免无关文件被扫入上下文 - 如果必须使用当前目录作为构建路径,在上下文根目录创建
.dockerignore文件,写入排除规则把无关路径全部剔除,Python Docker SDK会自动识别该文件,规则和原生docker build命令的.dockerignore完全兼容,至少需要加入以下基础排除项:
/proc /sys /dev /run __pycache__/ *.pyc *.pyo *.pyd .env .git/ # 按需补充其他不需要进入构建上下文的路径
- 如果你使用DooD模式运行容器,调整挂载配置,不要把宿主机的根目录、系统虚拟目录挂载到容器内的构建上下文路径下
- 快速验证:新建一个空测试目录,把
my.Dockerfile放到测试目录下,临时把SDK调用的path参数改成这个测试目录路径,执行构建如果不报错,就可以确认是上下文包含无权限读取的虚拟文件导致的问题
内容的提问来源于stack exchange,提问作者wiseboar
相关产品推荐
相关产品推荐

