如何使用Docker改善Angular 5项目的构建时间?

kyo*_*kyo 10 nginx docker dockerfile angular-cli angular5

我正在努力改善自动化的构建时间.现在只需要14分钟来构建前端.

在此输入图像描述


这是我到目前为止所得到的

web.dockerfile

### STAGE 1: Build ###
FROM node:9.3.0-alpine as builder

COPY package.json ./

RUN npm set progress=false && npm config set depth 0 && npm cache clean --force

## Storing node modules on a separate layer will prevent unnecessary npm installs at each build
RUN npm i
RUN mkdir /web
RUN cp -R ./node_modules ./web

WORKDIR /web

COPY . .

RUN $(npm bin)/ng build --prod --build-optimizer

### STAGE 2: Setup ###

FROM nginx:1.13.8-alpine

COPY nginx.conf /etc/nginx/nginx.conf
COPY site.conf /etc/nginx/conf.d/default.conf
RUN rm -rf /usr/share/nginx/html/*

COPY --from=builder /web/dist /usr/share/nginx/html/

RUN touch /var/run/nginx.pid && \
  chown -R nginx:nginx /var/run/nginx.pid && \
  chown -R nginx:nginx /var/cache/nginx && \
  chown -R nginx:nginx /usr/share/nginx/html

USER nginx
Run Code Online (Sandbox Code Playgroud)

RUN $(npm bin)/ ng build --prod --build-optimizer

上面这一行几乎占用了整个99%的构建时间.


.angular-cli.json

{
  "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
  "project": {
    "name": "web"
  },
  "apps": [{
    "root": "src",
    "outDir": "dist",
    "assets": [
      "assets",
      "favicon.ico"
    ],
    "index": "index.html",
    "main": "main.ts",
    "polyfills": "polyfills.ts",
    "test": "test.ts",
    "tsconfig": "tsconfig.app.json",
    "testTsconfig": "tsconfig.spec.json",
    "prefix": "app",
    "styles": [
      "styles.css",
      "../node_modules/bootstrap/dist/css/bootstrap.min.css",
      "../node_modules/ngx-toastr/toastr.css",
      "../src/assets/css/style.css",
      "../src/assets/css/colors/blue.css"

    ],
    "scripts": [
      "../node_modules/jquery/dist/jquery.min.js",
      "../node_modules/popper.js/dist/umd/popper.min.js",
      "../node_modules/bootstrap/dist/js/bootstrap.min.js",
      "../node_modules/jquery-slimscroll/jquery.slimscroll.min.js",
      "../node_modules/pace-js/pace.min.js"
    ],
    "environmentSource": "environments/environment.ts",
    "environments": {
      "dev": "environments/environment.ts",
      "prod": "environments/environment.prod.ts"
    }
  }],
  "e2e": {
    "protractor": {
      "config": "./protractor.conf.js"
    }
  },
  "lint": [{
      "project": "src/tsconfig.app.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "src/tsconfig.spec.json",
      "exclude": "**/node_modules/**"
    },
    {
      "project": "e2e/tsconfig.e2e.json",
      "exclude": "**/node_modules/**"
    }
  ],
  "test": {
    "karma": {
      "config": "./karma.conf.js"
    }
  },
  "defaults": {
    "styleExt": "css",
    "component": {}
  }
}
Run Code Online (Sandbox Code Playgroud)

Environement

DockerCloud连接到我的AWS

AWS:EC2 micro


结果

这个dockerfile完美运行,并且它可以构建成功.

但是建造需要大约14分钟.


问题

怎么会改变这个呢?

是因为我的实例处理器太少了吗?


我现在对任何建议持开放态度.

任何提示/建议/帮助将非常感谢!

Ton*_*y3n 4

[长话;博士]

  • 使用卷来存储node_modules和.npm
  • 并行化部分流程(例如测试)
  • 使用相对路径时要小心
  • 不要使用 复制整个项目COPY . .。相对路径问题和可能的信息泄漏。
  • 创建一个仅包含用于构建和测试的核心依赖项的单独映像(例如 npm、java、chrome-driver、libgconf2)。
  • 配置管道以使用此映像
  • 让 CI 克隆存储库并将您的项目复制到容器中以进行构建和测试
  • dist根据故障率归档构建的文件(例如)和标签
  • 创建一个新映像,其中包含足够运行您构建的文件的内容。

[长版]

您的 npm 依赖项很可能会被重新下载和/或您的 docker 镜像会为您运行的每个构建进行重建。

与其将文件复制到 Docker 镜像中,不如为模块和缓存挂载卷,这样以后包含的其他依赖项就不需要再次下载。您应该考虑为其创建卷的典型目录是 npm_modules(一个用于全局,一个用于本地)和 .npm(缓存)。

您的package.json文件被复制到 root 中/,并且相同的文件package.json被复制到/webwith中COPY . .

的初始运行npm i正在安装到中/,并且您将再次运行它/web。您下载了两次依赖项,但是这些模块会/用于任何用途吗?npm i无论如何,您似乎在和中使用相同的 package.json ng build,因此相同的事情被执行了两次, ([编辑] - 似乎不会ng build重新下载包)但 node_modules 在中不可用,/因此npm i命令创建另一个并重新下载所有包。

您在根目录中创建一个web目录/,但还有其他命令指示相对路径./web。您确定事情在正确的地方运行吗?如果您使用相对路径,则不能保证程序会在您想要的目录中查找。虽然它似乎适用于此映像,但相同的做法在可能具有不同初始工作目录的其他映像中将不一致。

[可能是也可能不是相关信息]

虽然我没有使用 Bitbucket 进行自动化构建,但在运行 Jenkins 管道时我遇到了类似的问题。Jenkins 将项目放在不同的目录中,以便每次运行时,所有依赖项都会重新下载。我最初以为该项目会在其中/home/agent/project,但实际上它被放置在其他地方。pwd我在构建步骤中使用and命令找到了将项目复制到的目录npm cache verify,然后将卷安装到正确的位置。您可以在构建时生成的日志中查看输出。

您可以通过展开管道页面中的部分来查看输出。

在此输入图像描述

如果每次运行时都会重建映像,请单独构建映像,然后将映像推送到注册表。配置管道文件以使用您的图像。您应该尽可能尝试使用已经可用的基础镜像,除非您需要的其他依赖项在基础镜像中不可用(例如 alpine 的 apk 包,而不是 npm。npm 依赖项可以存储在卷中)。如果您要使用公共注册表,请勿存储任何可能包含敏感数据的文件。配置您的管道,以便使用卷和/或使用机密来安装事物。

对测试和构建步骤进行基本重组。

       Image on Docker Hub
              |
              |
           ---|-------------------------------------|
           |                       |                |
           V                       V                |
Commit -- build (no test) ---> e2e tests (no build)-]--+--> archive build --> (deploy/merge/etc)
                         |           _______________|  ^
                         |           v                 |
                         |-> unit tests (no build)---->|
Run Code Online (Sandbox Code Playgroud)

您不需要完全遵循它,但它应该让您了解如何使用并行步骤来分离事物并缩短完成时间。