繁体   English   中英

docker-compose 中的卷安装如何工作

[英]How volume mounting works in docker-compose

我有一个非常简单的 node js 应用程序,项目结构如下所示。

index.js

package.json

package-lock.json

Dockerfile

FROM node:12.18.2-alpine
WORKDIR /test-app
COPY package.json package-lock.json ./
RUN npm i
COPY . ./
EXPOSE 3000
ENTRYPOINT [ "node", "index.js" ]

docker-compose.yml

version: '3.2'

services:
  test-app:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - .:/test-app
      - "test_app_node_modules:/test-app/node_modules"
volumes:
  test_app_node_modules:
    driver: local

如果您查看docker-compose.yml文件中的volumes部分,首先我将主机上的当前目录挂载到容器上的test-app目录。 这表示:

  1. 我当前目录中的任何文件或目录都将反映在容器目录中,对容器目录所做的任何更改也将反映回主机目录。
  2. 这意味着在node_modules构建期间安装在容器的test-app目录中的 node_modules 也被覆盖。

volumes部分的下一步被命名为卷 这表示:

  1. 它应该将容器内的test-app/node_modules中的所有内容复制到test_app_node_modules卷。 但是test-app/node_modules是空的,因为第 1 步覆盖了它。
  2. 这意味着我们创建了一个空卷并将其安装到容器中。

如果是这样,它应该会导致缺少依赖项错误,但我的应用程序运行正常。 我不确定我从哪里得到 node_modules。

另外,我在主机目录中看到一个空的 node_modules 文件夹。 我认为这背后的原因是"test_app_node_modules:/test-app/node_modules"在容器中查找node_modules ,但它不存在,因此它创建了一个,结果,它被反射回主机目录。

我无法掌握卷安装的想法。 这里的流程是什么? 当没有节点模块时,如何开始将其存储到卷中?

在纯粹的机械层面上,这里发生了几件事。

Docker 对卷安装进行排序。 它知道/test-app/node_modules/test-app的子目录。 所以 Docker 将

  1. 创建从主机目录到容器目录的绑定挂载
  2. 如果需要作为挂载点,请创建一个空的node_modules目录
  3. 在该挂载点上挂载 Docker 卷

这是主机上的空node_modules目录的来源: Docker 在完成绑定挂载后将其创建为挂载点,因此那里的更改会反映在主机内容中。

当命名卷被挂载到容器中时,当且仅当命名卷为空时, Docker 会将镜像中的内容复制到卷中 这个特定步骤忽略了容器中已经安装了一个卷。 (如果卷是匿名卷,这也适用,您在其他节点示例中可以看到;它不适用于主机绑定挂载,如果卷中有旧内容,或者在 Kubernetes 上。)

所以这就是为什么这显然有效。 作为此问题说明的其他答案,这不是 Docker 的特别有效使用。 如果您需要实时开发设置,我还建议您只删除这些volumes: ,并直接在主机上运行node index.js

in your docker file you have first created WORKDIR /test-app inside it you have added a package.json file and installed dependencies RUN npm i so now there is already node_module present inside docker image itself.

之后使用COPY. ./ COPY. ./您正在向 docker 图像添加额外的文件,如index和其他所有文件。

如果您将删除整个volume部分,那么它也将工作,因为您的 docker 图像包含代码及其依赖项。

version: '3.2'

services:
  test-app:
    build: .
    ports:
      - "3000:3000"

我不确定您为什么要以这种方式设置 docker 容器,但它不起作用的原因是对卷和绑定安装的工作方向的误解。 你说:

它应该将容器内的 test-app/node_modules 中的所有内容复制到 test_app_node_modules 卷。 但是 test-app/node_modules 是空的,因为第 1 步覆盖了它。

这是从前到后。 使用卷时,该被复制到目标中。 这就是卷的全部意义——它们旨在让您即使重建容器也能保留数据。 如果您使用绑定安装卷,则主机目录将复制到 docker 容器中的目标中 所以你在主机上的test_app_node_modules目录被复制到容器中的/test-app/node_modules中。 大概test_app_node_modules包含您的所有节点模块,因此您不会收到有关缺少模块的错误。

只有在您的容器实际运行时,容器中运行的代码才能更新/删除卷中的数据 - 而不是在您构建容器时。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM