Docker 在使用卷时写入主机文件系统的速度很慢。这使得像 npm install
这样的任务在 NodeJS 中非常痛苦。如何从卷中排除 node_modules
文件夹以便构建更快?
最佳答案
众所周知,Docker 在 macOS 上的挂载卷支持速度慢得可怜(click here for more info)。对于我们的 Node 开发人员来说,这意味着启动您的应用程序非常慢,因为必需的 node install
命令。好吧,这里有一个快速的小技巧来解决这种缓慢的问题。
首先,快速浏览一下项目:
(来源:fredlackey.com)
长话短说,我正在将项目根目录 (./
) 中的所有内容映射到容器的一个卷。这允许我使用小部件,如 gulp.watch()
和 nodemon
来自动重启项目,或者在我修改文件时注入(inject)任何新代码。
这是实际问题的 50%!
因为项目的root被映射到容器内的工作目录,调用npm install
导致node_modules
将在根目录中创建...实际上是在主机文件系统上。这就是 Docker 令人难以置信的缓慢安装卷将项目踢到 nads 的地方。事实上,一旦您发出 docker-compose up
,您可能会花费长达 五分钟 等待您的项目出现。
“您的 Docker 设置一定是错误的!”
正如您将看到的,Docker 对于这个小项目来说非常普通。
首先,你的 Dockerfile:
FROM ubuntu:16.04
MAINTAINER "Fred Lackey" <fred.lackey@gmail.com>
RUN mkdir -p /var/www \
&& echo '{ "allow_root": true }' > /root/.bowerrc \
&& apt-get update \
&& apt-get install -y curl git \
&& curl -sL https://deb.nodesource.com/setup_6.x | bash - \
&& apt-get install -y nodejs \
&& npm install -g bower gulp gulp-cli jshint nodemon npm-check-updates
VOLUME /var/www
EXPOSE 3000
当然还有心爱的 docker-compose.yml
:
version: '2'
services:
uber-cool-microservice:
build:
context: .
container_name: uber-cool-microservice
command:
bash -c "npm install && nodemon"
volumes:
- .:/var/www
working_dir: /var/www
ports:
- "3000"
正如您所看到的,这个测试项目是精简的、平均的,并且按预期工作....除了 npm install
是 sloooooooooow。
此时,调用 npm install
会导致项目的所有依赖项都被安装到卷 中,众所周知,这是主机文件系统。这就是痛苦的来源。
“那你说的‘绝招’是什么?”
如果我们可以从将项目的根目录映射到卷但以某种方式排除 node_modules
并允许写入它就好了Docker 的联合文件系统在容器内。
根据 Docker 的文档,从卷装载中排除文件夹是不可能的。我想这是有道理的。
但是,这实际上是可能的!
技巧?简单的! 额外的卷安装!
通过向 Dockerfile
添加一个行:
FROM ubuntu:16.04 MAINTAINER "Fred Lackey" RUN mkdir -p /var/www \ && echo '{ "allow_root": true }' > /root/.bowerrc \ && apt-get update \ && apt-get install -y curl git \ && curl -sL https://deb.nodesource.com/setup_6.x | bash - \ && apt-get install -y nodejs \ && npm install -g bower gulp gulp-cli jshint nodemon npm-check-updates VOLUME /var/www VOLUME /var/www/node_modules EXPOSE 3000
... and one line to the docker-compose.yml
file ...
version: '2' services: uber-cool-microservice: build: context: . container_name: uber-cool-microservice command: bash -c "npm install && nodemon" volumes: - .:/var/www - /var/www/node_modules working_dir: /var/www ports: - "3000"
That's it!
In case you missed it, we added:
VOLUME /var/www/node_modules
和
- /var/www/node_modules
说什么!?!?
简而言之,额外的卷会导致 Docker 在容器(文件夹等)内创建内部 Hook ,并等待它被挂载。由于我们从不安装文件夹,我们基本上欺骗 Docker 只写入容器内的文件夹。
最终结果是我们能够挂载项目的根目录,利用像 gulp.watch()
和 nodemon
这样的工具,同时编写node_modules
到更快的联合文件系统。
Quick Note re:
node_modules
:
For some reason, while using this technique, Docker will still create thenode_modules
folder within the root of your project, on the host file system. It simply will not write to it.
关于node.js - 如何在使用挂载卷时提高 Docker 构建速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41710327/