Skip to content

前端部署方案 ​

一. 触发方式 ​

1.1 自动触发 ​

使用Jenkins/Gitlab runner 等仓库监控工具去设置触发条件, 触发后执行开发自己设置的相应脚本, 如下面是我之前设置的一个gitlab脚本, 该脚本只对 feature/zk 分支生效, 即如果该分支有合入或者推送就会触发下面的命令, 替换Nginx的静态资源

后面会补充gitlab runner的相关部署经历

image: node:14.7.0
cache:
  key: ${CI_BUILD_REF_NAME}
  paths:
    - node_modules/  #缓存node_modules
stages:
  #- test
  - deploy
MES-deploy:
  stage: deploy
  script:
    - echo '***************************'
    - cd ./product
    - npm install --registry=https://registry.npm.taobao.org
    - npm run build
    - rm -rf /usr/local/nginx/html/dist/product
    - cp -r /home/gitlab-runner/builds/hh4QSqNh/0/cdp/cdp-web/dist/product/ /usr/local/nginx/html/dist/product/
    - echo 'deploy success'
    - cd ..
    - echo '***************************'
    - cd ./productGroup
    - npm install --registry=https://registry.npm.taobao.org
    - npm run build
    - ls
    - rm -rf /usr/local/nginx/html/dist/productGroup
    - cp -r /home/gitlab-runner/builds/hh4QSqNh/0/cdp/cdp-web/dist/productGroup/ /usr/local/nginx/html/dist/productGroup/
    - echo 'deploy success'
    - echo '***************************'
  tags:
    - v1
  only:
    - feature/zk

1.2 手动触发 ​

这种方式有点原始

  1. 一个是自己登陆服务器然后运行里面的构建脚本
  2. 开发在自己电脑上使用脚本去直连服务器, 然后跑一些脚本

对于方式1, 就不说了. 如果是使用方式2, 那么需要直连服务器, 解决方案在下面

服务器A连接服务器B, 并运行服务器B中的shell命令(不用输入密码) 将服务器A的 id_rsa.pub 复制到B服务器的 .ssh/authorized_keys 中, 如果B中没有该文件, 创建一个就可以 如 ssh root@10.253.xx.xx "pwd" , 即可 或者也可以使用下面的命令 scp -r id_rsa.pub root@10.253.xx.xx:/root/.ssh/authorized_keys 比如, 可以像下面这样去配置

ssh root@10.253.xx.xx "pwd"
cd /xxx/project/
npm run build
cp dist /usr/share/nginx/html

二. 部署方式 ​

这里有两种部署方式

2.1 使用Docker部署 ​

先提供相关文件(Dockerfile: 镜像打包, 这里使用了多阶段镜像打包, 即基于node生成的文件打包生成nginx镜像)

FROM node:16.13-alpine as node
# Install app dependencies
# A wildcard is used to ensure both package.json AND package-lock.json are copied
# where available (npm@5+)
COPY . .
# 安装依赖
RUN yarn install
# 打包
RUN yarn build

FROM nginx:latest
# 将上一步打包后的文件copy到nginx里面
COPY --from=node dist /usr/share/nginx/html
EXPOSE 80

镜像可以选择在服务器上打包, 然后直接重启或者在本地或者另一台服务器上打包, 再上传部署

  • 服务器上打包
// example: 之前运行的容器是web
// 基于Dockerfile打包镜像
docker build -t web-img .
# 由于经常重复打包, 所以使用下面的命令删除无用的镜像
docker rmi $(docker images -f "dangling=true" -q)

docker rm -f web
// 将nginx的配置文件挂载出来
docker run -d -it -p 80:80 -v /root/nginx/conf:/etc/nginx/conf.d --name web web-img /bin/bash
  • 本地其他服务器打包镜像

这种情况需要把打包的镜像上传到私库, 然后部署服务器再去拉取最新镜像重新部署. 听起来又要上传又要去重新拉取很麻烦, 但是这里可以使用一个镜像 watchtower 去帮助我们自动检测镜像是否变化, 是否需要重新部署, 具体如下Dokcerfile文件类似, 主要是打包上传脚本

#!/bin/bash
# 本地build镜像(指定dockerfile文件)
docker build -t vite . --no-cache
# 本地打tag
docker tag vite 10.253.xx.xx:5000/vite:latest
# 删除无用的镜像
# 由于经常重复打包, 所以使用下面的命令删除无用的镜像
docker rmi $(docker images -f "dangling=true" -q)
# 推送到私有仓库, 私有仓库
docker push 10.253.xx.xx:5000/vite:latest

2.2 普通部署 ​

普通部署没什么好说的, 打包好后替换nginx html里面的静态资源即可, 使用一些简单的cp, rm命令

三. 补充 ​

3.1 Gitlab runner ​

相关配置可以直接搜索gitlab官网, 下面是一些之前配置普通版踩过的坑, Docker版的后面我再补充

  • 新建一个gitlab runner用户, 这里最好最好新建为root, 否则后面会有很多麻烦的权限问题, 导致CI/CD不能拉去代码

    gitlab-runner install --working-directory /home/gitlab-runner --user root

  • 证书问题

    由于一些gitlab使用https证书, 导致我们注册gtilab的时候会在中间报错X 509... 这种

解决方案就是将gitlab的证书注册到服务器上, 证书放在 /etc/pki/ca-trust/source/anchors/ 文件夹里面, 然后更新证书

或者在注册gitlab runner的时候使用

xxx register --tls-ca-file xxxx

指定证书

  • gitlab runner拉取代码报错

    原因是gitlab runner连接的时候也需要有自己的ssh密钥 它走的不是服务器的ssh key

我们需要先在/home/gitlab-runner目录下生成gitlab runner自己的ssh-key, 然后将这个key复制到目录服务器的 /root/.ssh/authorized_keys 文件中, 同时, 我们还需要在gitlab-runner服务器上使用gitlab-runner用户去ssh连接下, 输入确认, 然后CI才能正常访问, 如下所示:

image2

或者可以尝试在runner的配置中添加下面的

environment = ["GIT_SSL_NO_VERIFY=true"]

配置完类似于下面这样

image1

3.2 私有仓库创建和watchtower运行的命令 ​

  • 私有仓库

私有仓库相关知识链接: https://yeasy .gitbook.io/docker_practice/repository/registry

# 搭建私有仓库 
$ docker run -d -p 5000:5000 --restart=always --name registry registry

本地/服务器想要将镜像推送到私有仓库, 有时还需要在本地配置私有仓库的地址, 否则docker不允许你通过非HTTPS的方式推送, 如下

json
{
  "registry-mirror": [
    "https://hub-mirror.c.163.com",
    "https://mirror.baidubce.com"
  ],
  "insecure-registries": [
    "10.253.xx.xx:5000"
  ]
}
  • watchtower

watchtower相关中文网站链接: https://p3terx.com/archives/docker-watchtower.html

watchtower 支持自定义监测容器对象, 但是有一点, 其目前只支持定时监测容器变化, 不能像Jenkins这种实时触发

docker run -d \
    --name watchtower \
    --restart unless-stopped \
    -v /var/run/docker.sock:/var/run/docker.sock \
    containrrr/watchtower -c \
    <容器名字> --interval 3600
    
# 或者
 docker run -d --name watchtower --restart unless-stopped
 -v /var/run/docker.sock:/var/run/docker.sock 
 containrrr/watchtower -c 
$(cat ~/zk/.watchtower.list) 
--interval 3600

3.3 Docker部署 ​

Nginx的容器部署命令一般为

# 后台 交互 暴漏端口 挂载目录 名字 镜像名 交互shell
docker run -d -it -p 80:80 -v /root/nginx/conf:/etc/nginx/conf.d --name nginx /bin/bash

上面这种挂载如果conf里面没有文件, 那么也会把nginx镜像里面相对文件夹里面本来存在的文件给冲掉.

这里可以使用单个容器部署, 也可以使用docker-compose去部署, compose是配置型的文件, 所以会简单一些

四. 推荐方案 ​

简单的才是最好用的!此处的示例是基于自搭建的gitlab仓库实现的,示例基于下面的文章调试完成

https://juejin.cn/post/6967972435064782879

https://juejin.cn/post/7074780794459258917#heading-9

Gitlab runner(Docker) + Nginx(Docker)部署仓库地址: http://124.221.123.79:8084/

4.1 搭建自己的gitlab仓库 ​

因为仓库搭建起来很占内存,所以此处服务器最好是4G内存+

此处搭建使用docker中文版, docker compose运行

version: '3'
services:
   web:
     image: 'twang2218/gitlab-ce-zh'   #gitlab镜像
     restart: always
     privileged: true  #权限
     hostname: ''       #主机名, 即虚拟机的IP, 这里可以是纯IP
     environment:
        TZ: 'Asia/Shanghai'
        GITLAB_OMNIBUS_CONFIG: |
            external_url '' #主机名,即虚拟机的IP, 这里需要添加http前缀
            gitlab_rails['gitlab_shell_ssh_port'] = 2222
            nginx['listen_port'] = 8084
     ports:
        - '8084:8084'
        - '8443:443'
        - '2222:22'
     volumes:
        - './config:/etc/gitlab'
        - './logs:/var/log/gitlab'
        - './data:/var/opt/gitlab'

配置解析

  • external_url: 该参数是指定外部访问仓库的地址
  • gitlab_shell_ssh_port: ssh拉取代码的端口
  • nginx['listen_port']: nginx监听端口, 不设置的话就是external_url: 80或者443

更多镜像配置可以参考: https://docs.gitlab.com/ee/administration/environment_variables.html

4.2 配置Gitlab runner ​

  • 启动容器
docker run -d --name gitlab-runner --restart always
-v /home/gitlab-runner/config:/etc/gitlab-runner 
-v /var/run/docker.sock:/var/run/docker.sock 
gitlab/gitlab-runner:latest

映射/var/run/docker.sock这个文件是为了让容器可以通过/var/run/docker.sock与Docker守护进程通信,管理其他Docker容器 -v /home/gitlab-runner/config:/etc/gitlab-runner是将runner的配置文件映射到宿主机/home/gitlab-runner/config方便调整和查看配置

  • 注册runner

可以进入容器进行注册, 也可以在外面进行注册, 这里可以使用 gtilab-runner register 进行交互式注册, 按照上面提示填写信息(信息可以在下图所示位置找到)即可

image

其中exector可以选docker. 注册完毕后我们可以在宿主机的/home/gitlab-runner/config 文件夹里面看见runner的配置信息, 如下所示

image3

concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "first-register-runner"
  url = "http://xxx:8084/"
  token = "xxx"
  executor = "docker"
  clone_url = "http://xxx:8084/"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "alpine:latest"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache","/usr/bin/docker:/usr/bin/docker","/var/run/docker.sock:/var/run/docker.sock"]
    shm_size = 0

后续有修改也可以直接在这里进行修改, 大部分配置修改不用手动重启runner 容器

注意:

  • 由于上面我们配置了nginx监听端口, 而runner执行的时候默认是从80等默认端口获取仓库文件的, 所以我们要在上面runner配置config.toml中增加一个属性: clone_url, 其值就是主机地址和nginx监听的端口
  • volumes里面添加docker的一些配置, 这样就可以在runner的docker里面创建基于宿主机的新docker(nginx)

4.3 创建.gitlab-ci.yml文件 ​

如果是使用https, 那么需要寻找自签证书 https://docs.gitlab.com/runner/configuration/tls-self-signed.html#supported-options-for-self-signed-certificates-targeting-the-gitlab-server 其他的一些runner配置可以去gitlab上搜索一下, 我之前配置公司的runner失败了, 找不到完整证书 ci配置文件

image: node:alpine
stages: # 分段
  - install
  - build
  - deploy
cache: # 缓存
  paths:
    - node_modules
job_install:
  tags:
    - v2
  stage: install
  script:
    - npm install
  only:
    - master
job_build:
  tags:
    - v2
  stage: build
  script:
    - npm run build
  artifacts:
    paths:
      - dist/
    expire_in: 3 mins
  only:
    - master
job_deploy:
  tags:
    - v2
  image: docker
  stage: deploy
  dependencies:
    - job_build
  script:
    - docker build . -t app-images
    - if [ $(docker ps -aq --filter name=app-container) ]; then docker rm -f app-container;fi
    - docker run -d -p 8082:80 --name app-container app-images
  only:
    - master

dockerfile配置

FROM nginx:latest
COPY  ./dist /usr/share/nginx/html
EXPOSE 80
# nginx的官方镜像Dockerfile 已经指定 nginx -g "daemon off;"
CMD ["/usr/sbin/nginx", "-g", "daemon off;"]

这里对原文的配置进行了一些改造, 去掉了无用的东西, 最后结果是配置了三个job, 分别为安装依赖和打包, 最后使用打包job生成的dist文件夹进行nginx docker构建与部署

五. 扩展 - 使用Github action ​

仓库地址: https://github.com/scattter/template-react

github给每个用户默认提供了服务器来跑流水线, 所以只需要通过github仓库的action仓库配置流水线即可

配置文件(不同项目可以设置不同的action)

# This is a basic workflow to help you get started with Actions
name: Auto deploy
# Controls when the workflow will run
on:
  # Triggers the workflow on push or pull request events but only for the main branch
  push:
    branches: [ main, dev ]
  pull_request:
    branches: [ main, dev ]
# A workflow run is made up of one or more jobs that can run sequentially or in parallel
jobs:
  # This workflow contains a single job called "build"
  build:
    # The type of runner that the job will run on
    runs-on: ubuntu-latest
    # Steps represent a sequence of tasks that will be executed as part of the job
    steps:
      # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
      - uses: actions/checkout@v3
      - name: Setup Node.js environment
        uses: actions/setup-node@v3.1.1
        with:
          node-version: "14.X"
      - name: install deps
        run: npm install
      - name: build app
        run: npm run build
      - name: deploy build file with scp
        uses: appleboy/scp-action@master
        with:
          host: ${{ secrets.REMOTE_HOST }}
          username: 'root'
          password: ${{ secrets.REMOTE_PASSWORD }}
          port: 22
          source: "dist/"
          target: ${{ secrets.REMOTE_WORK_DIR }}

上面的 secrets.REMOTE_HOST 等是用户自己配置在github仓库的, 这样就避免了私密信息的泄露 高阶的一些action配置(如docker部署)我暂时还没有去看