【问题标题】:Docker volumes not mounting/linkingDocker 卷未安装/链接
【发布时间】:2019-11-08 19:22:26
【问题描述】:

我在 Docker Desktop for Windows 中。我正在尝试使用 docker-compose 作为构建容器,它在其中构建我的代码,然后代码位于我的本地构建文件夹中。构建过程肯定是成功的;当我exec 进入我的容器时,文件就在那里。但是,我的本地文件夹没有任何反应——没有创建 build 文件夹。

docker-compose.yml

version: '3'
services:
  front_end_build:
    image: webapp-build
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - 5000:5000
    volumes:
      - "./build:/srv/build"

Dockerfile

FROM node:8.10.0-alpine

EXPOSE 5000

# add files from local to container
ADD . /srv

# navigate to the directory
WORKDIR /srv

# install dependencies
RUN npm install --pure-lockfile --silent

# build code (to-do: get this code somewhere where we can use it)
RUN npm run build

# install 'serve' and launch server.
# note: this is just to keep container running
# (so we can exec into it and check for the files).
# once we know that everything is working, we should delete this.
RUN npx serve -s -l tcp://0.0.0.0:5000 build

我还尝试删除为文件夹提供服务的最后一行。然后我确实得到了一个构建文件夹,但是那个文件夹是空的。

更新: 我还尝试了多阶段构建:

FROM node:12.13.0-alpine AS builder
WORKDIR /app
COPY . .
RUN yarn
RUN yarn run build

FROM node:12.13.0-alpine
RUN yarn global add serve
WORKDIR /app
COPY --from=builder /app/build .
CMD ["serve", "-p", "80", "-s", "."]

当我的卷未设置(或设置为诸如 ./build:/nonexistent 之类的不存在的源目录)时,应用程序会正确提供,并且我在本地计算机上得到一个空的构建文件夹(空的,因为源文件夹不存在)。

但是,当我将 volumes 设置为 - "./build:/app"(构建文件的正确来源)时,我不仅在本地计算机上得到了一个空的 build 文件夹,而且在容器中的 app 文件夹也是空的!

似乎正在发生的事情类似于 1. Container被构建,它在builder中构建文件。 2. 文件从生成器复制到第二个容器。 3.volumes被链接了,然后因为我本地的build文件夹是空的,它在容器上的链接文件夹也变成了空!

我已尝试重置我的共享云端硬盘凭据,但无济于事。

我该怎么做?!?!

【问题讨论】:

    标签: docker docker-compose dockerfile docker-volume


    【解决方案1】:

    我相信您误解了主机卷的工作方式。卷定义:

    ./build:/srv/build
    

    在撰写文件中,将在容器内的/srv/build 的主机上挂载./build。这发生在运行时,而不是在您的映像构建期间,因此在执行 Dockerfile 指令之后。映像中的任何内容都不会复制到主机,并且挂载目录中的任何文件都不可见(这是 Linux 挂载命令的标准行为)。

    如果您需要将文件从容器复制回主机,有多种选择。

    1. 您可以执行步骤来填充构建文件夹作为容器运行的一部分。这在开发中很常见。为此,您的 CMD 可能会变成一个包含多个要运行的命令的脚本,最后一步是 exec 来运行您的应用程序。

    2. 您可以切换到命名卷。 Docker 将使用图像的内容初始化这些。甚至可以为主机上的文件夹创建命名绑定挂载,这与主机挂载几乎相同。有一个命名绑定挂载的示例in my presentation here

    3. 您的容器入口点可以在启动时将文件复制到主机挂载。这通常出现在将在未知情况下运行的图像上,例如詹金斯图像做到了这一点。我也在我的示例base image 中的保存/加载卷脚本中执行此操作。

    【讨论】:

      【解决方案2】:

      tl;dr; 卷不会在构建阶段挂载,只有在运行容器时才会挂载。您可以运行命令docker run <image id> -v ./build/:/srv/build cp -R /app /srv/build将数据复制到本地磁盘


      当 Docker 构建映像时,它会在 临时 容器中执行所有操作,您在 Dockerfile 中的每个命令都在单独的容器中运行,每个命令都会创建一个最终成为最终映像的层.

      这样做的结果是构建期间的数据流是单向的,您无法将卷从主机挂载到容器中。当您运行构建时,您将看到 Sending build context to Docker daemon,因为您的本地 Docker CLI 正在发送 context(您在 docker build 之后指定的路径,通常是表示当前目录的 .)到Docker 守护进程(实际工作的进程)。要记住的一个关键点是 Docker CLI (docker) 实际上并没有做任何工作,它只是将命令发送到 Docker 守护进程dockerd。构建阶段不应该更改本地系统上的任何内容,容器旨在仅将更改封装到容器映像中,并为您提供可以一致重复使用的构建快照,知道内容是一样的。

      【讨论】:

        猜你喜欢
        • 2015-08-18
        • 1970-01-01
        • 2018-01-14
        • 1970-01-01
        • 2015-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多