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

6

Docker使用卷时,写入主机文件系统速度缓慢。这使得像NodeJS中的npm install这样的任务变得异常痛苦。我如何从卷中排除node_modules文件夹,以加快构建速度?

1个回答

18

众所周知,Docker在macOS上的挂载卷支持非常慢(点击此处了解更多信息)。对于我们这些Node开发人员来说,这意味着由于必须执行node install命令,启动应用程序非常缓慢。好吧,这里有一个快速的小技巧可以绕过这种缓慢。

首先,快速查看项目:

超酷微服务示例
(来源: fredlackey.com)

简而言之,我将项目根目录(./)中的所有内容映射到容器的一个卷中。这使我可以使用小部件,例如gulp.watch()nodemon自动重新启动项目,或在修改文件时注入任何新代码。 这只是实际问题的50%! 因为将项目的根目录映射到容器内的工作目录,所以调用npm install会在根目录中创建node_modules...实际上是在主机文件系统上。这就是Docker的挂载卷异常缓慢的地方。按照现有方式,一旦输入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非常缓慢之外。
目前,调用npm install会导致所有项目依赖项安装到卷中,而我们都知道,这是主机文件系统。这就是痛苦的来源。
“那么你提到的‘技巧’是什么呢?”
如果只能从卷挂载中受益,同时排除node_modules并允许其写入容器内部的Docker联合文件系统,那该多好啊。
根据Docker的文档,无法从卷挂载中排除一个文件夹,这也许是有道理的。
然而,这实际上是可以做到的!
技巧?简单!只需在Dockerfile中添加一行即可:
从ubuntu:16.04开始
维护者 "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
卷 /var/www 卷 /var/www/node_modules
暴露3000端口

...还有一个行在docker-compose.yml文件中...

版本:'2'
服务:
超酷微服务: 构建: context: . 容器名称:uber-cool-microservice 命令: bash -c "npm install && nodemon" 卷: - .:/var/www - /var/www/node_modules 工作目录:/var/www 端口: - "3000"

就这样!

如果你错过了,我们添加了:

VOLUME /var/www/node_modules

并且

- /var/www/node_modules

什么!?!?

简而言之,额外的容量会导致Docker在容器内部创建钩子(文件夹等),并等待其被挂载。由于我们从未挂载该文件夹,因此我们基本上欺骗Docker只是在容器内部写入文件夹。

最终结果是,我们能够挂载项目的根目录,利用像gulp.watch()nodemon这样的工具,同时将node_modules的内容写入更快的联合文件系统中。

关于node_modules的快速说明:
由于某种原因,使用此技术时,Docker仍会在主机文件系统中的项目根目录中创建node_modules文件夹,但不会向其中写入任何内容。

原文发表在我的博客上。


不错的解决方法。您知道在使用 yarn 工作区的单体库设置中,是否可以针对嵌套的 node_modules 目录执行类似操作吗? - Michael

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接