Docker已成为开发的必然工具。日常开发人员在容器化他们的应用程序方面面临着新的挑战。其中一个重要问题是将应用程序容器化以适应不同的环境。在 Node.js 中使用 Docker 制作多阶段构建。

你可以问我,为什么我们需要在 node.js 应用程序中进行多阶段构建。为什么我们不能只构建一个单阶段映像并将其部署到服务器?

我们正处于一个编译器和转译器起着至关重要作用的发展时代。特别是在javascript开发环境中。例如,TypeScriptBabel

多阶段构建之前

在多阶段构建的概念之前,应用程序将有两个Dockerfile。一个用于开发,另一个用于生产。这被称为 构建器模式。但是维护两个 Dockerfile 并不理想。

Dockerfile.dev

FROM node:10.15.2-alpine
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY . .
RUN npm run dev

Dockerfile

FROM node:10.15.2-alpine
WORKDIR /usr/src/app
COPY package.json ./
RUN npm install
COPY /usr/src/app/dist ./dist
EXPOSE 4002
CMD npm start

虽然,它解决了开发和生产镜像构建的问题。从长远来看,这将是昂贵的。它也会在本地磁盘中占用大量空间。

使用多阶段构建

多阶段构建将不同的环境Dockerfile合二为一,以创建生产构建。例如,Staging build 创建应用程序源代码的编译版本,最终构建包含部署在镜像容器中的编译版本。

让我们看一个使用 babel 和 MongoDB 为 Node.js 构建多阶段的示例。完整的源代码在这个存储库中可用

创建一个目录并使用 Express 和Babel初始化应用程序。

分期构建

FROM node:10.15.2-alpine
WORKDIR /usr/src/app
COPY package.json ./
COPY .babelrc ./
RUN npm install
COPY ./src ./src
RUN npm run build

上面的命令,将 node:10.15.2-alpine 作为基础镜像,并将所有源代码与 babel 配置一起复制。它构建编译后的代码并将其存储在容器中的 dist 文件夹中。

最终版本

FROM node:10.15.2-alpine
WORKDIR /usr/src/app
COPY package.json ./
COPY .babelrc ./
RUN npm install
COPY --from=0 /usr/src/app/dist ./dist
EXPOSE 4002
CMD npm start

此命令从先前的暂存构建中获取编译版本并将其存储在新的图像容器中。魔法发生在 COPY --fromu003d0

COPY --fromu003d0 行仅将先前阶段的构建工件复制到新阶段。

命名构建阶段

您可以命名它们并将其用作参考,而不是使用数字来引用构建阶段。例如,我们使用名称 appbuild 指定阶段构建

暂存 Docker 构建

FROM node:10.15.2-alpine AS appbuild
WORKDIR /usr/src/app
COPY package.json ./
COPY .babelrc ./
RUN npm install
COPY ./src ./src
RUN npm run build

最终泊坞窗构建

我们使用 COPY --fromu003dappbuild 引用以前的构建

FROM node:10.15.2-alpine
WORKDIR /usr/src/app
COPY package.json ./
COPY .babelrc ./
RUN npm install
COPY --from=appbuild /usr/src/app/dist ./dist
EXPOSE 4002
CMD npm start

完整的 Dockerfile

# Build Stage 1
# This build created a staging docker image 
#
FROM node:10.15.2-alpine AS appbuild
WORKDIR /usr/src/app
COPY package.json ./
COPY .babelrc ./
RUN npm install
COPY ./src ./src
RUN npm run build

# Build Stage 2
# This build takes the production build from staging build
#
FROM node:10.15.2-alpine
WORKDIR /usr/src/app
COPY package.json ./
COPY .babelrc ./
RUN npm install
COPY --from=appbuild /usr/src/app/dist ./dist
EXPOSE 4002
CMD npm start

一次,我们完成了 dockerfile。创建 docker compose 将多个容器链接在一起。

创建一个 docker-compose.yml 文件并添加以下内容,

version: "3"

services: 
  app:
    container_name: app
    restart: always
    build: .
    environment: 
      - PORT=4002
    ports: 
      - "4002:4002"
    links:
      - mongo
  mongo:
    container_name: mongo
    image : mongo
    volumes: 
      - ./data:/data/db
    ports: 
      - "27017:27017"        

之后,使用命令运行 docker compose,

docker-compose up

您可以看到 docker 构建了一个中间映像并使用它来构建最终映像。一旦构建了最后一个镜像,Docker 就会删除中间镜像。

完整的源代码在这个存储库中可用

Logo

CI/CD社区为您提供最前沿的新闻资讯和知识内容

更多推荐