部署Vue3项目到生产K8s
1. 配置Node.js和Nginx基础镜像
准备Node.js 20和Nginx的基础镜像,用于构建和运行Vue3项目。
2. Nexus新建NPM仓库
在Nexus中创建一个专门用于存储npm依赖的仓库,例如名为vue3-npm的仓库。
3. 批量上传NPM依赖到Nexus私服
将项目所需的npm依赖包批量上传到Nexus私服中,以加速构建过程并确保依赖的可用性。
4. 新建流水线
创建一个Jenkins流水线脚本,实现从代码拉取到K8s部署的全自动化流程。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
| pipeline { agent any tools { nodejs 'node20' } environment { docker_directory = 'docker' frontend_dir = 'xjkyGPT-web' serverport = '80' } stages { stage('scm') { steps { checkout([$class: 'GitSCM', branches: [[name: '${branch}']], doGenerateSubmoduleConfigurations: false, extensions: [], submoduleCfg: [], userRemoteConfigs: [[credentialsId: 'xjcares_git', url: 'http://172.31.70.132:33788/xjcares/xjkygpt.git']]]) sh 'echo \'nodefinished:<\'$(date +%Y-%m-%d\\ %H:%M:%S)\'>\'' } } stage('Build Frontend') { steps { sh ''' cd ${frontend_dir} pwd # 备份原始 package-lock.json (如果存在),以防 npm ci 修改它 if [ -f package-lock.json ]; then cp package-lock.json package-lock.json.bak fi rm -rf node_modules
# 使用Node.js 20容器构建,并在容器内配置npm指向Nexus # 关键修改1: -w /app (而不是 /app/xjkyGPT-web) docker run --rm -v $(pwd):/app -w /app 172.31.10.118/library/node:20-alpine sh -c " # 在容器内也创建 .npmrc 文件 # 关键修改2: 使用 //registry-url/:_authToken 格式 cat > .npmrc <<INNEREOF registry=http://172.31.70.135:8081/repository/vue3-npm/ //172.31.70.135:8081/repository/vue3-npm/:_authToken=YWRtaW46eGpreUAxMjMsLg== fetch-retries=3 fetch-retry-factor=1.5 fetch-retry-maxtimeout=60000 fetch-retry-mintimeout=10000 INNEREOF # 查看 .npmrc 内容以确认 echo '--- .npmrc contents ---' cat .npmrc echo '-----------------------' # 查看当前目录内容 (现在应该是 xjkyGPT-web 的内容) echo '--- Current directory contents ---' ls -la echo '----------------------------------' # 查看 package.json 以确认项目结构 echo '--- package.json ---' cat package.json echo '------------------' # 安装依赖 (使用 Nexus 私服) npm ci --registry=http://172.31.70.135:8081/repository/vue3-npm/ --unsafe-perm=true --allow-root # 执行构建 npm run build " ''' sh 'echo \'nodefinished:<\'$(date +%Y-%m-%d\\ %H:%M:%S)\'>\'' } } stage('build and push image') { steps { sh ''' docker login -u admin -p Harbor12345 172.31.10.118 cd ${frontend_dir} # 生成唯一tag,使用时间戳+构建号 BUILD_TAG=$(date +%Y%m%d-%H%M%S)-${BUILD_NUMBER} REPOSITORY=172.31.10.118/xjcares/${module}-frontend:${BUILD_TAG} # 创建Dockerfile用于构建前端镜像 cat > Dockerfile <<EOF FROM 172.31.10.118/library/nginx:alpine ENV TZ=PRC RUN ln -snf /usr/share/zoneinfo/\$TZ /etc/localtime && echo \$TZ > /etc/timezone COPY dist/ /usr/share/nginx/html/ COPY nginx.conf /etc/nginx/conf.d/default.conf EOF if [ ! -f nginx.conf ]; then cat > nginx.conf <<'NGINXEOF' events { worker_connections 1024; }
http { include /etc/nginx/mime.types; default_type application/octet-stream; server { listen 80; root /usr/share/nginx/html; index index.html; # 代理 API 请求到后端服务 location /api/ { # 去掉 proxy_pass 末尾的斜杠 proxy_pass http://gateway-service:8888; # 添加重写规则,去掉 /api/ 前缀 rewrite ^/api/(.*)$ /$1 break; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 60s; proxy_send_timeout 60s; proxy_read_timeout 60s; } # 处理Vue Router History模式 location / { try_files $uri $uri/ /index.html; } # 静态资源缓存 - FIXED: escaped backslash location ~* \\.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ { expires 1y; add_header Cache-Control "public, immutable"; } } } NGINXEOF fi docker build -t $REPOSITORY . docker push $REPOSITORY # 将镜像tag保存到workspace根目录下的文件 echo "$REPOSITORY" > ../IMAGE_TAG.txt docker logout 172.31.10.118 docker rmi $REPOSITORY ''' } }
stage('deploy') { steps { kubeconfig(caCertificate: '', credentialsId: 'snowlotus-kubeconfig', serverUrl: '') { sh ''' pwd # 从workspace根目录读取IMAGE_TAG.txt NEW_IMAGE_TAG=$(cat IMAGE_TAG.txt) # 创建K8s部署YAML文件 cat > frontend-deployment.yaml <<EOF apiVersion: apps/v1 kind: Deployment metadata: name: ${module}-frontend labels: app: ${module}-frontend spec: replicas: ${instanceNum} selector: matchLabels: app: ${module}-frontend template: metadata: labels: app: ${module}-frontend spec: containers: - name: ${module}-frontend image: $NEW_IMAGE_TAG ports: - containerPort: 80 resources: requests: memory: ${memory} cpu: "0.1" limits: memory: ${memory} cpu: "0.5" EOF # 创建Service YAML文件 cat > frontend-service.yaml <<EOF apiVersion: v1 kind: Service metadata: name: ${module}-frontend-svc labels: app: ${module}-frontend spec: selector: app: ${module}-frontend ports: - protocol: TCP port: 80 targetPort: 80 nodePort: 31833 type: NodePort EOF # 应用新配置 kubectl delete -f frontend-deployment.yaml --ignore-not-found=true kubectl delete -f frontend-service.yaml --ignore-not-found=true kubectl apply -f frontend-deployment.yaml kubectl apply -f frontend-service.yaml ''' } } } } }
|
5. 项目中新建.npmrc文件
在前端项目的根目录下创建.npmrc文件,配置npm私服地址,使得本地、测试环境和生产环境都能统一使用私服进行依赖安装。
1 2 3 4 5 6
| registry=http://172.31.70.135:8081/repository/vue3-npm/ //172.31.70.135:8081/repository/vue3-npm/:_authToken=YWRtaW46eGpreUAxMjMsLg== fetch-retries=3 fetch-retry-factor=1.5 fetch-retry-maxtimeout=60000 fetch-retry-mintimeout=10000
|
6. 结果
整个流程实现了在流水线中自动构建、打包、封装成镜像,并部署到K8s集群。无需手动上传node_modules,无需手动配置Nginx的前端路由,前端项目作为一个独立的K8s Pod运行。