向Docker添加卷,但排除子文件夹

Gol*_*den 170 docker dockerfile

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

到现在为止还挺好.

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

我想挂载/hostFolder到泊坞容器(无论是读写或只读并不重要,无论是对我的作品),但我希望把它列入/hostFolder/subFolder.我想排除这个,我也希望Docker容器能够对这个子文件夹进行更改,而不会在主机上更改它.

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

ker*_*nix 340

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

volumes:
   - './angularApp:/opt/app'
   - /opt/app/node_modules/
Run Code Online (Sandbox Code Playgroud)

因此,所有内容./angularApp都映射到/opt/app,然后我创建另一个挂载卷/opt/app/node_modules/,现在是空目录 - 即使在我的本地计算机./angularApp/node_modules中不是空的.

  • 你先生是绅士和学者.辉煌! (80认同)
  • 不要忘记尾随斜线!例如./ opt/app/node_modules不起作用,它将被./angularApp/node_modules覆盖 (16认同)
  • 请注意顺序很重要:如果你的镜像在 `/opt/app/node_modules/` 下有文件,如果你在父目录之后挂载它,它们将被忽略。例如,如果您想在图像中包含模块,但能够稍后刷新它,您将按以下顺序列出卷:`- /opt/app/node_modules/` 然后父`- './angularApp:/选择/应用'` (7认同)
  • 它可以工作,但我无法删除容器内的这些目录 例如:我需要用另一个同名目录替换`/opt/app/node_modules/`。发生错误:“音量繁忙” (5认同)
  • 谢谢!你救了我的一天!如果使用简单的docker,而不是compos,它看起来像:-v $ {pwd):/ build / -v / build / node_modules` (5认同)
  • 我找到了该文档,https://docs.docker.com/storage/volumes/#populate-a-volume-using-a-container。`如果您启动一个创建新卷的容器,如上所述,并且该容器待挂载的目录中有文件或目录(如上面的 /app/ ),则该目录的内容被复制到卷中。 (5认同)
  • 请注意,当您运行“docker-compose build”时,“node_modules”不会更新!我期望 `/opt/app/node_modules/` 始终与容器在该位置的所有内容保持同步。但内容仅在创建卷时才最初复制。因此,如果您的“package.json”发生更改并且重新构建容器,则卷中的“node_modules”将不再与容器同步。 (4认同)
  • 这个技巧曾经对我有用,但似乎不再适用,即使对于同一个 Compose 文件也是如此。好奇它是否也停止为其他人工作。 (3认同)
  • @RichardClayton感谢恭维:-) (2认同)
  • @kemix - 天才! (2认同)
  • 是的 @plinehan,它也停止为我工作。现在不确定如何忽略 node_modules。 (2认同)
  • 我注意到了一个奇怪的效果。如果我的主机没有“node_modules”文件夹,则在按此处所述运行包含卷的容器后,它将获得一个“空”“node_modules”文件夹。它与卷断开连接,因此此处的更改不会反映在容器中(很好)。*但是*对父文件夹的更改仍然存在,所以如果我取消链接/删除主机的“node_modules”,那么*容器的*也会被删除! (2认同)

Nat*_*e T 109

如果您希望docker-compose忽略子目录但持久化,则可以在以下位置执行以下操作docker-compose.yml:

volumes:
  node_modules:
services:
  server:
    volumes:
      - .:/app
      - node_modules:/app/node_modules
Run Code Online (Sandbox Code Playgroud)

这会将当前目录挂载为共享卷,但会挂载持久性docker卷来代替本地node_modules目录.这类似于@kernix的答案,但这将允许node_modulesdocker-compose up运行之间保持,这可能是期望的行为.

  • 命名卷是一种优越的方法.Protip:确保您没有使用带连字符的卷名.你将在调试噩梦中度过你生命的一小部分,但却发现你再次被一种荒谬的细微差别所愚弄. (16认同)
  • 如果有人为了理解*为什么*使用`node_modules:`命名卷'忽略"docker容器中的`/ app/node_modules`,可能会发现这篇文章有用[Docker如何处理多种挂载类型?](https: //stackoverflow.com/a/47873699/2235814) (3认同)
  • "请注意,docker-compose down会杀死这些持久卷." 在Docker for Mac v 17.0.5+(以及可能的旧版本)中并非如此.`docker-compose down`将删除容器,但是音量将持续到你运行类似`docker system prune的东西 (2认同)
  • 我不知道我是否做错了什么,但如果这样做,请启动容器,然后在主机上运行npm install,它也会更改容器内的node_modules。我无法想象为什么有人会想要这样做,但是我仍然在寻找更清洁的分隔。 (2认同)
  • @Renra遇到了完全相同的问题,即使我有命名的卷,我的主机也会不断覆盖node_modules ...导致了各种不兼容问题。放弃修复它并通过仅复制我的src文件夹而不是整个仓库来解决它 (2认同)

Fra*_*ong 14

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

volumes:
   - /hostFolder:/folder
   - /dev/null:/folder/fileToBeExcluded
Run Code Online (Sandbox Code Playgroud)

  • 我需要的完美解决方案(不将node_modules映射到主机,因为在Windows主机上破坏了符号链接的东西).指向/ dev/null不起作用,但创建一个空白目录并将其映射到完美的工作并解决了我遇到的问题 - 感谢这个想法. (6认同)
  • 这在 Docker for Mac 18.09.0 中不起作用:`无法启动服务 xxx:OCI 运行时创建失败:container_linux.go:348:启动容器进程导致“process_linux.go:402:容器初始化导致 \”rootfs_linux.go: 58: 将 \\\"/dev/null\\\" 安装到 rootfs \\\"/var/lib/docker/overlay2/d15ed56ad020d408c63a1f6a6365dbb88d5d3b78a4605980d3faa9861102ef21/merged:\一个目录到一个文件(或反之亦然)?检查指定的主机路径是否存在并且是预期的类型`。添加尾部斜杠没有帮助。 (3认同)
  • 请注意,这仅适用于排除文件!/dev/null 是一个文件,因此应该是目标,错误消息对此非常清楚:“您是否正在尝试将目录挂载到文件上(或反之亦然)?” 检查指定的主机路径是否存在并且是预期的类型。这并不完全是OP想要的,但它对我来说非常有用,因为我需要排除单个文件。 (2认同)

小智 14

对于那些试图在node_modules不被本地覆盖的地方获得良好工作流程的人来说,这可能会有所帮助。

  1. 更改您的 docker-compose 以将匿名持久卷安装到 node_modules 以防止您的本地覆盖它。这已在此线程中概述了几次。
services:
  server:
    build: .
    volumes:
      - .:/app
      - /app/node_modules
Run Code Online (Sandbox Code Playgroud)
  1. 这是我们遗漏的重要一点。在旋转堆栈时使用docker-compose -V. 如果没有这个,如果你添加了一个新的包并重建了你的镜像,它将使用node_modules你最初的 docker-compose 启动。
    -V, --renew-anon-volumes   Recreate anonymous volumes instead of retrieving
                               data from the previous containers.
Run Code Online (Sandbox Code Playgroud)

  • 关于“--renew-anon-volumes”的注释是一个重要的补充。在某些情况下,您希望挂载源代码文件夹并通过将其挂载为匿名卷来排除 node_modules 文件夹。该标志避免重复使用之前创建的匿名卷,以便正确反映对“package.json”的更改。 (4认同)
  • 使用此方法时,会在主机上创建一个空的“node_modules”目录。我们怎样才能避免这种情况呢? (4认同)

Adr*_*uat 13

首先,使用ADDDockerfile中的指令与使用卷(通过参数或Dockerfile中的指令)非常不同.在与命令只是把当时的文件的副本运行.在使用该命令创建新图像之前,不会更新这些文件.相比之下,使用卷实质上是说"此目录不应存储在容器映像中;而是使用主机上的目录"; 每当卷中的文件发生更改时,主机和容器都会立即看到它.-vdocker runVOLUMEADDCOPYdocker builddocker build

我不相信你可以使用卷实现你想要的东西,如果你想这样做,你将不得不重新考虑你的目录结构.

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

请记住,任何文件添加到图像使用COPYADD必须在IE或下方运行的目录中生成上下文中docker build的.

  • 我似乎找不到在“.dockerignore”文件中放入什么内容以排除子目录(甚至目录)的示例。鉴于这就是该文件的既定目的,这很奇怪。 (2认同)

DS.*_*DS. 12

使用 docker 命令行:

docker run \
    --mount type=bind,src=/hostFolder,dst=/containerFolder \
    --mount type=volume,dst=/containerFolder/subFolder \
    ...other-args...
Run Code Online (Sandbox Code Playgroud)

-v也可以使用该选项(归功于Bogdan Mart),但--mount更清晰和推荐


小智 7

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

volumes:
   - ./angularApp:/opt/app
   - .empty:/opt/app/node_modules/
Run Code Online (Sandbox Code Playgroud)


小智 5

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

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

Run Code Online (Sandbox Code Playgroud)

这是解决方案,/修复了node_modules之后的问题。


小智 5

我发现这个链接救了我:Working with docker bind mounts and node_modules。此工作解决方案将在 docker 卷管理器中
创建一个“排除”命名卷。卷名称“exclude”是任意的,因此您可以使用卷的自定义名称来代替“ exclude”

services:
    node:
        command: nodemon index.js
        volumes:
            - ./:/usr/local/app/
            # the volume above prevents our host system's node_modules to be mounted
            - exclude:/usr/local/app/node_modules/

volumes:
    exclude:
Run Code Online (Sandbox Code Playgroud)

您可以在官方文档中查看有关卷的更多信息- 使用卷与 docker compose