Ewa*_*ren 11 node.js node-modules docker docker-compose
我最近一直在尝试 dockerize(用于开发和稍后用于生产)一个 MERN 堆栈应用程序,Node.js(更特别是 node_modules)和 Docker 之间的交互让我有点失望。在整个问题中,我将用于开发的计算机指定为“主机”。
在开发时,有没有一种方法可以在不将主机的 node_modules 文件夹安装到容器的情况下对 Node.js 应用程序进行 Dockerize 化?
我可以想到使用 Docker(及其 docker-compose 实用程序)进行开发的 3 大优势(我将其称为第 1、2 和 3 点):
docker-compose up数据库、后端和前端都已启动并运行)。前 2 点在 dockerizing 一个 Node.js 应用程序时没有问题;但是我觉得第三个在开发环境中更难实现,因为依赖项在 Node 中的工作方式及其 node_modules 功能。让我解释 :
这是我简化的项目文件夹结构:
project
? docker-compose.yml
?
????node-backend
? ? Dockerfile
? ? package.json
? ? server.js
? ?
? ????src
? ? ? ...
? ?
? ????node_modules
? ? ...
?
????react-frontend
? ...
Run Code Online (Sandbox Code Playgroud)
根据我的尝试以及我在互联网上的文章和教程中看到的内容,基本上有 3 种使用 Docker 开发 Node.js 的方法。在所有 3 种方法中,我假设我使用以下 Dockerfile 来描述我的应用程序的图像:
# node-backend/Dockerfile
FROM node:lts-alpine
WORKDIR /usr/src/app
COPY package*.json ./
RUN npm install
COPY . ./
EXPOSE 8000
CMD [ "npm", "start" ]
Run Code Online (Sandbox Code Playgroud)
开发时,将主机的整个代码文件夹(包括 node_modules)挂载到容器中。该docker-compose.yml文件通常如下所示(为清楚起见,不包括数据库或 react 应用程序配置):
# ./docker-compose.yml
version: "3"
services:
backend:
build: ./node-backend/
ports:
- 8000:8000
volumes:
- ./node-backend:/usr/src/app
Run Code Online (Sandbox Code Playgroud)
这种方法是最简单的安装和使用用于发展:代码的主机和容器,热重装(带之间同步nodemon例如)的作品,依赖性主机和容器(无需在每个重建容器之间同步npm install some-module上主机)。
但是,它不尊重第 3 点:由于主机的 node_modules 也安装到容器中,它们可能包含一些针对主机操作系统编译的特定于平台的部分(例如node-gyp插件)(在我的情况下) 、macOS 或 Windows) 而不是容器的操作系统 (Alpine Linux)。
挂载主机的源代码文件夹,但这次创建一个卷(命名或匿名)来保存容器的 node_modules,防止它们被主机的 node_modules 隐藏。
# ./docker-compose.yml
version: "3"
services:
backend:
build: ./node-backend/
ports:
- 8000:8000
volumes:
- ./node-backend:/usr/src/app
- /usr/src/app/node_modules
Run Code Online (Sandbox Code Playgroud)
通过这种方法,现在考虑了第 3 点:我们确保开发中容器使用的 node_modules 文件夹是专门为容器创建的,因此包含适当的特定于平台的代码。
但是,安装新的依赖项很痛苦:
npm install直接在容器中运行您的s(使用docker exec),但是除非您每次都手动执行,否则不会在您的主机上安装依赖项。重要的是还必须为 IDE(在我的情况下为 VSCode)在本地安装它们以提供自动完成、linting、避免“缺少模块”警告......npm install在你的主机上运行你的s 但你每次都必须重建你的 Docker 镜像,以便容器的 node_modules 是最新的,这很耗时。最后一种方法是直接在容器内进行开发,这意味着不需要挂载主机,您只需要创建一个卷(这次让它命名,但我认为匿名也可以?)以便更改您的代码和 node_modules 是持久的。我还没有尝试过这种方法,所以我不确定docker-compose.yml文件会是什么样子,但可能是以下几行:
# ./docker-compose.yml
version: "3"
services:
backend:
build: ./node-backend/
ports:
- 8000:8000
volumes:
- backend-data:/usr/src/app
volumes:
backend-data:
Run Code Online (Sandbox Code Playgroud)
这种方法也符合第3 点,但是在容器内进行远程开发比在主机上进行常规开发更难设置(尽管 VSCode 显然简化了该过程)。此外,源代码版本控制(即使用 Git)似乎有点烦人,因为您必须将主机的 SSH 标识传递到您的容器才能允许它访问您的远程存储库。
如您所见,我还没有找到一种结合了我正在寻找的所有优点的方法。我需要一种易于设置和在开发中使用的方法;这尊重第 3 点,因为它是容器化理念和目的的一个重要方面;这不会使容器和主机之间的 node_modules 同步成为头疼的问题,同时保留了 IDE 的所有功能(Intellisense、linting 等)。
有什么我完全想念的吗?你们有什么解决这个问题的方法?
我建议查看这个项目https://github.com/BretFisher/node-docker-good-defaults,它通过使用技巧支持本地和容器node_modules,但与某些框架(例如strapi)不兼容:
container node_modules被放置在应用程序的上一级文件夹(节点的算法来解析 deps,递归地在应用程序的文件夹中查找 node_modules),并且它们从应用程序文件夹中删除host node_modules放置在应用程序文件夹内(那里没有更改)bind-mount the package.json + lock在容器(记住应用程序中的一个文件夹)到主机(应用程序文件夹)之间专门添加额外的文件,以便它们始终保持同步=>因此,当您这样做时docker exec npm install dep,您只需要npm install dep在主机上并最终重建您的docker映像。| 归档时间: |
|
| 查看次数: |
1083 次 |
| 最近记录: |