作为前端,我是这样从零实现CI/CD二(node服务部署及前后端联调)

1,549 阅读3分钟

背景

在上一篇文章作为前端,我是这样从零实现CI/CD的中,我们主要介绍了如何在服务器上安装、运行Jenkins平台、初始化Jenkins的相关配置。后面介绍了如何在Jenkins平台上创建了一个github的前端应用,并将其进行编译打包、生成Docker镜像,最终通过运行镜像将我们的前端项目跑在了服务器上。

但对于一个完整的项目来说,我们不仅需要前端界面,还需要有后端服务,所以这篇文章将介绍如何使用Jenkins平台去部署node服务供前端使用。

在Jenkins平台部署node应用

创建node应用

类似前端项目部署,我们首先在Jenkins平台创建一个node应用:

image.png

关联git仓库

创建好应用后,我们需要去关联到当前node应用的代码仓库,类似上篇文章介绍的那样,分为以下几个流程:

1. 进入Jenkins容器,生成公钥

docker exec -it ${容器id} bash

// 由于之前部署前端应用时,已经生成了一个公钥,为了保证公钥不被覆盖需要设置一个名字: be-jenkins
ssh-keygen -t rsa -f ~/.ssh/be-jenkins

2. 查看公钥

docker exec -it ${容器id} bash

cat ~/.ssh/be-jenkins.pub

3. 将公钥配置到,git仓库的Deploy keys下:

image.png

4. 配置Jenkins参数

image.png

image.png

有了之前部署前端应用的基础,这里的配置非常容易,最终我们会构建出一个node镜像be-jenkinsshell脚本中写打包镜像的命令即可

部署node服务

dockerfile

前面我们已经在Jenkins平台中做好了准备工作,后面就需要在项目用写一个Dockerfile来进行Docker镜像的构建:

FROM node:16.8

WORKDIR /usr/src/app

COPY package*.json ./

RUN npm install

COPY . ./

EXPOSE 3000

CMD [ "npm", "start" ]

构建镜像

到这里我们就可以进行node应用的构建了,点击【立即构建】按钮:

image.png 可以看到我们的node镜像已经构建完成了。

我们进入服务器,运行一下这个镜像:docker run -itd -p 3001:3000 --name be-jenkins be-jenkins

输入我们的地址:${ip}:3001/list

image.png

这里的/list实际就是我的node服务中写的一个接口,直接返回了一个固定的数据,用来检测我们的服务是否部署成功

此时,我们已经成功的将这个node服务部署到了服务器上

nginx配置

到目前为止,我们已经实现了前端应用后端应用的部署,并可以通过ip进行访问,我们的功能已经实现了一大半。但对于一个完整的项目,我们还需要配置自己的域名,就是可以直接输入域名访问到对应的应用。接下来我们就来实现这一功能

先介绍一下大致的思路:
首先,我们需要在平台(我这里用的是腾讯云)上配置域名解析;
第二步,通过配置nginx,将域名的请求代理到指定的应用中;
最后一步,启动nginx,进行测试

首先,我们需要在服务器中使用docker下载nginx镜像:docker pull nginx

设置前端应用

此时,我们可以在服务器根目录创建一个default.conf文件,并设置文件内容:

server {
    listen       80;
    listen  [::]:80;
    server_name  {你的域名};

    #access_log  /var/log/nginx/host.access.log  main;

    location / {
        proxy_pass http://{你的服务器ip}:8085;
    }


location ^~ /api/ {

    add_header Access-Control-Allow-Origin *;

    add_header Access-Control-Allow-Methods 'GET,POST,DELETE,OPTIONS,HEAD';

    rewrite ^/api/(.*)$ /$1 break;

    proxy_pass http://{你的服务器ip}:3001;

    proxy_set_header Host $http_host;

  }

}

这个nginx的配置的主要功能就是设置代理,由于我们的前端项目部署在8085端口,后端服务部署在3001端口,但由于前后端不在一个端口,在前端发送请求的时候,会出现跨域问题导致请求失败,而我们通过nginx将后端服务反向代理到域名下,并设置路由转发,当访问/api/时会走到后端服务中,而访问/时则走到前端服务,这样就解决了前后端端口或域名不一致导致的跨域问题。

最后执行命令 docker run --name nginx -v $(pwd)/default.conf:/etc/nginx/conf.d/default.conf -p 80:80 -d nginx启动nginx。

这时,我们在前端项目中发一个请求用来测试功能是否走通了:

axios.get('/api/list').then((res) => {
  if(res.data) {
    this.list = res.data
  }
})

然后我们把前端项目再部署一次,输入域名看下效果:

image.png

image.png

可以看到已经可以正常的调用,前后端的功能就完成了。此时我们已经实现了前后端的部署、并通过nginx实现了域名的访问和前后端请求跨域的问题。目前离完整的项目就差最后一步了:连接数据库,通过接口进行数据库的增删改查。

链接数据库

现在离一个完整的项目就差一步了:这里我使用的是mysql,这部分可以用最简洁的方式实现一下:

  • 拉取mysql镜像
  • 使用docker运行mysql
  • 在后端服务中链接mysql
  • 在前端读取数据库中的数据进行测试

运行mysql

首先,使用命令docker pull mysql:latest拉取mysql镜像
然后使用命令:

docker run -it --rm --name mysql -p 3306:3306 --mount "src=mysqldata,target=/var/lib/mysql" -e MYSQL_ROOT_PASSWORD=123456 mysql

mysql运行在3306端口,启动的一些参数可以阅读这篇使用Docker启动MySQL数据库,这里对每个参数都有一个说明。

链接mysql

我们需要后端项目中安装mysql依赖:yarn add mysql2,由于mysql 8以上的版本用之前老的依赖链接时会报错,所以就安装了mysql2这个依赖来链接数据库:

新建一个config.js文件来管理相关的配置项:

module.exports = {
  db: {
    host: '你的服务器ip',
    port: '3306', // 刚才启动的端口
    user: 'root', // 用户名
    password: '123456', // 刚才设置的密码
    database: 'sys', // 要链接的数据库
  },
}

db/index.js中写链接mysql的方法:

const mysql = require('mysql2')

const config = require('../config').db

module.exports = mysql.createConnection(config)

只要按照mysql2的官方文档写就好了。

后面再写了两个接口,用来执行sql语句来读写数据库:

  • 创建users
// 该接口会创建一个 user 表,里面有name 和 address 两个字段
app.post('/create_user_table', function (req, res) {
  connection.query(
    'CREATE TABLE IF NOT EXISTS users (name VARCHAR(255), address VARCHAR(255))',
    function (err, result) {
      if (!err) {
        res.send({
          code: 'success',
          result,
        })
      } else {
        res.send({
          code: 'error',
          err,
        })
      }
    }
  )
})
  • users表中插入数据
app.post('/add_user', function (req, res) {
  const { name, address } = req.body;
  connection.query(
    `INSERT INTO users (name, address) VALUES ('${name}', '${address}')`,
    function (err, result) {
      if (err) {
        res.send(err)
      } else {
        res.send('success')
      }
    }
  )
})
  • 获取users表中的数据
app.get('/get_user', function (req, res) {
  connection.query(
    `SELECT * from users;`,
    function (err, result) {
      if (err) {
        res.send(err)
      } else {
        res.send(result)
      }
    }
  )
})
  • 在前端项目中请求接口获取数据
// 添加用户
handleAddUser() {
  axios
    .post('/api/add_user', {
      name: this.name,
      address: this.address,
    })
    .then((res) => {
      if (res.data === 'success') {
        this.name = ''
        this.address = ''
      }
    })
}

// 获取用户列表
updateUserList() {
  axios.get('/api/get_user').then((res) => {
    this.userList = res.data
  })
}

前端的逻辑非常简单,只要看下这个简陋的界面即可:

image.png

上面输入内容点击添加就执行handleAddUser,下面更新数据就请求updateUserList, 这里再简单看下接口请求的效果:

image.png

image.png

很明显,我们的数据库已经写入了数据,并可以读取出来了,最后把这个简陋的链接贴上来有兴趣的小伙伴可以点击进入

最后

这两篇文章算是把项目部署的大致流程走了一遍:从部署jenkins,到部署前后端应用,后面又使用ngxin配置了域名、设置了反向代理,最后又把mysql数据库连成功。每个步骤都是最简单的方案,但是也覆盖到了很多内容,这个流程中一定是有很多待优化和提升的地方,也希望小伙伴们可以提出来更多的建议一起探讨,互相进步。

最后的最后
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿

感谢阅读 🙏