背景
在上一篇文章作为前端,我是这样从零实现CI/CD的中,我们主要介绍了如何在服务器上安装、运行Jenkins
平台、初始化Jenkins
的相关配置。后面介绍了如何在Jenkins
平台上创建了一个github
的前端应用,并将其进行编译打包、生成Docker
镜像,最终通过运行镜像将我们的前端项目跑在了服务器上。
但对于一个完整的项目来说,我们不仅需要前端界面,还需要有后端服务,所以这篇文章将介绍如何使用Jenkins
平台去部署node服务
供前端使用。
在Jenkins平台部署node应用
创建node应用
类似前端项目部署,我们首先在Jenkins
平台创建一个node应用:
关联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
下:
4. 配置Jenkins
参数
有了之前部署前端应用的基础,这里的配置非常容易,最终我们会构建出一个
node
镜像be-jenkins
,shell
脚本中写打包镜像的命令即可
部署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应用的构建了,点击【立即构建】按钮:
可以看到我们的node
镜像已经构建完成了。
我们进入服务器,运行一下这个镜像:
docker run -itd -p 3001:3000 --name be-jenkins be-jenkins
输入我们的地址:${ip}:3001/list
这里的
/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
}
})
然后我们把前端项目再部署一次,输入域名看下效果:
可以看到已经可以正常的调用,前后端的功能就完成了。此时我们已经实现了前后端的部署、并通过
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
})
}
前端的逻辑非常简单,只要看下这个简陋的界面即可:
上面输入内容点击添加就执行handleAddUser
,下面更新数据就请求updateUserList
,
这里再简单看下接口请求的效果:
很明显,我们的数据库已经写入了数据,并可以读取出来了,最后把这个简陋的链接贴上来有兴趣的小伙伴可以点击进入
最后
这两篇文章算是把项目部署的大致流程走了一遍:从部署jenkins
,到部署前后端应用
,后面又使用ngxin
配置了域名、设置了反向代理,最后又把mysql
数据库连成功。每个步骤都是最简单的方案,但是也覆盖到了很多内容,这个流程中一定是有很多待优化和提升的地方,也希望小伙伴们可以提出来更多的建议一起探讨,互相进步。
最后的最后
我正在参与掘金技术社区创作者签约计划招募活动,点击链接报名投稿感谢阅读 🙏