使用Docker-outside-Docker的VS Code开发容器文件挂载变目录问题
环境配置
文件夹结构
[VS Code Dev Container文件夹结构]
devcontainer.json 配置
{ "name": "flowable-poc", "dockerComposeFile": "docker-compose.yml", "service": "app", "workspaceFolder": "/workspaces", "forwardPorts": [8090], "features": { "ghcr.io/devcontainers/features/docker-outside-of-docker:1": {}, } }
docker-compose.yml 配置
version: '3.8' volumes: maven-repo: services: app: container_name: flowable-poc-javadev build: context: . dockerfile: Dockerfile volumes: - ..:/workspaces:cached - ../settings.xml:/home/vscode/.m2/settings.xml:ro - ${LINEVIEW_FLOWABLE_LICENSE_PATH}:/home/vscode/.flowable/flowable.license - maven-repo:/home/vscode/.m2 user: vscode command: sleep infinity
问题现象
在开发容器内部的.devcontainer/licence目录下执行以下命令:
docker run -it --rm -v flowable.license:/root/.flowable/flowable.license ubuntu bash -c "ls -la /root/.flowable"
执行结果显示目标路径下的flowable.license是一个目录而非文件:
drwxr-xr-x 2 root root 4096 Nov 26 11:53 flowable.license
疑问:是否必须使用主机路径?但这样会很麻烦,因为Java应用可以直接引用开发容器内的文件和目录。
原因与解决办法
核心问题
你使用的-v flowable.license:/root/.flowable/flowable.license语法中,Docker将flowable.license识别为Docker卷的名称,而非开发容器内的文件路径。由于主机Docker中不存在同名卷,它会自动创建一个空目录卷挂载到目标路径,这就是你看到目录的原因。
另外需要注意:你启用了docker-outside-of-docker特性,开发容器内的docker命令实际上调用的是主机的Docker守护进程,所以挂载路径参数指向的是主机文件系统的路径,而非开发容器内的路径。
解决方法
方法1:使用主机对应路径绑定挂载
找到flowable.license在主机上的绝对路径(因为开发容器通过- ..:/workspaces挂载了项目根目录,主机路径为项目根目录下的.devcontainer/licence/flowable.license),修改命令为:
docker run -it --rm -v /path/to/your/project/.devcontainer/licence/flowable.license:/root/.flowable/flowable.license ubuntu bash -c "ls -la /root/.flowable"
替换/path/to/your/project为你本地项目的实际绝对路径。
方法2:通过Docker卷中转文件
如果不想依赖主机路径,可先将开发容器内的文件复制到Docker卷,再挂载该卷:
# 创建专用卷 docker volume create flowable-license-vol # 从开发容器复制文件到卷 docker cp flowable-poc-javadev:/workspaces/.devcontainer/licence/flowable.license flowable-license-vol:/flowable.license # 挂载卷到新容器 docker run -it --rm -v flowable-license-vol:/root/.flowable ubuntu bash -c "ls -la /root/.flowable"
这样/root/.flowable目录下会直接出现flowable.license文件。
方法3:利用容器卷共享
通过--volumes-from参数让新容器共享开发容器的挂载卷,直接访问目标文件:
docker run -it --rm \ --volumes-from flowable-poc-javadev \ ubuntu bash -c "cp /workspaces/.devcontainer/licence/flowable.license /root/.flowable/ && ls -la /root/.flowable"
--volumes-from会挂载开发容器的所有卷,新容器因此能访问到/workspaces路径下的文件。
内容的提问来源于stack exchange,提问作者Chris Rollings

