使用jenkins的流水线功能,可以很方便的知道各个步骤的执行进度和所用时间,还是比较方便的。

在流水线中可以使用docker进行打包, 这样就可以很方便的使用任何docker镜像,而不需要安装对应的环境。

本文要实现的目的如下:

  1. 从git仓库拉取代码,并允许指定分支或tag
  2. jenkins编译代码
  3. 构建镜像
  4. push镜像到远程仓库(此处是阿里云仓库)

使用前准备

本文的jenkins本身也是docker安装的, 为了直接使用宿主机的docker,需要在安装jenkins容器的时候将宿主机的docker映射到jenkins容器中,比如使用docker-compose时其部分配置如下:

1
2
- /var/run/docker.sock:/var/run/docker.sock
- /usr/bin/docker:/usr/bin/docker

Java镜像构建

springboot工程

需要有一个springboot工程的仓库,并且在项目的根文件下新建一个Dockerfile文件, 内容如下:

1
2
3
4
5
6
FROM openjdk:17
RUN echo "Asia/Shanghai" > /etc/timezone
VOLUME /tmp
ADD target/app.jar app.jar
EXPOSE 15800
ENTRYPOINT ["java","-jar","-Dspring.profiles.active=prod", "app.jar"]

同时还需要在项目的根目录下新建一个 settings.xml文件,用于指定中央仓库地址和本地仓库地址, 方便缓存,国内一般可以指定maven的仓库地址为阿里云, 文件内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
<localRepository>/root/.m2</localRepository>
<mirrors>
<mirror>
<id>aliyunmaven</id>
<mirrorOf>*</mirrorOf>
<name>aliyunmaven</name>
<url>https://maven.aliyun.com/repository/public</url>
</mirror>
</mirrors>
<pluginGroups>
<pluginGroup>org.apache.maven.plugins</pluginGroup>
<pluginGroup>org.codehaus.mojo</pluginGroup>
</pluginGroups>
</settings>

jenkins项目

jenkins新建项目, 风格选择“流水线”,然后在流水线处加入groovy脚本, 下面这个是结合git仓库所使用的groovy脚本内容, 可以直接粘贴到jenkins上。

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
def branchTransform(branch) {
return branch.replace("origin/", "");
}
def t = branchTransform("${TAG}");

pipeline {
agent {
docker {
image 'maven:3.8.5-openjdk-17'
args '-v /opt/docker/jenkins/repo/mvn:/root/.m2'
}
}
stages {
stage ("git pull") {
steps {
checkout([$class: 'GitSCM', branches: [[name: '${TAG}']], extensions: [], userRemoteConfigs: [[credentialsId: '.....', url: '....']]])
}
}

stage('mvn package') {
steps {
sh 'mvn clean package -DskipTests=true -s settings.xml -B -U'
}
}
stage('docker build') {
steps {
sh 'docker build -t your_registry/service:' + t + ' .'
}

}
stage('docker push') {
steps {
sh 'docker login --username=username --password=password your_registry'
sh 'docker push your_registry/service:' + t
}
}
}
}

对上面脚本的内容进行一一说明:

  1. branchTransform函数, 是在之前指定了一个构建参数, 此处是git的分支或tag, 这样可以在构建的时候手动指定分支或tag, 设置过程如下图所示(需要提前安装git paramter插件才会有这个界面):

  2. 由于此处使用的是java版本是17,所以使用的maven镜像是maven:3.8.5-openjdk-17, 同时为了加快构建,此处选择将maven的本地仓库地址持久化,注意,此处的maven镜像其实是宿主机上的,所以在进行目录映射的时候, 映射的也是宿主机的路径和maven容器中的路径,对于本例:

    • /opt/docker/jenkins/repo/mvn 宿主机上的路径,maven仓库都会被缓存到此处
    • /root/.m2 maven镜像中的路径,是在上一步中settings.xml文件中指定的
  3. git pull 从仓库中拉取代码, 可以直接使用jenkins自带的流水线语法来生成, 注意, 需要提前生成一个凭证,用于从git仓库获取代码

  4. mvn package 编译java代码

  5. docker build 构建docker镜像

  6. docker push 将镜像push到远程仓库

vue镜像构建

vue工程

此处是使用nginx来运行编译后的vue项目,所以实际上构建的是一个nginx镜像。

需要在vue项目根目录下新建一个Dockerfile文件, 内容如下:

1
2
3
4
5
FROM nginx:1.22.1
RUN echo "Asia/Shanghai" > /etc/timezone
COPY dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 15802

同时,还需要在项目根目录下新建一个nginx.conf文件,用于nginx的一些配置,比如端口转发等。

jenkins项目

基本过程同springboot一样, 此处就不在赘述,直接贴一个groovy脚本, 内容如下:

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
def branchTransform(branch) {
return branch.replace("origin/", "");
}
def t = branchTransform("${TAG}");

pipeline {
agent {
docker {
image 'node:12.5.0'
}
}
stages {
stage ("git pull") {
steps {
checkout([$class: 'GitSCM', branches: [[name: '${TAG}']], extensions: [], userRemoteConfigs: [[credentialsId: '......', url: '......']]])
}
}

stage('npm run build') {
steps {
sh 'npm config set registry https://registry.npm.taobao.org'
sh 'npm install'
sh 'npm run build'
}
}
stage('docker build') {
steps {
sh 'docker build -t your_registry/service:' + t + ' .'
}

}
stage('docker push') {
when { environment name: 'PUSH', value: 'true' }
steps {
sh 'docker login --username=username --password=password your_registry'
sh 'docker push your_registry/service:' + t
}
}
}
}