前端部署方案
一. 触发方式
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/zk1.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:latest2.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才能正常访问, 如下所示:

或者可以尝试在runner的配置中添加下面的
environment = ["GIT_SSL_NO_VERIFY=true"]配置完类似于下面这样

3.2 私有仓库创建和watchtower运行的命令
- 私有仓库
私有仓库相关知识链接: https://yeasy .gitbook.io/docker_practice/repository/registry
# 搭建私有仓库
$ docker run -d -p 5000:5000 --restart=always --name registry registry本地/服务器想要将镜像推送到私有仓库, 有时还需要在本地配置私有仓库的地址, 否则docker不允许你通过非HTTPS的方式推送, 如下
{
"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 36003.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仓库实现的,示例基于下面的文章调试完成
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 进行交互式注册, 按照上面提示填写信息(信息可以在下图所示位置找到)即可

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

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:
- masterdockerfile配置
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部署)我暂时还没有去看
