OpenShift 上的现代应用程序,第 2 部分:链式构建

大家好! 这是我们系列文章的第二篇文章,我们将在其中展示如何在 Red Hat OpenShift 上部署现代 Web 应用程序。

OpenShift 上的现代应用程序,第 2 部分:链式构建

在上一篇文章中,我们稍微介绍了新的 S2I(源到映像)构建器映像的功能,该映像专为在 OpenShift 平台上构建和部署现代 Web 应用程序而设计。 然后我们对快速部署应用程序的主题感兴趣,今天我们将了解如何使用 S2I 映像作为“纯”构建器映像并将其与相关 OpenShift 程序集结合起来。

干净的建设者形象

正如我们在第 XNUMX 部分中提到的,大多数现代 Web 应用程序都有一个所谓的构建阶段,该阶段通常执行代码转译、多文件串联和缩小等操作。 作为这些操作的结果获得的文件 - 这是静态 HTML、JavaScript 和 CSS - 存储在输出文件夹中。 该文件夹的位置通常取决于所使用的构建工具,对于 React,这将是 ./build 文件夹(我们将在下面更详细地讨论这一点)。

源到图像 (S2I)

在这篇文章中,我们不会涉及“什么是 S2I 以及如何使用它”这个主题(您可以阅读有关此的更多信息 这里),但重要的是要清楚此过程中的两个步骤,以了解 Web App Builder 映像的作用。

组装阶段

组装阶段本质上与运行 docker build 并最终得到新的 Docker 映像时发生的情况非常相似。 因此,当在 OpenShift 平台上开始构建时,就会发生此阶段。

对于 Web App Builder 映像,它负责安装应用程序的依赖项并运行构建。 汇编脚本。 默认情况下,构建器映像使用 npm run build 构造,但这可以通过 NPM_BUILD 环境变量覆盖。

正如我们之前所说,已完成的、已构建的应用程序的位置取决于您使用的工具。 例如,对于 React,这将是 ./build 文件夹,对于 Angular 应用程序,这将是 project_name/dist 文件夹。 而且,如上一篇文章所示,默认设置为构建的输出目录的位置可以通过 OUTPUT_DIR 环境变量覆盖。 好吧,由于输出文件夹的位置因框架而异,您只需将生成的输出复制到映像中的标准文件夹,即 /opt/apt-root/output。 这对于理解本文的其余部分很重要,但现在让我们快速看看下一个阶段 - 运行阶段。

运行阶段

当对组装阶段创建的新映像调用 docker run 时,就会发生此阶段。 在 OpenShift 平台上部署时也会发生同样的情况。 默认 运行脚本 使用 服务模块 提供位于上述标准输出目录中的静态内容。

此方法适合快速部署应用程序,但通常不建议以这种方式提供静态内容。 好吧,由于实际上我们只提供静态内容,因此我们不需要在图像中安装 Node.js - 一个 Web 服务器就足够了。

换句话说,组装时我们需要一件事,执行时我们需要另一件事。 在这种情况下,链式构建就派上用场了。

链式构建

这就是他们写的 链式构建 在 OpenShift 文档中:

“两个程序集可以链接在一起,一个程序集生成已编译的实体,另一个程序集将该实体托管在用于运行该实体的单独映像中。”

换句话说,我们可以使用 Web App Builder 映像来运行我们的构建,然后使用 Web 服务器映像(相同的 NGINX)来提供我们的内容。

因此,我们可以将 Web App Builder 镜像用作“纯”构建器,同时拥有一个小型运行时镜像。

现在让我们通过一个具体的例子来看一下。

对于训练,我们将使用 简单的反应应用程序,使用 create-react-app 命令行工具创建。

它将帮助我们将一切整合在一起 OpenShift 模板文件.

让我们更详细地查看该文件,并从参数部分开始。

parameters:
  - name: SOURCE_REPOSITORY_URL
    description: The source URL for the application
    displayName: Source URL
    required: true
  - name: SOURCE_REPOSITORY_REF
    description: The branch name for the application
    displayName: Source Branch
    value: master
    required: true
  - name: SOURCE_REPOSITORY_DIR
    description: The location within the source repo of the application
    displayName: Source Directory
    value: .
    required: true
  - name: OUTPUT_DIR
    description: The location of the compiled static files from your web apps builder
    displayName: Output Directory
    value: build
    required: false

这里的一切都非常清楚,但值得注意的是 OUTPUT_DIR 参数。 对于我们示例中的 React 应用程序,无需担心,因为 React 使用默认值作为输出文件夹,但对于 Angular 或其他应用程序,需要根据需要更改此参数。

现在让我们看一下 ImageStreams 部分。

- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-builder  // 1 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: react-web-app-runtime  // 2 
  spec: {}
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: web-app-builder-runtime // 3
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: nodeshift/ubi8-s2i-web-app:10.x
- apiVersion: v1
  kind: ImageStream
  metadata:
    name: nginx-image-runtime // 4
  spec:
    tags:
    - name: latest
      from:
        kind: DockerImage
        name: 'centos/nginx-112-centos7:latest'

看一下第三张和第四张图片。 它们都被定义为 Docker 镜像,你可以清楚地看到它们来自哪里。

第三张图片是 web-app-builder,它来自 nodeshift/ubi8-s2i-web-app,标记为 10.x 码头工人中心.

第四个是带有最新标签的 NGINX 映像(版本 1.12) 码头工人中心.

现在让我们看一下前两张图片。 它们在开始时都是空的,并且仅在构建阶段创建。 第一个图像,react-web-app-builder,将是一个组装步骤的结果,该组装步骤将结合 web-app-builder-runtime 图像和我们的源代码。 这就是为什么我们在该镜像的名称中添加了“-builder”。

第二个镜像——react-web-app-runtime——将是结合 nginx-image-runtime 和 React-web-app-builder 镜像中的一些文件的结果。 该映像也将在部署期间使用,并且仅包含我们应用程序的 Web 服务器和静态 HTML、JavaScript、CSS。

使困惑? 现在让我们看一下构建配置,它会变得更清晰一些。

我们的模板有两种构建配置。 这是第一个,它非常标准:

  apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-builder
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-builder:latest // 1
    source:   // 2 
      git:
        uri: ${SOURCE_REPOSITORY_URL}
        ref: ${SOURCE_REPOSITORY_REF}
      contextDir: ${SOURCE_REPOSITORY_DIR}
      type: Git
    strategy:
      sourceStrategy:
        env:
          - name: OUTPUT_DIR // 3 
            value: ${OUTPUT_DIR}
        from:
          kind: ImageStreamTag
          name: web-app-builder-runtime:latest // 4
        incremental: true // 5
      type: Source
    triggers: // 6
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - imageChange: {}
      type: ImageChange

正如您所看到的,带有标签 1 的行表示此构建的结果将放置在我们之前在 ImageStreams 部分中看到的同一个react-web-app-builder 图像中。

标记为 2 的行告诉您从哪里获取代码。 在我们的例子中,这是一个 git 存储库,位置、ref 和上下文文件夹由我们上面看到的参数确定。

标记为 3 的行是我们在参数部分中看到的。 它添加了 OUTPUT_DIR 环境变量,在我们的示例中是 build。
标记为 4 的行表示使用 web-app-builder-runtime 图像,我们已经在 ImageStream 部分中看到了该图像。

标记为 5 的行表示,如果 S2I 映像支持增量构建,并且 Web App Builder 映像也支持增量构建,则我们希望使用增量构建。 首次启动时,组装阶段完成后,映像会将 node_modules 文件夹保存到存档文件中。 然后,在后续运行中,映像将简单地解压缩此文件夹以减少构建时间。

最后,标记为 6 的行只是一些触发器,使构建在发生变化时自动运行,无需手动干预。

总的来说,这是一个非常标准的构建配置。

现在让我们看一下第二个构建配置。 它与第一个非常相似,但有一个重要的区别。

apiVersion: v1
  kind: BuildConfig
  metadata:
    name: react-web-app-runtime
  spec:
    output:
      to:
        kind: ImageStreamTag
        name: react-web-app-runtime:latest // 1
    source: // 2
      type: Image
      images:                              
        - from:
            kind: ImageStreamTag
            name: react-web-app-builder:latest // 3
          paths:
            - sourcePath: /opt/app-root/output/.  // 4
              destinationDir: .  // 5
             
    strategy: // 6
      sourceStrategy:
        from:
          kind: ImageStreamTag
          name: nginx-image-runtime:latest
        incremental: true
      type: Source
    triggers:
    - github:
        secret: ${GITHUB_WEBHOOK_SECRET}
      type: GitHub
    - type: ConfigChange
    - type: ImageChange
      imageChange: {}
    - type: ImageChange
      imageChange:
        from:
          kind: ImageStreamTag
          name: react-web-app-builder:latest // 7

所以第二个构建配置是react-web-app-runtime,它开始时非常标准。

标记为 1 的行并不是什么新鲜事 - 它只是表示构建结果被放入react-web-app-runtime 图像中。

与之前的配置一样,标记为 2 的行指示从何处获取源代码。 但请注意,这里我们说的是从图像中获取的。 此外,从我们刚刚创建的图像 - 来自react-web-app-builder(如标记为3的行所示)。 我们想要使用的文件位于图像内部,其位置在标记为 4 的行中设置,在我们的示例中为 /opt/app-root/output/。 如果您还记得,这是存储根据构建应用程序结果生成的文件的位置。

带有标签 5 的术语中指定的目标文件夹只是当前目录(记住,这就是全部,在名为 OpenShift 的神奇东西中运行,而不是在本地计算机上运行)。

策略部分(标记为 6 的行)也与第一个构建配置类似。 只是这一次我们将使用 nginx-image-runtime,我们已经在 ImageStream 部分看到过它。

最后,标记为 7 的行是触发器的一部分,每次react-web-app-builder 图像发生变化时都会激活此构建。

否则,此模板包含非常标准的部署配置,以及与服务和路由相关的内容,但我们不会讨论太多细节。 请注意,将部署的映像是react-web-app-runtime 映像。

应用部署

现在我们已经了解了模板,接下来让我们看看如何使用它来部署应用程序。

我们可以使用名为 oc 的 OpenShift 客户端工具来部署我们的模板:

$ find . | grep openshiftio | grep application | xargs -n 1 oc apply -f

$ oc new-app --template react-web-app -p SOURCE_REPOSITORY_URL=https://github.com/lholmquist/react-web-app

上面屏幕截图中的第一个命令是一种有意的工程方式来查找模板。/openshiftio/application.yaml。

第二个命令只是基于此模板创建一个新应用程序。

这些命令运行后,我们将看到有两个程序集:

OpenShift 上的现代应用程序,第 2 部分:链式构建

返回到概览屏幕,我们将看到启动的 Pod:

OpenShift 上的现代应用程序,第 2 部分:链式构建

单击该链接,我们将进入我们的应用程序,这是默认的 React 应用程序页面:

OpenShift 上的现代应用程序,第 2 部分:链式构建

补充1

对于 Angular 爱好者,我们还有 示例应用程序.

除了 OUTPUT_DIR 变量之外,这里的模式是相同的。

补充2

在本文中,我们使用NGINX作为Web服务器,但是将其替换为Apache非常容易,只需更改文件中的模板即可 NGINX 镜像阿帕奇图像.

结论

在本系列的第一部分中,我们展示了如何在 OpenShift 平台上快速部署现代 Web 应用程序。 今天,我们研究了 Web 应用程序映像的作用,以及如何使用链式构建将其与 NGINX 等纯 Web 服务器结合起来,以创建更适合生产的应用程序构建。 在本系列的下一篇也是最后一篇文章中,我们将展示如何在 OpenShift 上为您的应用程序运行开发服务器并确保本地和远程文件的同步。

本系列文章内容

  • 部分1: 如何通过几个步骤部署现代 Web 应用程序;
  • 第 2 部分:如何将新的 S2I 映像与现有 HTTP 服务器映像(例如 NGINX)一起使用,并使用关联的 OpenShift 程序集进行生产部署;
  • 第 3 部分:如何在 OpenShift 平台上为您的应用程序运行开发服务器并将其与本地文件系统同步。

Дополнительныересурсы

来源: habr.com

添加评论