向Docker添加一个卷,但不包括一个子文件夹


209

假设我的主机上有一个Docker容器和一个文件夹/hostFolder。现在,如果我要对这个文件夹添加到多克尔容器的体积,那么我可以通过使用这样做ADDDockerfile或安装它作为一个音量。

到目前为止,一切都很好。

现在/hostFolder包含一个子文件夹/hostFolder/subFolder

我想挂载/hostFolder到泊坞容器(无论是读写或只读不要紧,可以工作在我),但我希望把它列入/hostFolder/subFolder。我想排除这一点,我也希望Docker容器能够对此子文件夹进行更改,而不会在主机上也进行更改。

这可能吗?如果是这样,怎么办?


2
@AbhijitSarkar的评论不是很有建设性(也没有任何帮助)。
卡诺

1
@Kano这是评论,不是答案。
Abhijit Sarkar

Answers:


396

使用docker-compose我可以在本地使用node_modules,但是可以在docker容器中使用以下语法忽略它 docker-compose.yml

volumes:
   - './angularApp:/opt/app'
   - /opt/app/node_modules/

因此,所有内容./angularApp都映射到了/opt/app,然后我创建了另一个装载卷/opt/app/node_modules/,该装载卷现在是空目录-即使在我的本地机器./angularApp/node_modules上也不是空的。


3
它有效,但我无法删除容器中的这些目录。例如:我需要替换/opt/app/node_modules/为另一个具有相同名称的目录。错误发生:“繁忙”
Stepan Yudin

32
不要忘记后面的斜线!例如。/选择/应用/ node_modules不工作,这将是覆盖由./angularApp/node_modules
Stingus

3
该技巧曾经对我有用,但似乎不再适用,即使对于相同的Compose文件也是如此。好奇它是否也停止了为他人服务。
plinehan '18年

7
谢谢!你救了我的一天!如果使用简单的docker,而不是compos,它将看起来像: -v $(pwd):/build/ -v /build/node_modules
Bogdan Mart

3
我找到了文档docs.docker.com/storage/volumes/…If you start a container which creates a new volume, as above, and the container has files or directories in the directory to be mounted (such as /app/ above), the directory’s contents are copied into the volume.
hiroshi

118

如果要使子目录被docker-compose忽略但是持久的,则可以在以下步骤中执行以下操作docker-compose.yml

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules

这会将您的当前目录挂载为共享卷,但是将永久性docker卷挂载到本地node_modules目录中。这类似于@kernix的答案,但是这将允许node_modulesdocker-compose up两次运行之间持续存在,这可能是所需的行为。


20
命名卷是一种更好的方法。提示:请确保您未使用带连字符的卷名。您将在一生的噩梦中度过一生,却发现自己再次被一个荒谬的细微差别所迷惑。
–ustintheweb

3
“请注意,docker-compose down将杀死这些持久卷。” 在适用于Mac v 17.0.5+的Docker(可能还有旧版本)中,情况并非如此。docker-compose down将删除容器,但该卷将持续存在,直到运行类似docker system prune
BrDaHa

3
如果有人有兴趣了解为什么在Docker容器中使用node_modules:命名卷“忽略” /app/node_modules,可能会发现这篇文章很有用。docker 如何处理多种安装类型?
ira

3
我不知道我是否做错了什么,但是如果这样做,请启动容器,然后在主机上运行npm install,它也会更改容器内的node_modules。我无法想象为什么有人会这样做,但是我仍然在寻找更清洁的分隔。
雷拉

3
@Renra遇到了完全相同的问题,即使我有命名的卷,我的主机也将不断覆盖node_modules ...导致了各种不兼容问题。放弃修复它并通过仅复制我的src文件夹而不是整个存储库来解决它
dancypants

19

要排除文件,请使用以下命令

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded

6
我需要的完美解决方案(不要将node_modules映射到主机,因为symlink东西在Windows主机上坏了)。指向/ dev / null无效,但是创建一个空白目录并将其映射到该目录可以完美地解决我遇到的问题-感谢这个想法。
Liam Hammett

1
这并不在码头工人的Mac 18.09.0工作:Cannot start service xxx: OCI runtime create failed: container_linux.go:348: starting container process caused "process_linux.go:402: container init caused \"rootfs_linux.go:58: mounting \\\"/dev/null\\\" to rootfs \\\"/var/lib/docker/overlay2/d15ed56ad020d408c63a1f6a6365dbb88d5d3b78a4605980d3faa9861102ef21/merged\\\" at [...] unknown: Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type。添加斜杠没有帮助。
布莱斯

我可以确认它在使用Docker 18.09.3。的Ubuntu 16.04上都不起作用。
德克

那对我不起作用。它所做的全部工作就是将/dev/null设备文件复制到容器中。
Radon Rosborough

1
请注意,这仅适用于排除文件!/ dev / null是一个文件,因此应该是目标,错误消息对此非常清楚:Are you trying to mount a directory onto a file (or vice-versa)? Check if the specified host path exists and is the expected type。这并不是OP所要寻找的,但这对我非常有用,因为我需要排除单个文件。
阿维乌斯

13

首先,ADD在Dockerfile中使用指令与使用卷有很大不同(通过Dockerfile中的-v参数docker runVOLUME指令)。在ADDCOPY命令只是把当时的文件的副本docker build运行。在使用docker build命令创建新映像之前,不会更新这些文件。相比之下,使用卷实际上是在说:“该目录不应存储在容器映像中;而应在主机上使用目录”。只要更改卷中的文件,主机和容器都将立即看到它。

我不相信您可以使用卷来实现所需的功能,如果要执行此操作,则必须重新考虑目录结构。

但是,使用来实现非常简单COPY(应该首选ADD)。您可以使用.dockerignore文件排除子目录,也可以使用COPY所有文件RUN rm bla删除子目录。

请记住,使用COPY或添加到映像的任何文件都ADD必须在构建上下文内部,即在运行目录的内部或下方docker build


1
每天学习新知识:-)从构建上下文(而不是宿主)中进行COPY和ADD工作。可以使用一个卷来遮罩subFolder吗?OP希望挂载/ hostFolder(我认为),并使/ hostFolder / subFolder断开连接。如果每个都有一个VOLUME,但是只有hostFolder被“挂载”(-v),那么将subFolder更改隔离到容器上是否可以?
格雷格

我不确定,我从未尝试过嵌套卷。我不认为这是个好主意,但我必须研究一下。
Adrian Mouat 2015年

1
我似乎找不到任何在.dockerignore文件中放置什么以排除子目录(甚至目录)的示例。鉴于这是文件的既定目的,这很奇怪。
Lukas Oberhuber

1
一旦添加了任何文件,它们仍然会出现在某些层中。因此,如果对安全敏感,则删除它们将不会帮助您隐藏它们或减小图像大小(因为它们将位于基础层中)。squash图层有一些选项。一个是github.com/goldmann/docker-squash,另一个是oc ex dockerbuildopenshift项目中使用的。
akostadinov

6

看起来旧的解决方案不再起作用了(至少对我而言)。不过,创建一个空文件夹并将目标文件夹映射到该文件夹​​很有帮助。

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/

docker-compose 1.25.0-rc3文件语法v3 对我也不起作用。
thisismydesign

6

使用docker命令行:

docker run \
    --mount type=bind,src=/hostFolder,dst=/containerFolder \
    --mount type=volume,dst=/containerFolder/subFolder \
    ...other-args...

-v也可以使用该选项(贷记给Bogdan Mart),但--mount更明确和推荐使用


6

对于也有问题的人,node_modules文件夹仍然会从本地系统覆盖,反之亦然

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules/

这是解决方案,其解决方案是在/node_modules之后添加尾随。


0

要排除包含在计算机卷中的已装入文件,您必须通过将卷分配给该文件来覆盖它。在您的配置文件中:

services:
  server:
    build : ./Dockerfile
    volumes:
      - .:/app

dockerfile中的一个示例:

# Image Location
FROM node:13.12.0-buster
VOLUME /app/you_overwrite_file
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.