如何实现vue项目的更新

事情起缘

这个问题还得从自己的博客系统说起,因为我博客系统采用的是前后端分离模式开发。前端使用的是nuxt,后端用的是go,每次发布新版本前端都需要重新构建。

本来是打算直接自己写一个程序来自动下载项目然后自动编译的,但是考虑到不同系统编译可能会出现各种bug。所以就打算另寻它法。

使用docker

最后我采用了群里大佬的建议,打算使用docker来部署博客系统,因为docker的镜像更新非常方便,所以如果我有新的版本更新的话,我就只需要自己推送一个新版本的镜像就可以了。大家可以直接下载最新的镜像然后启动容器就行。

当然这个方案还存在下面这几个问题

如何构建镜像

一开始的想法我是打算自己手动把代码放到容器里面然后在自己手动编译,最后打包镜像的,但是我发现这样非常麻烦,而且还有一个问题就是无法实现自动根据用户的域名来修改镜像里面的代码并重新编译。

最后我决定采用dockerfile来自动构建镜像,我什么都不需要做,docker自动根据dockerfile文件进行依赖下载和项目构建。

比如我的web端的dockerfile文件格式如下

FROM node:alpine

# 指定工作目录
WORKDIR /app/xblog-web

# 复制当前路径文件
COPY . .

# 先解压文件,然后系统自动进行构建
RUN chmod +x ./build.sh && sh ./build.sh

# 每次启动容器时自动启动web项目
CMD  chmod +x ./startup.sh && sh ./startup.sh

我这里就可以实现自动下载初始镜像,然后把我项目的代码负责到镜像里面RUN执行的是编译安装操作,CMD是每次启动容器时进行的操作

然后我的自动构建脚本代码如下:

#!/bin/bash
echo -e "\033[36m====[欢迎使用博客博客系统web端镜像自动构建脚本 V1.0]==== \033[0m"
# 更新grep
echo "正在更新grep..."
apk add --no-cache --upgrade grep
#echo "使用淘宝镜像..."
#npm config set registry https://registry.npm.taobao.org
# 开始安装
echo "正在安装依赖...."
npm install
# 构建项目
echo "正在构建项目...."
npm run build
echo -e "\033[36m 镜像构建完毕,感谢你使用本系统,祝你玩的愉快φ(>ω<*)。系统稍后会自动结束构建,请勿取消操作! \033[0m"

我这个操作也非常简单,自动执行 npm install安装好依赖,然后先自动构建一下,后续用户运行的时候就不需要重新下载依赖了,可以减少项目重新构建所需要的时间

当然仅仅是自动下载依赖还是不够的,因为我们的项目前后端分离的,所以部署的时候必须要指定后端的地址,而每次修改地址后都需要重新编译才能正常使用。所以我必须要想办法来实现用户启动容器的时候只需要指定后端地址,然后我们服务器就可以自动修改配置文件然后重新编译,最终实现代码如下:

# 配置文件
file="package.json"

# 构建代码
Build () {
  echo "检测到你的配置文件发生变化,正在修改配置文件...."
  # 自动宁进行/转义
  api=${api//\//\\\/}
  web=${web//\//\\\/}
  ws=${ws//\//\\\/}
  apiT=${apiT//\//\\\/}
  webT=${webT//\//\\\/}
  wsT=${wsT//\//\\\/}
  # 修改配置文件
  sed -i "s/${apiT}/${api}/g" ${file}
  sed -i "s/${webT}/${web}/g" ${file}
  sed -i "s/${wsT}/${ws}/g" ${file}
  # 是否需要设置淘宝镜像
  if [ "$tao" -eq 1 ]
  then
    echo "已设置为淘宝镜像..."
    npm config set registry https://registry.npm.taobao.org
  else
    echo "已设置为默认镜像..."
    npm config set registry https://registry.npmjs.org/
  fi
  echo "正在安装依赖...."
  npm install
  # 构建项目
  echo "正在构建项目...."
  npm run build
  Start
}

# 运行程序
Start () {
  # 启动项目
  echo "正在启动项目..."
  npm start
}

##########
# 主程序
##########

# 判断是否有https
if [ "$https" -eq 1 ]
then
  ws="wss://$api"
  api="https://$api"
  web="https://$web"
else
  ws="ws://$api"
  api="http://$api"
  web="http://$web"
fi

# 获取配置文件里面的地址
apiT=$( sed -n '7p' ${file} | grep -oP '(?<=SERVER=).*(?=\ L)')
webT=$( sed -n '7p' ${file} | grep -oP '(?<=LOCAL=).*(?=\ W)')
wsT=$( sed -n '7p' ${file} | grep -oP '(?<=WS=).*(?=\ n)')

# 判断是否需要重新编译
if [ "$apiT" == "$api" ]
then
  Start
else
  Build
fi

这个代码看起来挺复杂的但是实现的逻辑非常简单,首先我利用sed和grep过滤出packafge.json里面的api和web地址并且和环境变量进行比对,如果相同的话就直接运行即可,如果不同的话就使用sed里面的文本替换功能来修改package.json文件,然后我们重新编译,这样就可以实现自动编译了。

如何启动镜像

构建好镜像后下一个问题就是启动镜像了,因为我最终的目标是用户只需要使用一条命令就可以自动启动镜像并且配置好内容,这里我们就用到了Docker Compose,利用这个我们就可以非常方便的同时启动多个容器并进行配置。

version: '3'
# 我们这里指定对应的服务
services:
  # 下面我们安装web
  web:
    # 镜像自动启动
    restart: always
    # 指定容器名字
    container_name: xlog-web
    # 使用博客系统镜像
    image: xxx/xiaoyou66/xblog-web
    # 指定端口
    ports:
      - '3000:3000'
    # 使用环境变量
    environment:
      # web地址,不要加http前缀,如果是ip记得加端口号
      web: 192.168.123.131:3000
      # api地址,不要加http前缀s,如果是ip记得加端口号
      api: 192.168.123.131:2333
      # 是否有https 有就是1 没有就是0
      https: 0
      #  是否使用淘宝镜像,国内服务器为1,国外的为0
      tao: 1
  # 这里我们安装api
  api:
    # 镜像自动启动
    restart: always
    # 指定容器名字
    container_name: xlog-api
    # 使用博客系统镜像
    image: xxx/xiaoyou66/xblog-api
    network_mode: "host"
    # 配置文件挂载
    volumes:
      # 注意这里前面是主机的地址,后面是容器里面的地址,前面可以改,但是后面不能改
      - /xblog/api/configs:/app/xblog-api/configs
      - /xblog/api/assets:/app/xblog-api/assets
      - /xblog/api/upload:/app/xblog-api/upload

我们通过dockerComposer可以指定启动的镜像,然后设置镜像的启动模式以及端口指定还有设置环境变量。

持久化问题

解决了自动构建功能后,下面就是配置数据持久化问题,因为后端的配置文件修改后或者自己上传文件后如果我重新拉取镜像的话容器里面的配置数据就会恢复,所以为了避免这个问题,我们就需要把配置文件映射到容器外部,第一次我们初始化的时候我们先检查文件,如果发现映射的文件没有文件的话就复制配置文件。如果有就不复制,代码如下所示:

volumes:
      # 注意这里前面是主机的地址,后面是容器里面的地址,前面可以改,但是后面不能改
      - /xblog/api/configs:/app/xblog-api/configs
      - /xblog/api/assets:/app/xblog-api/assets
      - /xblog/api/upload:/app/xblog-api/upload

我们判断代码如下所示

# 先判断资源文件夹是否有映射
if [ -z "$(ls -A assets)" ];
then
#  如果为空,那么就复制备份文件夹
   echo "正在复制资源文件夹..."
   cp -rf assets-back/* assets/
fi
# 判断配置文件夹是否为空
if [ -z "$(ls -A configs)" ];
then
#  如果为空,那么就复制备份文件夹
  echo "正在复制配置文件夹..."
   cp -rf configs-back/* configs/
fi

好了整个自动构建的流程就大致是这样了。

利用阿里云自动构建镜像

最后我想实现自动拉取github的代码然后自动构建并推送镜像。我们这里采用的是阿里云的容器镜像服务

我们创建了两个镜像仓库

这里我们可以自动设置规则,点击构建后阿里云就会自动拉取最新代码然后自动构建镜像,简直完美!

一键脚本

最后我在自己写了一个脚本,可以自动安装docker,部署系统和更新,这样就实现了最终的目标:自动构建镜像,用户一键更新,不需要任何其他的操作,这就是shell脚本的强大之处。一切都自动化,彻底解放自己的双手!