Windows10+WSL2下Docker Compose挂载外部目录无法识别文件求助
我近期开始学习Docker与Docker Compose,为练习将一个小型Python脚本容器化。该脚本从指定输入目录读取文件、处理后保存至指定输出目录,要求将主机的输入输出目录挂载为容器内的卷。但容器内的脚本无法识别挂载目录中的文件。
我的系统是Windows10,使用带WSL2的Docker Desktop。项目目录结构如下:
-./src -app.py -Dockerfile -docker-compose.yaml
Dockerfile内容如下:
FROM python:3.9 WORKDIR /app COPY . /app/ RUN apt-get update && apt-get install ffmpeg libsm6 libxext6 -y RUN python3 -m pip install -r requirements.txt CMD ["python3", "app.py"]
我通过docker build -t laz2pcd .构建镜像。最初的docker-compose.yaml配置如下:
services: laz2pcd: image: laz2pcd volumes: - /mnt/c/laz_test:/var/data_in - /mnt/c/pcd_test:/var/data_out environment: - INTENSITY=TRUE - OFFSET_X=0 - OFFSET_Y=0 - OFFSET_Z=0
容器无报错但未执行任何操作,脚本日志显示无文件可处理。当我将主机目录移至docker-compose.yaml所在的项目目录,并修改卷配置为:
volumes: - ./src:/app - ./laz_test:/var/data_in - ./pcd_test:/var/data_out
后,脚本终于能识别并处理文件。我无法理解该现象,想请教:为何只能使用项目目录下的文件夹?为何需要挂载./src:/app?
一、为啥只能用项目目录下的文件夹?
核心是WSL2和Docker Desktop的文件权限与挂载规则:
- Docker Desktop在WSL2模式下,默认只开放两类目录的挂载权限:一是WSL2自身文件系统里的目录,二是Windows系统中被Docker Desktop授权共享的磁盘目录。你最初用的
/mnt/c/laz_test是WSL2映射的Windows C盘目录,但如果这个目录所在的C盘没在Docker Desktop的文件共享列表里勾选,容器就没有权限访问其中的文件,自然读不到内容。 - 当你把目录移到docker-compose.yaml所在的项目目录时,Docker Desktop会自动识别并授权当前项目所在的目录,所以挂载后容器能正常读取里面的文件。
你可以去Docker Desktop的设置里确认:打开Settings > Resources > File Sharing,看看C盘(或者你项目所在的磁盘)有没有被勾选,勾上之后,Windows里其他目录也能通过/mnt/c/xxx的方式挂载给容器用。
二、为啥需要挂载./src:/app?
这个操作其实不是必须的,但在你的场景里生效,是因为两个坑:
- 镜像构建上下文错了:看你的项目结构,Dockerfile在
./src里,但你执行docker build的时候,是不是在根目录跑的命令?如果是,那构建上下文是根目录,不是./src,这时候COPY . /app/会把根目录下的文件(比如docker-compose.yaml)复制到容器的/app,而不是./src里的app.py和依赖文件。挂载./src:/app相当于把本地正确的脚本目录覆盖到容器里,让容器能运行正确的代码。 - 脚本路径配置问题:如果你的
app.py里用了相对路径读取文件,而镜像构建时因为上下文错误,导致脚本里的路径和容器里挂载的/var/data_in不匹配,挂载本地src目录后,直接用本地的脚本运行,就绕开了这个问题。
正确的做法是:构建镜像时,要么进入./src目录执行docker build -t laz2pcd .,要么在根目录执行docker build -t laz2pcd ./src,指定./src作为构建上下文。这样镜像里的/app就会包含正确的app.py和依赖,这时候不需要挂载./src:/app,只要数据目录挂载正确,容器就能正常处理文件。
内容的提问来源于stack exchange,提问作者onthebox

