node.js - 如何在使用挂载卷时提高 Docker 构建速度

标签 node.js docker docker-compose docker-volume

Docker 在使用卷时写入主机文件系统的速度很慢。这使得像 npm install 这样的任务在 NodeJS 中非常痛苦。如何从卷中排除 node_modules 文件夹以便构建更快?

最佳答案

众所周知,Docker 在 macOS 上的挂载卷支持速度慢得可怜(click here for more info)。对于我们的 Node 开发人员来说,这意味着启动您的应用程序非常慢,因为必需的 node install 命令。好吧,这里有一个快速的小技巧来解决这种缓慢的问题。

首先,快速浏览一下项目:

uber-cool-microservice example
(来源: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 installsloooooooooow

此时,调用 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 the node_modules folder within the root of your project, on the host file system. It simply will not write to it.

The original article is on my blog.

关于node.js - 如何在使用挂载卷时提高 Docker 构建速度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41710327/

相关文章:

node.js - node.js 的 Openshift 端口

javascript - 在nodejs中发送表单数据时req.files不存在

node.js - 查找对象是否在预保存钩子(Hook) Mongoose 中更改

docker - 使用Letsencrypt的Docker HAProxy SSL终止

docker - 使用 Docker chown 容器目录 (ubuntu - mysql/mysql-server)

node.js - 将数据发布到数据库后如何重定向到另一个页面?

Docker 通过命令或文件设置环境变量

php - 设置从主机到 docker 容器的 PHP 路径

python - 滑子/RabbitMQ : OSError: Server unexpectedly closed connection

docker - 我可以通过使用通用图像来节省内存吗?