[英]Docker-compose: node_modules is not present in docker volume
[英]How to handle node_modules with docker-compose in a monorepo project
我正在使用 yarn 工作区运行一个 Node.js monorepo 项目。 文件结构如下所示:
workspace_root
node_modules
package.json
apps
appA
node_modules
package.json
appB
node_modules
package.json
libs
libA
dist
node_modules
package.json
所有应用程序都是独立的,但它们都需要libA
我正在使用 docker-compose 运行所有这些应用程序。我的问题是如何正确处理所有依赖项,因为我不希望node_modules
文件夹与主机同步。 在本地,当我在工作区根目录运行yarn install
时,它会安装所有项目的所有依赖项,填充不同的node_modules
。 在 docker-compose 中,理想情况下每个应用程序都不应知道其他应用程序。
到目前为止,我的方法有效但不理想且可扩展性不强。
version: "3.4"
services:
# The core is in charge of installing dependencies for ALL services. Each service must for wait the core, and then
# just do their job, not having to handle install.
appA:
image: node:14-alpine
volumes: # We must load every volumes for install
- .:/app # Mount the whole workspace structure
- root_node_modules:/app/node_modules
- appA_node_modules:/app/apps/appA/node_modules
- appB_node_modules:/app/apps/appB/node_modules
- libA_node_modules:/app/libs/libA/node_modules
working_dir: /app/apps/appA
command: [sh, -c, "yarn install && yarn run start"]
appB:
image: node:14-alpine
volumes: # We must load every volumes for install
- .:/app # Mount the whole workspace structure
- root_node_modules:/app/node_modules
- appB_node_modules:/app/apps/appB/node_modules
working_dir: /app/apps/appB
command: [sh, -c, "/scripts/wait-for-it.sh appA:4001 -- yarn run start"]
# And so on for all apps....
volumes:
root_node_modules:
driver: local
appA_node_modules:
driver: local
appB_node_modules:
driver: local
libA_node_modules:
driver: local
我看到的主要缺点:
appA
负责安装所有应用程序的依赖项。我想避免为开发而构建,因为每次添加依赖项时都必须完成它,这很麻烦而且会减慢你的速度
附在我创建的这个答案示例存储库的底部。
基本上利用纱线工作区,我为每个构建时使用的包/模块创建了一个通用的 dockerfile。
为每个 docker 映像复制整个存储库(这不是以后发布产品的好做法,您可能希望为此创建不同的流程)
因此,如果将整个存储库安装到每个正在运行的服务上,您可以观察库中的更改(在存储库中我已经配置了 nodemon,因此它也会观察 lib 文件)
总结一下:
docker-compose build
。 无论如何,一旦图书馆安顿下来并且更改频率降低,我就不会担心重复的docker-compose build
,你会发现你的自我重建更少(但我也给出了解决方案的任何方式)
我相信在你的情况下,你应该做的最好的事情是构建你自己的 Docker 图像而不是使用节点中的图像。 所以,让我们做一些编码。 首先,您应该告诉 Docker 忽略 node_modules 文件夹。 为此,您需要为每个应用程序创建一个 .dockerignore 和一个 Dockerfile。 因此,您的结构可能如下所示:
workspace_root
node_modules
package.json
apps
appA
.dockerignore
node_modules
Dockerfile
package.json
appB
.dockerignore
node_modules
Dockerfile
package.json
libs
libA
.dockerignore
dist
node_modules
Dockerfile
package.json
在 .dockerignore 文件中,您可以在下面重复相同的值。
node_modules/
dist/
这将使 docker 在构建过程中忽略这些文件夹。 现在是 Dockerfile 本身。 因此,为了确保您的项目在容器内正常运行,最佳做法是在容器内构建项目,而不是在容器外。 它避免了许多“在我的电脑上工作正常”的问题。 也就是说,Dockerfile 的一个示例可能是这样的:
# build stage
FROM node:14-alpine AS build-stage
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
# production stage
FROM nginx:stable-alpine as production-stage
COPY --from=build-stage /app/dist /usr/share/nginx/html
COPY prod_nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
在那种情况下,我也使用了 nginx,以确保用户通过适当的网络服务器访问容器。 最后我也会让 prod_nginx.conf。 但这里的要点是,您可以只构建该图像并将其发送到 dockerhub,然后从那里在您的 docker-compose.yml 中使用它,而不是使用原始节点图像。
Docker-compose.yml 会是这样的:
version: "3.4"
services:
appA:
image: mydockeraccount/appA
container_name: container-appA
port:
- "8080:80"
....
现在,正如承诺的那样,prod_nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer"'
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name _ default_server;
index index.html;
location / {
root /usr/share/nginx/html;
index index.html;
try_files $uri $uri/ /index.html;
}
}
}
希望能帮助到你。 最好的祝福。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.