自动化构建 Vue/H5 前端应用
自动化构建 Vue/H5 应用,其构建方式和自动化构建 Java 基本相同,重点是更改 Deployment、Jenkinsfile 和 Dockerfile 即可。
本示例项目可以从 https://gitee.com/dukuan/vue-project.git
找到该项目。接下来将该项目导入到自己的 Gitlab 中。
定义 Jenkinsfile
在项目仓库根目录创建 Jenkinsfile 文件,文件内容如下:
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
216pipeline {
agent {
kubernetes {
cloud 'kubernetes-test'
slaveConnectTimeout 1200
workspaceVolume hostPathWorkspaceVolume(hostPath: "/opt/workspace", readOnly: false)
yaml '''
apiVersion: v1
kind: Pod
spec:
containers:
- args: [\'$(JENKINS_SECRET)\', \'$(JENKINS_NAME)\']
image: \'registry.cn-beijing.aliyuncs.com/citools/jnlp:alpine\'
name: jnlp
imagePullPolicy: IfNotPresent
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
readOnly: false
- command:
- "cat"
env:
- name: "LANGUAGE"
value: "en_US:en"
- name: "LC_ALL"
value: "en_US.UTF-8"
- name: "LANG"
value: "en_US.UTF-8"
image: "registry.cn-beijing.aliyuncs.com/citools/node:lts"
imagePullPolicy: "IfNotPresent"
name: "build"
tty: true
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
- command:
- "cat"
env:
- name: "LANGUAGE"
value: "en_US:en"
- name: "LC_ALL"
value: "en_US.UTF-8"
- name: "LANG"
value: "en_US.UTF-8"
image: "registry.cn-beijing.aliyuncs.com/citools/kubectl:self-1.17"
imagePullPolicy: "IfNotPresent"
name: "kubectl"
tty: true
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
readOnly: false
- command:
- "cat"
env:
- name: "LANGUAGE"
value: "en_US:en"
- name: "LC_ALL"
value: "en_US.UTF-8"
- name: "LANG"
value: "en_US.UTF-8"
image: "registry.cn-beijing.aliyuncs.com/citools/docker:19.03.9-git"
imagePullPolicy: "IfNotPresent"
name: "docker"
tty: true
volumeMounts:
- mountPath: "/etc/localtime"
name: "localtime"
readOnly: false
- mountPath: "/var/run/docker.sock"
name: "dockersock"
readOnly: false
restartPolicy: "Never"
nodeSelector:
build: "true"
securityContext: {}
volumes:
- hostPath:
path: "/var/run/docker.sock"
name: "dockersock"
- hostPath:
path: "/usr/share/zoneinfo/Asia/Shanghai"
name: "localtime"
- name: "cachedir"
hostPath:
path: "/opt/m2"
'''
}
}
stages {
stage('Pulling Code') {
parallel {
stage('Pulling Code by Jenkins') {
when {
expression {
env.gitlabBranch == null
}
}
steps {
git(
url: 'git@gitlab.59izt.com:kubernetes/vue-project.git',
changelog: true,
poll: true,
branch: "${BRANCH}",
credentialsId: 'gitlab-key'
)
script {
COMMIT_ID = sh(
returnStdout: true,
script: "git log -n 1 --pretty=format:'%h'"
).trim()
TAG = BUILD_TAG + '-' + COMMIT_ID
println "Current branch is ${BRANCH}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"
}
}
}
stage('Pulling Code by trigger') {
when {
expression {
env.gitlabBranch != null
}
}
steps {
git(
url: 'git@gitlab.59izt.com:kubernetes/vue-project.git',
branch: env.gitlabBranch,
changelog: true,
poll: true,
credentialsId: 'gitlab-key'
)
script {
COMMIT_ID = sh(
returnStdout: true,
script: "git log -n 1 --pretty=format:'%h'"
).trim()
TAG = BUILD_TAG + '-' + COMMIT_ID
println "Current branch is ${env.gitlabBranch}, Commit ID is ${COMMIT_ID}, Image TAG is ${TAG}"
}
}
}
}
}
stage('Building') {
steps {
container(name: 'build') {
sh '''
npm install --registry=https://registry.npm.taobao.org
npm run build
'''
}
}
}
stage('Docker build for creating image') {
environment {
HARBOR_USER = credentials('HARBOR_ACCOUNT')
}
steps {
container(name: 'docker') {
sh """
echo ${HARBOR_USER_USR} ${HARBOR_USER_PSW} ${TAG}
docker build -t ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG} .
docker login -u ${HARBOR_USER_USR} -p ${HARBOR_USER_PSW} ${HARBOR_ADDRESS}
docker push ${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG}
"""
}
}
}
stage('Deploying to K8s') {
environment {
MY_KUBECONFIG = credentials('kubernetes-test')
}
steps {
container(name: 'kubectl') {
sh """
/usr/local/bin/kubectl --kubeconfig $MY_KUBECONFIG \
set image deploy -l \
app=${IMAGE_NAME} \
${IMAGE_NAME}=${HARBOR_ADDRESS}/${REGISTRY_DIR}/${IMAGE_NAME}:${TAG} \
-n $NAMESPACE
"""
}
}
}
}
environment {
COMMIT_ID = ''
HARBOR_ADDRESS = 'harbor.china-snow.net'
REGISTRY_DIR = 'kubernetes'
IMAGE_NAME = 'vue-project'
NAMESPACE = 'kubernetes'
TAG = ''
}
parameters {
gitParameter(
branch: '',
branchFilter: 'origin/(.*)',
defaultValue: '',
description: 'Branch for build and deploy',
name: 'BRANCH',
quickFilterEnabled: false,
selectedValue: 'NONE',
sortMode: 'NONE',
tagFilter: '*',
type: 'PT_BRANCH'
)
}
}以上文件内容相比 Java 项目的 Jenkinsfile 文件,只是修改了以下几个地方:
- 构建容器(build)改为具有 NodeJS 环境的镜像,版本需要和公司项目一致
1
image: "registry.cn-beijing.aliyuncs.com/citools/node:lts"
- NodeJS 的缓存目录为 node_modules,因为 workspace 采用的是 hostPath,该目录会被缓存到创建 Pod 节点的/opt/目录,所以这里的 cachedir 挂载项可以去除;
- 修改
Pulling Code
Stage 中 git 的 URL 地址; - 修改
Building
Stage 中的构建命令,具体的命令可以询问开发
1
2npm install --registry=https://registry.npm.taobao.org
npm run build- 修改 environment 配置中的镜像名称为项目名称
定义 Dockerfile
在项目仓库根目录创建 Dockerfile 文件,文件内容如下:
1
2
3FROM registry.cn-beijing.aliyuncs.com/dotbalo/nginx:1.15.12
COPY dist/* /usr/share/nginx/html/
定义 kubernetes 资源
对于 Kubernetes 的资源也是类似的,只需要更改资源名称和端口号即可
创建 vue-demo.yaml 文件,内容如下:
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
114apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: vue-project
name: vue-project
namespace: kubernetes
spec:
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 10
selector:
matchLabels:
app: vue-project
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
labels:
app: vue-project
spec:
affinity:
nodeAffinity:
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 1
preference:
matchExpressions:
- key: app
operator: In
values:
- vue-project
containers:
- image: nginx
imagePullPolicy: IfNotPresent
name: vue-project
ports:
- containerPort: 80
name: http
protocol: TCP
env:
- name: TZ
value: Asia/Shanghai
- name: LANG
value: C.UTF-8
resources:
limits:
cpu: "4"
memory: 4Gi
requests:
cpu: "1"
memory: 1Gi
lifecycle: {}
readinessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 80
timeoutSeconds: 2
livenessProbe:
failureThreshold: 2
initialDelaySeconds: 30
periodSeconds: 10
successThreshold: 1
tcpSocket:
port: 80
timeoutSeconds: 2
dnsPolicy: ClusterFirst
imagePullSecrets:
- name: harborkey
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
apiVersion: v1
kind: Service
metadata:
labels:
app: vue-project
name: vue-project
namespace: kubernetes
spec:
ports: # 端口按照实际情况进行修改
- name: http
port: 80
protocol: TCP
targetPort: 80
selector:
app: vue-project
sessionAffinity: None
type: ClusterIP
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: vue-project
namespace: kubernetes
spec:
rules:
- host: vue-project.test.com
http:
paths:
- backend:
service:
name: vue-project
port:
number: 80
path: /
pathType: ImplementationSpecific创建该资源
1
2
3
4# kubectl create -f vue-demo.yaml
deployment.apps/vue-project created
service/vue-project created
ingress.networking.k8s.io/vue-project created
创建 Jenkins Job
创建 Jenkins Job 和之前并无太大区别。
登录 Jenkins –> 选择
New Item
输入 Job 名称,选择 Job 类型为Pipeline
点击 OK 后,选择
Pipeline
–> 选择Pipeline script from SCM
,SCM 选择Git
,输入 GitLab 上的项目地址,选择 Credentials 证书;点击确定,有于 Pipeline 的特性,需要手动运行一次,才会出现
Build with Parameters
选项; 所以需要搜东点击一次Build Now
;再次选择 vue-project 项目, 点击
Build with Parameters
,会自动获取该项目所有的分支,选择一个分支,点击Build
,进行构建;可以点击 Bule Ocean 进入控制台查看构建状态,注意查看最后的镜像 TAG
查看 Harbor 仓库是否已经存在镜像
在 kubernetes 集群查看服务是否更新,查看镜像TAG是否是最新的镜像
1
2# kubectl get deployments.apps -n kubernetes vue-project -oyaml |grep image:
image: harbor.china-snow.net/kubernetes/vue-project:jenkins-vue-project-2-9720fd5