#玩转华为云CodeArts#1024上云正当时,一切皆服务

举报
胡琦 发表于 2024/10/20 15:29:59 2024/10/20
【摘要】 在云计算时代,技术的边界不断被突破,而“一切皆服务”的理念正是这场变革的核心。在《1024上云正当时,一切皆服务》这篇文章中,作者通过将本地全栈项目迁移至华为云的实际操作,展示了从开发到部署的完整流程,尤其是在华为云 CodeArts 与 CCE 的支持下,如何通过容器化、自动化流水线将项目快速上线。对于想要掌握云上开发与部署的开发者,这篇文章无疑是一份实践经验的宝贵指南。

1024 是属于程序员的节日,也是上云的最佳时机。随着云计算的普及,‘一切皆服务’的理念已深入人心。从开发环境、项目构建、流水线到最终部署,无一不可以通过云平台实现自动化、智能化、规模化。随着业务需求的增长,开发者对云计算平台的要求越来越高,尤其是在开发效率、部署稳定性和弹性扩展方面。华为云凭借其 CodeArts 持续集成平台和 CCE(容器云引擎)提供了一个高效、一站式的上云解决方案。本次项目实践正是通过这些工具,实现了从本地开发环境到线上稳定运行的全流程自动化,本文将分享如何利用华为云将一个本地 TypeScript 全栈项目迅速部署上线,享受云端的高效与便捷,感受 Sequelize For GaussDB 的快意。

项目概述

项目功能:实现一个套完整的增删查改 restful api 接口,具体如下:

Methods
Urls
Actions
POST
/api/tutorials
create new Tutorial
GET
/api/tutorials
retrieve all Tutorials
GET
/api/tutorials/:id
retrieve a Tutorial by :id
PUT
/api/tutorials/:id
update a Tutorial by :id
DELETE
/api/tutorials/:id
delete a Tutorial by :id
DELETE
/api/tutorials
delete all Tutorials
GET
/api/tutorials?title=[keyword]
find all Tutorials which title contains keyword

前端界面大致如图,展示搜索、列表查询、新增、编辑及删除等操作界面:

项目实现了通过 Sequelize 调用 GaussDB 进行 CRUD 操作。

大致的部署如下图:

技术栈

概览

前端:Vite + Vue3 + DevUI

后端:Express + Sequelize + GaussDB

**持续集成/部署: **Docker、Nginx、华为云 CodeArts、 CCE、ECS、SWR

开发语言:TypeScript

**代码托管:**GitCode

前端

  • Vite:使用 Vite 作为构建工具,主要优势是其极快的冷启动时间和热模块替换(HMR)机制。本项目通过 Vite 构建前端和后端,使用统一的 vite.config.ts 配置文件来开发 Vue3 前端和 Express 后端。
  • Vue 3:通过 Vue 3 设计响应式的前端界面,尤其是使用了其 Composition API 来组织代码。本项目使用 npm create vue@latest 快速创建 Vue 3 工程,默认使用 <script setup> 语法糖,并借助 unplugin-auto-import 简化 APIs 导入。
  • DevUI:基于全新设计体系,面向企业中后台产品的开源前端解决方案。DevUI 为 Web 应用提供了丰富的基础 UI 组件,提供了企业级应用的最佳 UI 实践。Vue DevUI 是基于 DevUI Design 的 Vue3 组件库,帮助开发者快速构建用户界面。本项目借助 unplugin-vue-components 按需引入组件,快速开发增删查改页面。

代码示例(Vue DevUI 组件实现一个简单的表单):

<d-form
    :data="tutorialData"
    ref="formRef"
    :rules="rules"
    class="form"
    :disabled="status === 'review'"
  >
    <d-form-item
      field="title"
      label="Title"
      help-tips="This is the tutorial title."
    >
      <d-input v-model="tutorialData.title" />
    </d-form-item>
    <d-form-item field="description" label="Description">
      <d-textarea v-model="tutorialData.description" />
    </d-form-item>
    <d-form-item field="published" label="Status">
      <d-radio-group direction="row" v-model="tutorialData.published">
        <d-radio :value="true">Published</d-radio>
        <d-radio :value="false">Pending</d-radio>
      </d-radio-group>
    </d-form-item>
  </d-form>

后端

  • Express:高度包容、快速而极简的 Node.js Web 框架。用于构建后端 API,处理 HTTP 请求,轻量且灵活。本项目借助 vite-express 完美将 Vite 和 Express 集成,我们可以轻松地快速开始编写全栈应用程序。
  • Sequelize:通过 Sequelize ORM 进行数据库操作,简化与 GaussDB 的数据交互。本项目还借助 sequelize-typescriptpgpg-hstore 让我们连接和操作 GaussDB 更加方便快捷。
  • GaussDB:GaussDB 是华为自主研发的分布式关系型数据库,支持分布式事务、同城跨 AZ 部署、1000 + 扩展及 PB 级存储,具备云上高可用、可靠、安全等关键能力,为企业提供全面、稳定、强扩展、高性能的数据库服务。

代码示例(Express models 层定义 GaussDB 的 Sequelize 模型):

import { Model, Table, Column, DataType } from "sequelize-typescript";

_// 定义tutorials表_
@Table({
  tableName: "tutorials",
})
export default class Tutorial extends Model {
  _// 定义id列_
  @Column({
    type: DataType.INTEGER,
    primaryKey: true,
    autoIncrement: true,
    field: "id"
  })
  id?: number;

  _// 定义title列_
  @Column({
    type: DataType.STRING(255),
    field: "title"
  })
  title?: string;

  _// 定义description列_
  @Column({
    type: DataType.STRING(255),
    field: "description"
  })
  description?: string;

  _// 定义published列_
  @Column({
    type: DataType.BOOLEAN,
    field: "published"
  })
  published?: boolean;
}

持续集成/部署

这里主要介绍一下华为云 CodeArts ,软件开发生产线 CodeArts 是一站式、全流程、安全可信的软件开发生产线,开箱即用,内置华为多年研发最佳实践,助力效能倍增和数字化转型。本项目的持续集成和部署主要用到了 CodeArts 的流水线、编译构建和部署功能,通过 CodeArts ,我们能将 Github 或 GitCode 等其他代码托管平台的代码作为构建代码源,快速构建 Docker 镜像并部署到 CCE 和 ECS 。

迁移上云

本地运行

我们先来看看当前项目的在本地如何运行,对于大部分 JavaScript / TypeScript 项目,我们只需要关注 package.json 文件即可获知技术栈、运行方式、部署方式等信息。如本项目的 package.json 文件:

{
  "name": "vite-express-vue3-app",
  "private": true,
  "version": "0.0.0",
  "scripts": {
    "start": "concurrently \"cross-env NODE_ENV=production npm run build-only\" \"cross-env NODE_ENV=production node ./build/main.js\" --raw",
    "start:dev": "concurrently \"npm run dev:server\" \"npm run dev:client\" --raw",
    "start:server": "tsx --tsconfig tsconfig.server.json  src/server/main.ts",
    "start:pm2": "cross-env NODE_ENV=production npm run build && cross-env NODE_ENV=production pm2 start ./build/main.js --name express-vue3",
    "build": "concurrently \"npm run build:server\" \"npm run build:client\"",
    "dev:server": "nodemon -w src/server -x tsx --tsconfig tsconfig.server.json src/server/main.ts",
    "dev:client": "vite",
    "build-only": "vite build",
    "build:server": "tsc -p tsconfig.server.json",
    "build:client": "run-p type-check \"build-only {@}\" --",
    "stop": "pm2 stop express-vue3",
    "restart": "pm2 restart express-vue3",
    "preview": "vite preview",
    "type-check": "vue-tsc --build --force",
    "lint": "eslint . --fix",
    "format": "prettier --write src/"
  },
  "dependencies": {
    "@types/cors": "^2.8.17",
    "@types/express": "^4.17.21",
    "@types/node": "^20.16.11",
    "axios": "^1.7.7",
    "cors": "^2.8.5",
    "cross-env": "^7.0.3",
    "dotenv": "^16.4.5",
    "express": "^4.21.1",
    "pg": "^8.13.0",
    "pg-hstore": "^2.3.4",
    "sequelize": "^6.37.4",
    "sequelize-typescript": "^2.1.6",
    "tsx": "^4.4.0",
    "vite-express": "^0.19.0",
    "vue": "^3.5.12",
    "vue-router": "^4.4.5"
  },
  "devDependencies": {
    "@devui-design/icons": "^1.4.0",
    "@tsconfig/node20": "^20.1.4",
    "@vitejs/plugin-vue": "^5.1.4",
    "@vitejs/plugin-vue-jsx": "^4.0.1",
    "@vue/eslint-config-prettier": "^10.0.0",
    "@vue/eslint-config-typescript": "^14.0.1",
    "@vue/tsconfig": "^0.5.1",
    "concurrently": "^9.0.1",
    "devui-theme": "^0.0.7",
    "eslint": "^9.12.0",
    "eslint-plugin-vue": "^9.29.0",
    "nodemon": "^3.0.1",
    "npm-run-all2": "^6.2.3",
    "pm2": "^5.4.2",
    "prettier": "^3.3.3",
    "typescript": "^5.6.3",
    "unplugin-auto-import": "^0.18.3",
    "unplugin-vue-components": "^0.27.4",
    "vite": "^5.4.8",
    "vite-plugin-vue-devtools": "^7.4.6",
    "vue-devui": "^1.6.21",
    "vue-tsc": "^2.1.6"
  }
}

dependenciesdevDependencies 定义了我们项目依赖的包和版本 dependencies 一般定义应用程序在运行时所需的依赖库。这些库是我们项目在生产环境中必须安装和使用的。比如前端框架 Vue、后端框架 Express 以及数据库相关的依赖库等,都应该放在 dependencies 中。devDependencies** **定义开发过程中所需的依赖库,包括测试工具、打包工具、代码质量检查工具等。这些库只在开发、构建或测试过程中使用,不会在生产环境中使用。

package.json 中,scripts 部分定义了常用的命令,可以用于简化开发、构建、测试和部署等操作。对于当前项目,scripts 部分如下:

{
  "scripts": {
    // 生产环境启动,先构建项目,然后启动后端
    "start": "concurrently \"cross-env NODE_ENV=production npm run build-only\" \"cross-env NODE_ENV=production node ./build/main.js\" --raw",

    // 开发环境启动,前后端同时启动,监控代码变化
    "start:dev": "concurrently \"npm run dev:server\" \"npm run dev:client\" --raw",

    // 启动后端(开发模式),通过 tsx 执行 main.ts 文件,并使用 tsconfig.server.json
    "start:server": "tsx --tsconfig tsconfig.server.json  src/server/main.ts",

    // 生产环境使用 pm2 启动项目,先构建,再使用 pm2 进行进程管理
    "start:pm2": "cross-env NODE_ENV=production npm run build && cross-env NODE_ENV=production pm2 start ./build/main.js --name express-vue3",

    // 同时构建前端和后端
    "build": "concurrently \"npm run build:server\" \"npm run build:client\"",

    // 后端开发模式,使用 nodemon 监听代码变化并自动重启
    "dev:server": "nodemon -w src/server -x tsx --tsconfig tsconfig.server.json src/server/main.ts",

    // 前端开发模式,使用 Vite 启动开发服务器
    "dev:client": "vite",

    // 仅构建前端,使用 Vite 进行打包
    "build-only": "vite build",

    // 使用 TypeScript 编译后端代码,读取 tsconfig.server.json 配置
    "build:server": "tsc -p tsconfig.server.json",

    // 构建前端项目并检查类型
    "build:client": "run-p type-check \"build-only {@}\" --",

    // 停止 PM2 进程
    "stop": "pm2 stop express-vue3",

    // 重启 PM2 进程
    "restart": "pm2 restart express-vue3",

    // Vite 提供的生产环境预览功能,模拟生产环境运行前端代码
    "preview": "vite preview",

    // 使用 vue-tsc 进行类型检查,确保项目的类型安全
    "type-check": "vue-tsc --build --force",

    // 自动修复的 ESLint 代码检查
    "lint": "eslint . --fix",

    // 使用 Prettier 格式化代码
    "format": "prettier --write src/"
  }
}

npm run start:dev 为例,我们同时在本地以开发模式运行了前端和后端:

我们从终端日志可以看到分别运行了前端: http://localhost:5173/ 和后端 : http://localhost:8080/ ,以及后端调用了 Sequelize 连接 GaussDB 。本地运行的页面效果如下:

配置修改

做过 Vue 开发的小伙伴应该都知道”跨域问题“,也就说前端调用后端接口时由于 ip 、端口等不同而导致接口虽然调通了但被浏览器拦截了。本项目中前端端口是 5173 、后端端口是 8080 ,在本地运行时,前端侧使用了 Vite 的 proxy 配置来处理跨域问题,如:

server: {
    host: '0.0.0.0',
    port: 5173,
    proxy: {
      '/api': {
        target: process.env.VITE_BASE_URL || 'http://localhost:3000',
        changeOrigin: true,
        **rewrite**: (_path_: string) => _path_.replace(/^\/api/, '')
      }
    }
  }

后端使用了 Cors 库允许跨域:

_// 导入cors中间件和CorsOptions类型_
import cors, { CorsOptions } from "cors";

_// 使用cors中间件_
_app_.use(cors());

在本项目中,我们还特别使用了 Express 的静态目录,使得后端端口能直接加载打包好的前端,作为静态页访问:

_// Serve static files from the client_
app.use(express.static(path.join(__dirname, isProduction ? '../dist' : '../../dist'))); _// 根据环境选择路径_

_// Fallback for all other routes to index.html_
app.get('*', (_req_: Request, _res_: Response) => {
  _res_.sendFile(path.join(__dirname, isProduction ? '../dist/index.html' : '../../src/dist/index.html')); _// 根据环境选择路径_
});

细心的小伙伴可能发现了我们代码中使用了大量的环境变量,如 process.env.VITE_BASE_URLNODE_ENV 等等,这其实是为了上云做的一些配置上的修改,比较典型的就是数据库配置 db.config.ts:

import 'dotenv/config'
_// 数据库配置_
console.log(process.env.DB_PORT, Number(process.env.DB_PORT))
export const config = {
  _// 数据库主机_
  HOST: process.env.DB_HOST || "localhsot",
  _// 数据库端口_
  PORT: Number(process.env.DB_PORT) || 5432,
  _// 数据库用户名_
  USER: process.env.DB_USER || "root",
  _// 数据库密码_
  PASSWORD: process.env.DB_PASSWORD || "Gauss@hello",
  _// 数据库名_
  DB: process.env.DB_NAME || "testdb",
  _// 数据库连接池配置_
  pool: {
    _// 最大连接数_
    max: 5,
    _// 最小连接数_
    min: 0,
    _// 获取连接的超时时间_
    acquire: 30000,
    _// 连接空闲的超时时间_
    idle: 10000
  }
};

_// 数据库方言_
export const dialect = "postgres";

这是为了应对上云时复杂多变的环境,下文中我们也会详细讲解迁移上云过程中如何去动态修改这些配置。

容器化

为什么要容器化?在这里我们不直接给出答案,希望大家通过下文的上云实践之后,能够自己寻找到。本项目在上云的时候,我们充分考虑了单机部署(ECS)和集群部署(CCE)这两种场景,在 ECS 场景下,我们将前后端部署在一台云服务器上;在 CCE 场景下,我们将前端后端分别部署在集群的不同节点上。因此,我们需要分别对前后端进行容器化,并还支持将前端通过 Nginx 部署。

前端 Dockerfile

_# 使用官方 Node.js 镜像作为基础镜像_
FROM node:20-alpine AS build

_# 设置工作目录_
WORKDIR /usr/src/app

_# 复制 package.json 和 package-lock.json_
COPY package*.json ./

USER root 
_# 安装 pm2 _
RUN npm install pm2 -g  --verbose --unsafe-perm --registry=https://repo.huaweicloud.com/repository/npm/
 
_# 安装项目依赖_
RUN npm install --verbose --unsafe-perm --registry=https://repo.huaweicloud.com/repository/npm/

_# 复制项目文件_
COPY . .

_# 构建应用程序_
RUN npm run build

_# 使用 Nginx 作为生产服务器_
FROM nginx:alpine

_# 复制构建后的文件到 Nginx 目录_
COPY --from=build /usr/src/app/dist /usr/share/nginx/html

_# 复制 Nginx 配置模板_
COPY nginx.conf /etc/nginx/nginx.conf

_# 暴露 Nginx 端口_
EXPOSE 80

_# 启动 Nginx,并使用 envsubst 替换环境变量_
CMD nginx -g 'daemon off;'

_# docker run -d -p 80:80 -e API_URL=http://192.168.10.22:8080 your_image_name_

后端 Dockerfile

_# 使用官方 Node.js 镜像作为基础镜像_
FROM node:20-alpine

_# 设置工作目录_
WORKDIR _/usr/src/app_

_# 复制 package.json 和 package-lock.json_
COPY _package*.json_ _./_

USER _root_ 
_# 安装 pm2 _
RUN _npm_ _install_ _pm2_ _-g_ _--verbose_ _--unsafe-perm_ _--registry=https://repo.huaweicloud.com/repository/npm/_
_# 安装项目依赖_
RUN _npm_ _install_ _--verbose_ _--unsafe-perm_ _--registry=https://repo.huaweicloud.com/repository/npm/_

_# 复制项目文件_
COPY _._ _._

_# 暴露应用程序的端口_
EXPOSE _3000_

_# 启动应用程序_
CMD _[_"pm2-runtime"_,_ "npm"_,_ "--"_,_ "start"_]_

Nginx 配置

events {
    worker_connections 1024_;  # 设置每个工作进程的最大连接数_
}
http {
    _# ... 其他配置 ..._

    include       mime.types_;  # 确保包含 mime.types 文件_
    default_type  application/octet-stream_;  # 默认 MIME 类型_

    
    server {
        listen 80_;_
        _# 前端应用的根目录_
        location / {
            root /usr/share/nginx/html_;  # 前端构建文件的路径_
            index index.html_;             # 默认首页_
            try_files $uri $uri/ /index.html_;  # 处理前端路由_
        }

        _# 代理后端接口请求_
        location /api/ {
            proxy_pass http://localhost:3000_;  # 使用环境变量配置后端接口,设置默认值_
            proxy_set_header Host $host_;              # 设置主机头_
            proxy_set_header X-Real-IP $remote_addr_;  # 设置真实 IP_
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for_;  # 设置转发的 IP_
            proxy_set_header X-Forwarded-Proto $scheme_;  # 设置转发协议_
        }
    }
    
    _# ... 其他配置 ..._
}

持续集成/部署

环境准备

  • ecs X86 计算 | 通用计算增强型 | c7.large.2 | 2 核 | 4GB ** 2 台**
  • gaussdb 8.x | 主备版 | 高可用(1 主 2 备) | 通用型 | 4 核 16GB
  • cce CCE 容器集群 | Standard/Turbo | 50 节点 | 3 实例(高可用)
  • vpcep 基础版
  • eip 独享 | 全动态 BGP | 按带宽计费 | 5Mbit/s 3 个
  • evs 通用型 SSD | 20GiB 2 个

如果考虑 ECS 场景,则 ecs 只要 1 台、eip 弹性公网 ip 也只需要 1 个、不需要 evs 云磁盘。

《环境开通指南》:https://gitcode.com/HuaweiCloudDeveloper/OpenSourceForHuaweiWiki/blob/main/zh_CN/docs/set-up-environment.md

GaussDB 注意事项

由于当前版本 Sequelize 连接 GaussDB 时对账密的加密方式存在兼容问题,我们需要在 GaussDB 后台修改 dn:password_encryption_type 为 1 ,详细参见:https://gitcode.com/HuaweiCloudDeveloper/OpenSourceForHuaweiWiki/issues/2?did=be6625f4cd41f319312e706648100a0ec944e52f#tid-1502121

此外,我们在迁移过程中遇到 root 用户被锁死的情况:

Unable to connect to the Database: ConnectionError [SequelizeConnectionError]: The account has been locked.

此时需要创建新用户并授予权限,后续通过新用户去连接数据库。

针对以上两点,我们目前的解决方案是:

  1. 开通 GaussDB 实例,并手动修改 dn:password_encryption_type 为 1
  2. 使用 root 登录数据库,创建新用户并授予权限:
gaussdb=# CREATE USER joe WITH PASSWORD "********";
gaussdb=# GRANT ALL PRIVILEGES TO joe;

CCE 注意事项

我们在迁移过程中还遇到了 CCE 中服务访问 GaussDB 超时的问题,详情参见: https://gitcode.com/HuaweiCloudDeveloper/OpenSourceForHuaweiWiki/issues/7

后面排查到是容器内部没有网外访问,于是我们在 CCE 中将 db_host 配置成内网地址。

这里的关键点在于:

  1. 确保 CCE 和 Gauss DB 在同一个 VPS 下 如图:

  1. 确保安全组已放行相关的出、入端口;比如 GaussDB 需放行 DB_PORT(如 5432) 如图:

  1. CCE 容器环境变量中 DB_HOST 使用 GaussDB 内网地址 如图:

CodeArts 注意事项

我们在迁移过程中,使用 CodeArts 流水线时也遇到了问题,选择 gitcode 仓库创建 CodeArts 构建任务无法选择仓库,详情参见:https://gitcode.com/HuaweiCloudDeveloper/OpenSourceForHuaweiWiki/issues/8

其原因除了权限问题还有 CodeArts 设计上的一些细节给开发者带来了困扰。我们的解决方案是:

建议使用 通用 Git作为代码源

构建流水线(以 CCE 为例)

新建项目

项目是使用 CodeArts 各服务的基础,创建项目后才能完成后续操作。

  • 在 CodeArts 控制台单击 立即使用
  • 单击 新建项目,选择 Scrum,输入项目名称如 huaweicloud-sequelize-gaussdb

构建并推送镜像

通过编译构建任务将软件的源代码编译成镜像,并把镜像推送归档到容器镜像服务(SWR)中。

  • 单击导航栏 持续交付 > 编译构建,进入编译构建服务。
  • 单击 新建任务,配置任务信息。
  • 配置基本信息:配置以下信息,单击“下一步”。

构建任务基本信息

配置项
配置参考
名称
opensource-demo-sequelize-for-Huawei-241014
代码源
通用 git
码仓库
opensource-demo-sequelize-for-Huawei-241014
分支
sequelize-for-huawei

构建模板,选择“系统模板”。

  • 配置构建步骤

    a.单击“点击添加构建步骤”,在步骤列表中找到“DevStar-Npm-容器构建”,单击选中后单击”确定“。

    b.(非必需,仅验证打包)单击“Npm 构建”,工具版本选择”nodejs20“, 命令改为如下:

export PATH=$PATH:~/.npm-global/bin
#设置缓存目录
npm config set cache ./npmcache

#nodejs 版本大于等于 18时 可以设置下面的值 
npm config set registry https://repo.huaweicloud.com/repository/npm/
npm config set prefix '~/.npm-global'

#加载依赖
npm install --verbose
#默认构建
npm run build

c.参照下表配置步骤“制作镜像并推送到 SWR 仓库”(表中未涉及的字段保持默认配置即可)。

配置项
配置建议
组织
输入在准备工作中创建的组织名称如"modelarts-lab"
镜像名称
输入镜像名称如“sequelize-for-huawei”
镜像标签
V1.0
Dockerfile 路径
./Dockerfile
  • 完成配置,单击“保存并执行”。

  • 登录容器镜像服务控制台,在页面左侧导航栏中选择“我的镜像”。
    页面中有 1 条新镜像名称为 sequelize-for-huawei,所属组织为“modelarts-lab”的记录。
    单击镜像名称查看详情,镜像版本为“v1.0”。

创建负载

在云容器引擎(CCE)中创建无状态负载(Deployment),用于加载运行 sequelize-for-huawei 镜像。

PS:目前 CodeArts 不支持 集群类型: CCE Standard(原 CCE 集群)

  • 登录云容器引擎控制台,单击在环境准备中购买的集群,进入详情页。
  • 在页面左侧导航选择“工作负载”,单击“创建工作负载”。
  • 参考下表完成配置,单击“创建工作负载”。

  • 并配置环境变量,如 GaussDB 相关的变量

  • 页面提示创建成功,单击“查看工作负载详情”,返回负载详情页面,“实例列表”页签中显示一条记录。当该记录的状态为“运行中”时,选择“访问方式”页签,单击“创建”,参考下表完成创建服务配置,单击“确定”。如果实例状态异常,请参考工作负载异常排查处理。

配置访问方式

配置项
配置建议
Service 名称
输入“sequelize-for-huawei-service”
访问类型
选择“负载均衡”。
服务亲和

集群级别
负载均衡器
- 选择“独享型 > 自动创建”。
- 实例名称:输入“sesequelize-for-huawei-service”。
- 弹性公网:选择“自动创建”。
端口配置
- 协议:TCP
- 容器端口:8080
- 服务端口:80
  • 打开新的浏览器页面,输入“http://IP”,其中 IP 为公网地址。如果出现以下访问结果,表示负载运行成功。

部署镜像

通过在部署服务中创建应用,将镜像部署自动化。

  • 返回 CodeArts 页面,单击导航栏“持续交付 > 部署”,进入部署服务。

a. 单击“新建应用”。

b. 输入应用名称“opensource-demo-sequelize-for-Huawei-241014”,单击“下一步”。

c. 选择“空白模板”,单击“确定”。

  • 在步骤列表中搜索并添加步骤“Kubernetes 快速部署(CCE 集群)”,参考下表完成步骤配置。

配置部署步骤

配置项
配置建议
区域
选择集群所在的区域。
集群名称
选择准备工作中购买的集群名称(支持 **CCE **Standard(原 CCE 集群) )。
命名空间名称
选择“default”。
工作负载名称
选择“sequelize-for-huawei”。
容器名称
选择创建负载时,容器配置部分的容器名称“sequelize-for-huawei”。
镜像名称

选择创建负载时,容器配置部分的容器名称“modelarts-lab/sequelize-for-huawei”。
镜像版本
v1.0 (后者自行迭代)

  • 单击“保存并部署”。

配置流水线实现自动化更新镜像部署

通过配置流水线,将代码仓库、构建、部署串联起来,当代码仓库中发生代码提交动作时,可以自动触发流水线的执行,实现持续交付。

  • 单击导航栏“持续交付 > 流水线”,进入流水线服务。
  • 单击“新建流水线”,配置流水线。
配置项
配置建议
名称
opensource-demo-sequelize-for-Huawei-241014
代码源
通用 Git。
代码仓
opensource-demo-sequelize-for-Huawei-241014
默认分支
sequelize-for-huawei
  • 配置工作流。

参考下表配置任务信息

配置项
配置建议
名称
保持默认值即可。
请选择需要调用的任务
选择“edge-service-build”。
代码仓
选择“servicecomb-fence”。
  • 单击“新建阶段”,并修改阶段名称为“构建”。
  • 单击“新建任务”,添加插件“Build 构建”,选择上文中构建任务 opensource-demo-sequelize-for-Huawei-241014
  • 单击“新建阶段”,并修改阶段名称为“部署”。
  • 单击“新建任务”,添加插件“Deploy 部署”,选择上文中部署任务 opensource-demo-sequelize-for-Huawei-241014

  • 选择“执行计划”页签,打开“Webhook”开关,获取 Webhook 触发源。

  • 将 Webhook 触发源回填到 GitCode 项目设置中

配置完成之后,只要我们提交代码就会触发流水自动部署。

至此,我们已经完成了将一个本地 TypeScript 全栈项目迅速部署上云。您学到了吗?

尾声

每一个代码片段、每一个服务的启动都仿佛置身于一个协作精密的自动化流程中。从 Vite 前端的极速热更新,到 Sequelize for GaussDB 强大的数据库支持,再到 Express 提供的高效后端框架,通过容器化,我们将这些零散的本地组件统一封装,打包成可随时运行的“云上应用”。这意味着,无论是处理突然的流量高峰,还是在不同环境中保证稳定的运行,一切都变得如此简单而有序。
通过这个项目的上云实践,我们体会到了“一切皆服务”的真正力量——从开发环境到容器编排,从持续集成到弹性扩展,云服务已不再是未来,而是我们手中的强大工具。今天的每一行代码,都在云上找到最适合的运行方式,也预示着我们每一个创新的未来,都将以更快的速度落地。
1024程序员节,属于每一个技术人的节日,也是上云的最好时机。通过云端的力量,我们不再为琐碎的部署细节所困,而是有更多的时间去构建真正有价值的功能。因为在云端,一切皆服务,技术与梦想都在这里找到最好的归宿。

我正在参加【有奖征文 第31期】华为云CodeArts,AI重塑的软件开发生产线!
活动链接:https://bbs.huaweicloud.com/blogs/434372

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。