【问题标题】:How to prevent a non-empty host folder from overriding a mounted container folder?如何防止非空主机文件夹覆盖已安装的容器文件夹?
【发布时间】:2022-08-24 21:30:59
【问题描述】:

我正在尝试使用 Docker 为 Laravel 项目编译我的资产。

因此,我创建了一个名为 npm 的服务,它是从以下 Dockerfile 构建的:

FROM node:16-alpine as node

WORKDIR /usr/src

ADD ./resources ./resources
COPY [\"package.json\", \"package-lock.json\", \"vite.config.js\", \"./\"]

RUN npm install --global cross-env
RUN npm install
RUN npm run build

另外,我正在使用以下 Docker-compose 配置

  node:
    build:
      context: ./
      dockerfile: ./services/nodejs/Dockerfile
    working_dir: /var/www
    container_name: \"nodejs\"
    volumes:
      - ./:/var/www
    tty: true
    depends_on:
      - php

虽然服务构建成功,但似乎我的主机目录(非空)覆盖了我的节点容器的内容。所以,最终我没有 \"node_modules\" 目录,我编译的资产和资源丢失了。

所以我该怎么做? 我认为我可以先将我的主机文件夹的内容复制到容器中,然后删除我的主机文件夹的内容,然后运行我的脚本,然后将其复制回来。但这似乎是一件非常耗时的事情。这种情况的最佳做法是什么?我确定我不是第一个将全栈 Laravel 项目 docker 化的人。提前致谢

  • 你正在使用一个卷为./:/var/www,它基本上可以做你不想要的
  • 您正在使用卷,因此这适用于您的开发环境。然后,您的容器中不需要 node_modules - 只需正常构建它
  • @apokryfos 是的,完全正确。我这样做的原因是因为我希望将节点容器中的文件夹复制回我的主机。我的意思是我必须以某种方式将 \"node_modules\" 和 \"resources\" 文件夹从我的节点容器复制到我的主机上,但我不知道该怎么做。
  • 对于生产,您不会使用卷,并将源复制到容器中,然后像现在一样在容器中构建它,但您不需要将其复制回主机。您最终获得的 docker 映像将是您在 docker 主机(实际上是任何 docker 主机)上运行应用程序所需的
  • 我个人在容器外部进行拉取,然后在这样做之前将文件复制到容器中,我这样做的原因是因为 git 通常不安装在容器中

标签: node.js laravel docker npm


【解决方案1】:

它看起来不像你 COPY 将你的应用程序代码放入容器中。这使您处于需要绑定挂载的位置,但是由于主机目录缺少一些构建的部分,因此最终的容器映像是不完整的。

这里有一个特别重要的细节是关于使用这个容器作为你的构建序列的一部分,我将回到这里。

首先要做的是确保您需要的所有东西都在图像本身中。

FROM node:16-alpine as node
WORKDIR /usr/src
RUN npm install --global cross-env

# run `npm install` first to avoid rebuilds if `package.json` is unchanged
COPY ["package.json", "package-lock.json", "vite.config.js", "./"]
RUN npm install

# then copy in the rest of the application
# (make sure `node_modules` and `build` are in `.dockerignore`)
COPY ./ ./
RUN npm run build

# and explain how to run the container (*)
CMD npm run start

然后在您的docker-compose.yml 文件中,您不需要指定volumes:,因为代码已经在您的图像中。您同样不需要声明 working_dir:,因为 Dockerfile 已经设置了 WORKDIR。您的 Compose 文件的这一部分可能会缩减为

  node:
    build:
      context: ./
      dockerfile: ./services/nodejs/Dockerfile
    tty: true    # actually needed?
    depends_on:
      - php

不过,我认为您实际上并不想要这个容器,因为

我正在尝试使用 Docker 为 Laravel 项目编译我的资产。

在这种情况下,您可以将此 Dockerfile(并且它必须是完整的自包含 Dockerfile)用作multi-stage build 的一部分。将此 Dockerfile 放在 PHP 应用程序 Dockerfile 的开头并为其命名,然后您可以COPY 将构建的资产从一个阶段转移到另一个阶段。

FROM node:16-alpine AS node # <-- `AS somename` is important
...
RUN npm run build
# no specific need for a CMD here

FROM php:fpm
...
COPY --from=node /usr/src/build ./static/

同样,由于这将在 Docker 映像构建时填写,因此不要使用 volumes: 挂载覆盖映像内容,这一点很重要。

如果你这样做,那么根本就没有“节点容器”,你可以直接从你的 docker-compose.yml 文件中删除它。对于此设置,您不需要长时间运行的服务器,您只需要在构建时让 Node 可用于运行编译步骤,并将其包含在 Dockerfile 阶段就足够了。

【讨论】:

    猜你喜欢
    • 2014-05-26
    • 1970-01-01
    • 1970-01-01
    • 2021-03-17
    • 1970-01-01
    • 2013-10-29
    • 2013-09-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多