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

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







在上一篇文章中,我们略微谈到了新的S2I(源到图像)构建器映像的功能,该映像旨在在OpenShift平台上构建和部署现代Web应用程序。然后,我们对快速应用程序部署这一主题感兴趣,但是今天,我们将研究如何将S2I映像用作“干净的”构建器映像,并将其与关联的OpenShift程序集结合在一起。



清洁生成器图像



正如我们在第一部分中提到的,大多数现代Web应用程序都有一个所谓的构建阶段,该阶段通常执行诸如代码转译,多个文件的串联和缩小之类的操作。生成的文件-静态HTML,JavaScript和CSS-添加到输出文件夹中。该文件夹的位置通常取决于所使用的构建工具,对于React,它将是./build文件夹(我们将在下面更详细地介绍到此文件夹)。



源到图像(S2I)



这篇文章根本不是关于什么是S2I以及如何使用它(您可以在此处阅读更多信息),但重要的是要清楚此过程的两个阶段,以了解Web App Builder图像的作用。



组装阶段



组装步骤本质上与运行docker build并以新的Docker映像结束时发生的操作非常相似。因此,在OpenShift平台上开始构建时会发生此阶段。



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



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



运行阶段



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



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



换句话说,我们在组装过程中需要一件事,而在执行过程中则需要另一件事。这是链接构建派上用场的地方。



链式构建



这是他们在OpenShift文档中关于链式构建的内容:



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



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



因此,我们可以将Web App Builder图像用作纯构建器,并且仍然具有较小的运行时图像。



现在,让我们看一个具体的例子。



在本教程中,我们将使用通过create-react-app命令行工具构建简单React应用程序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,它取自Docker hub上带有10.x标签的nodeshift / ubi8-s2i-web-app



第四个是NGINX映像(1.12版),在Docker hub上带有最新标签



现在,让我们看一下前两个图像。它们在开始时都是空的,并且仅在构建阶段创建。第一个图像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和context文件夹由我们上面已经看到的参数定义。



在参数部分已经看到标有3的行。它添加了在我们的示例中构建的OUTPUT_DIR环境变量。

标记为4的行表示要使用我们已经在ImageStream部分中看到的web-app-builder-runtime图像。



标记为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的行)也类似于第一个构建配置。仅这次,我们将使用在ImageStream部分中已经看到的nginx-image-runtime。



最后,标记为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的方法。



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



在完成这些命令之后,我们将看到我们有两个程序集:







返回“概述”屏幕,我们将看到窗格启动:







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







附录1



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



除了OUTPUT_DIR变量外,此处的模板相同。



附录二



在本文中,我们将NGINX用作Web服务器,但是用Apache替换它很容易,只需以Apache方式更改文件模板映像NGINX即可



结论



在本系列的第一部分中,我们向您展示了如何在OpenShift平台上快速部署现代Web应用程序。今天,我们研究了构成Web应用程序映像的原因以及如何将其与链式构建之类的纯Web服务器(如NGINX)结合使用,以创建更易于生产的应用程序构建。在本系列的下一篇最后一篇文章中,我们将向您展示如何在OpenShift上为您的应用程序运行开发服务器,以及如何使本地和远程文件保持同步。



本系列文章的内容










All Articles