简体   繁体   English

Docker 卷未安装/链接

[英]Docker volumes not mounting/linking

I'm in Docker Desktop for Windows.我在 Windows 的 Docker 桌面上。 I am trying to use docker-compose as a build container, where it builds my code and then the code is in my local build folder.我正在尝试使用 docker-compose 作为构建容器,它在其中构建我的代码,然后代码位于我的本地构建文件夹中。 The build processes are definitely succeeding;构建过程肯定是成功的; when I exec into my container, the files are there.当我exec到我的容器中时,文件就在那里。 However, nothing happens with my local folder -- no build folder is created.但是,我的本地文件夹没有任何反应——没有build文件夹。

docker-compose.yml docker-compose.yml

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

Dockerfile 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

I also tried removing the final line that serves the folder.我还尝试删除为文件夹提供服务的最后一行。 Then I actually did get a build folder, but that folder was empty.然后我确实得到了一个构建文件夹,但那个文件夹是空的。

UPDATE: I've also tried a multi-stage 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", "."]

When my volumes aren't set (or are set to, say, some nonexistent source directory like ./build:/nonexistent ), the app is served correctly, and I get an empty build folder on my local machine (empty because the source folder doesn't exist).当我的卷未设置(或设置为,例如,一些不存在的源目录,如./build:/nonexistent )时,应用程序被正确提供,并且我在本地机器上得到一个空的构建文件夹(空的,因为源文件夹不存在)。

However when I set my volumes to - "./build:/app" (the correct source for the built files), I not only wind up with an empty build folder on my local machine, the app folder in the container is also empty!但是,当我将volumes设置为- "./build:/app" (构建文件的正确来源)时,我不仅在本地机器上得到了一个空的build文件夹,容器中的app文件夹也是空的!

It appears that what's happening is something like 1. Container is built, which builds the files in the builder.看起来正在发生的事情类似于 1. 构建容器,它在构建器中构建文件。 2. Files are copied from builder to second container. 2. 文件从生成器复制到第二个容器。 3. Volumes are linked, and then because my local build folder is empty, its linked folder on the container also becomes empty! 3. Volumes被链接了,然后因为我本地的build文件夹是空的,它在容器上的链接文件夹也变成了空的!

I've tried resetting my shared drives credentials, to no avail.我试过重置我的共享驱动器凭据,但无济于事。

How do I do this???!我该怎么做呢???!

I believe you are misunderstanding how host volumes work.我相信您误解了主机卷的工作方式。 The volume definition:体积定义:

./build:/srv/build

In the compose file will mount ./build from the host at /srv/build inside the container.在 compose 文件中,将在容器内的/srv/build的主机上挂载./build This happens at run time, not during your image build, so after the Dockerfile instructions have been performed.这发生在运行时,而不是在您的映像构建期间,因此在执行 Dockerfile 指令之后。 Nothing from the image is copied out to the host, and no files in the directory being mounted in top of will be visible (this is standard behavior of the Linux mount command).映像中的任何内容都不会复制到主机,并且挂载在其顶部的目录中的任何文件都不可见(这是 Linux 挂载命令的标准行为)。

If you need files copied back out of the container to the host, there are various options.如果您需要将文件从容器复制回主机,有多种选择。

  1. You can perform your steps to populate the build folder as part of the container running.您可以执行步骤来填充构建文件夹作为容器运行的一部分。 This is common for development.这在开发中很常见。 To do this, your CMD likely becomes a script of several commands to run, with the last step being an exec to run your app.为此,您的CMD可能会变成一个包含多个要运行的命令的脚本,最后一步是运行您的应用程序的exec

  2. You can switch to a named volume.您可以切换到命名卷。 Docker will initialize these with the contents of the image. Docker 将使用图像的内容初始化这些。 It's even possible to create a named bind mount to a folder on your host, which is almost the same as a host mount.甚至可以为主机上的文件夹创建命名绑定挂载,这与主机挂载几乎相同。 There's an example of a named bind mount in my presentation here . 我在此处的演示文稿中有一个命名绑定挂载的示例。

  3. Your container entrypoint can copy the files to the host mount on startup.您的容器入口点可以在启动时将文件复制到主机挂载。 This is commonly seen on images that will run in unknown situations, eg the Jenkins image does this.这在将在未知情况下运行的图像上很常见,例如 Jenkins 图像就是这样做的。 I also do this in my save/load volume scripts in my example base image .我也在我的示例基本映像中的保存/加载卷脚本中执行此操作。

tl;dr; tl;博士; Volumes aren't mounted during the build stage, only while running a container.卷不会在构建阶段挂载,只有在运行容器时才会挂载。 You can run the command docker run <image id> -v./build/:/srv/build cp -R /app /srv/build to copy the data to your local disk您可以运行命令docker run <image id> -v./build/:/srv/build cp -R /app /srv/build将数据复制到本地磁盘


While Docker is building the image it is doing all actions in ephemeral containers, each command that you have in your Dockerfile is run in a separate container, each making a layer that eventually becomes the final image.虽然 Docker 正在构建映像,但它正在临时容器中执行所有操作,您在 Dockerfile 中的每个命令都在单独的容器中运行,每个命令都会创建一个最终成为最终映像的层。

The result of this is that the data flow during the build is unidirectional, you are unable to mount a volume from the host into the container.这样做的结果是构建期间的数据流是单向的,您无法将卷从主机安装到容器中。 When you run a build you will see Sending build context to Docker daemon , because your local Docker CLI is sending the context (the path you specified after the docker build , ususally . which represents the current directory) to the Docker daemon (the process that actually does the work). When you run a build you will see Sending build context to Docker daemon , because your local Docker CLI is sending the context (the path you specified after the docker build , ususally . which represents the current directory) to the Docker daemon (the process that实际上做的工作)。 One key point to remember is that the Docker CLI ( docker ) doesn't actually do any work, it just sends commands to the Docker Daemon dockerd .要记住的一个关键点是 Docker CLI ( docker ) 实际上并没有做任何工作,它只是向 Docker 守护进程dockerd发送命令。 The build stages shouldn't change anything on your local system, the container is designed to encapsulate the changes only into the container image, and give you a snapshot of the build that you can reuse consistently, knowing that the contents are the same.构建阶段不应更改本地系统上的任何内容,容器旨在仅将更改封装到容器映像中,并为您提供可以一致重用的构建快照,知道内容是相同的。

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

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