Jenkins 集成部署 SpringBoot

本贴最后更新于 1918 天前,其中的信息可能已经天翻地覆

Jenkins 集成部署 SpringBoot

1. 前言

随着业务的增长,需求也开始增多,每个需求的大小,开发周期,发布时间都不一致。基于微服务的系统架构,功能的叠加,对应的服务的数量也在增加,大小功能的快速迭代,更加要求部署的快速化,智能化。因此,传统的人工部署已经心有余而力不足。
持续集成,持续部署,持续交互对于微服务开发来说,是提高团队整体效率不可或缺的一环。合理的使用 CI,CD 能够极大的提高了生产效率,也提高了产品的交互质量。

本文主要介绍的内容有如下几点

  • docker 安装 Jenkins
  • Jenkins 安装后的初始化和相关配置
  • SpringBoot 的 docker 打包镜像
  • Jenkins 从 Github 拉取源码
  • Jenkins 将 SpringBoot 项目部署成 docker

阅读本文需要对 docker 和 linux 有一定的了解

2. Jenkins 安装及配置

2.1 安装 Jenkins

Jenkins 的安装采用的是 docker 版本安装,相对与其他版本的安装,会简单很多

运行 Jenkins 容器命令如下

docker run \
  --privileged=true \
  --name jenkins \
  -d \
  -u root \
  -p 8080:8080 \
  -v /usr/bin/docker:/usr/bin/docker \
  -v /usr/local/soft/jenkins:/var/jenkins_home \
  -v /var/run/docker.sock:/var/run/docker.sock \
  -e TZ=Asia/Shanghai \
  -v "$HOME":/home \
  jenkins/jenkins

相关参数说明

  • --privileged:使得容器内的用户拥有 root 权限
  • --name:运行容器的名称
  • -d: 容器后台运行
  • -u:指定容器的用户
  • -v /usr/bin/docker:/usr/bin/docker:将宿主的/var/run/docker.sock 文件挂载到容器内的同样位置,从而让容器内可以通过 unix socket 调用宿主的 Docker 引擎
  • -v /usr/bin/docker:/usr/bin/docker:同上
  • -v /usr/local/soft/jenkins:/var/jenkins_home:将 Jenkins 的数据目录挂载到主机目录/usr/local/soft/jenkins
  • -e:指定时区

2.2 初始化 Jenkins

  1. 浏览器打开 Jenkins 地址 (http://127.0.0.1/):8080

image1.png

找到 Jenkins 映射目录,找到相应文件,查看密码,登录

  1. 安装插件,一般直接选择推荐的插件安装

image2.png

  1. 安装插件较慢,等待片刻即可

image3.png

  1. 创建系统管理员

image4.png

  1. 安装完成,进入下一步

image5.png

2.3 配置相应的 Jenkins

2.3.1 maven

  1. 安装 maven

因为使用 Jenkins 默认的 maven 下载包比较慢,所以这里我自行安装 maven

进入设置-> 全局工具设置

image6.png

这里我安装的是 maven3.6.1

  1. 修改 maven 的配置

修改 Jenkins 安装目录下的 maven 配置,我的 maven 在主机的目录为 /usr/local/soft/jenkins/tools/hudson.tasks.Maven_MavenInstallation/maven_3.6.1,自己可自行判断目录

配置文件修改后为

<?xml version="1.0" encoding="UTF-8"?>

<!--
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements.  See the NOTICE file
distributed with this work for additional information
regarding copyright ownership.  The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License.  You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied.  See the License for the
specific language governing permissions and limitations
under the License.
-->

<!--
 | This is the configuration file for Maven. It can be specified at two levels:
 |
 |  1. User Level. This settings.xml file provides configuration for a single user,
 |                 and is normally provided in ${user.home}/.m2/settings.xml.
 |
 |                 NOTE: This location can be overridden with the CLI option:
 |
 |                 -s /path/to/user/settings.xml
 |
 |  2. Global Level. This settings.xml file provides configuration for all Maven
 |                 users on a machine (assuming they're all using the same Maven
 |                 installation). It's normally provided in
 |                 ${maven.conf}/settings.xml.
 |
 |                 NOTE: This location can be overridden with the CLI option:
 |
 |                 -gs /path/to/global/settings.xml
 |
 | The sections in this sample file are intended to give you a running start at
 | getting the most out of your Maven installation. Where appropriate, the default
 | values (values used when the setting is not specified) are provided.
 |
 |-->
<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">
  <!-- localRepository
   | The path to the local repository maven will use to store artifacts.
   |
   | Default: ${user.home}/.m2/repository
  <localRepository>/path/to/local/repo</localRepository>
  -->
  <localRepository>/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/MavenRepository</localRepository>

  <!-- interactiveMode
   | This will determine whether maven prompts you when it needs input. If set to false,
   | maven will use a sensible default value, perhaps based on some other setting, for
   | the parameter in question.
   |
   | Default: true
  <interactiveMode>true</interactiveMode>
  -->

  <!-- offline
   | Determines whether maven should attempt to connect to the network when executing a build.
   | This will have an effect on artifact downloads, artifact deployment, and others.
   |
   | Default: false
  <offline>false</offline>
  -->

  <!-- pluginGroups
   | This is a list of additional group identifiers that will be searched when resolving plugins by their prefix, i.e.
   | when invoking a command line like "mvn prefix:goal". Maven will automatically add the group identifiers
   | "org.apache.maven.plugins" and "org.codehaus.mojo" if these are not already contained in the list.
   |-->
  <pluginGroups>
    <pluginGroup>com.spotify</pluginGroup>
    <!-- pluginGroup
     | Specifies a further group identifier to use for plugin lookup.
    <pluginGroup>com.your.plugins</pluginGroup>
    -->
  </pluginGroups>

  <!-- proxies
   | This is a list of proxies which can be used on this machine to connect to the network.
   | Unless otherwise specified (by system property or command-line switch), the first proxy
   | specification in this list marked as active will be used.
   |-->
  <proxies>
    <!-- proxy
     | Specification for one proxy, to be used in connecting to the network.
     |
    <proxy>
      <id>optional</id>
      <active>true</active>
      <protocol>http</protocol>
      <username>proxyuser</username>
      <password>proxypass</password>
      <host>proxy.host.net</host>
      <port>80</port>
      <nonProxyHosts>local.net|some.host.com</nonProxyHosts>
    </proxy>
    -->
  </proxies>

  <!-- servers
   | This is a list of authentication profiles, keyed by the server-id used within the system.
   | Authentication profiles can be used whenever maven must make a connection to a remote server.
   |-->
  <servers>
    <!-- server
     | Specifies the authentication information to use when connecting to a particular server, identified by
     | a unique name within the system (referred to by the 'id' attribute below).
     |
     | NOTE: You should either specify username/password OR privateKey/passphrase, since these pairings are
     |       used together.
     |
    <server>
      <id>deploymentRepo</id>
      <username>repouser</username>
      <password>repopwd</password>
    </server>
    -->

    <!-- Another sample, using keys to authenticate.
    <server>
      <id>siteServer</id>
      <privateKey>/path/to/private/key</privateKey>
      <passphrase>optional; leave empty if not used.</passphrase>
    </server>
    -->
  </servers>

  <!-- mirrors
   | This is a list of mirrors to be used in downloading artifacts from remote repositories.
   |
   | It works like this: a POM may declare a repository to use in resolving certain artifacts.
   | However, this repository may have problems with heavy traffic at times, so people have mirrored
   | it to several places.
   |
   | That repository definition will have a unique id, so we can create a mirror reference for that
   | repository, to be used as an alternate download site. The mirror site will be the preferred
   | server for that repository.
   |-->
  <mirrors>
    <!-- mirror
     | Specifies a repository mirror site to use instead of a given repository. The repository that
     | this mirror serves has an ID that matches the mirrorOf element of this mirror. IDs are used
     | for inheritance and direct lookup purposes, and must be unique across the set of mirrors.
     |
    <mirror>
      <id>mirrorId</id>
      <mirrorOf>repositoryId</mirrorOf>
      <name>Human Readable Name for this Mirror.</name>
      <url>http://my.repository.com/repo/path</url>
    </mirror>
     -->
    <mirror>
      <id>alimaven</id>
      <name>aliyun maven</name>
      <mirrorOf>central</mirrorOf>
      <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
    </mirror>
  </mirrors>

  <!-- profiles
   | This is a list of profiles which can be activated in a variety of ways, and which can modify
   | the build process. Profiles provided in the settings.xml are intended to provide local machine-
   | specific paths and repository locations which allow the build to work in the local environment.
   |
   | For example, if you have an integration testing plugin - like cactus - that needs to know where
   | your Tomcat instance is installed, you can provide a variable here such that the variable is
   | dereferenced during the build process to configure the cactus plugin.
   |
   | As noted above, profiles can be activated in a variety of ways. One way - the activeProfiles
   | section of this document (settings.xml) - will be discussed later. Another way essentially
   | relies on the detection of a system property, either matching a particular value for the property,
   | or merely testing its existence. Profiles can also be activated by JDK version prefix, where a
   | value of '1.4' might activate a profile when the build is executed on a JDK version of '1.4.2_07'.
   | Finally, the list of active profiles can be specified directly from the command line.
   |
   | NOTE: For profiles defined in the settings.xml, you are restricted to specifying only artifact
   |       repositories, plugin repositories, and free-form properties to be used as configuration
   |       variables for plugins in the POM.
   |
   |-->
  <profiles>
    <!-- profile
     | Specifies a set of introductions to the build process, to be activated using one or more of the
     | mechanisms described above. For inheritance purposes, and to activate profiles via <activatedProfiles/>
     | or the command line, profiles have to have an ID that is unique.
     |
     | An encouraged best practice for profile identification is to use a consistent naming convention
     | for profiles, such as 'env-dev', 'env-test', 'env-production', 'user-jdcasey', 'user-brett', etc.
     | This will make it more intuitive to understand what the set of introduced profiles is attempting
     | to accomplish, particularly when you only have a list of profile id's for debug.
     |
     | This profile example uses the JDK version to trigger activation, and provides a JDK-specific repo.
    <profile>
      <id>jdk-1.4</id>

      <activation>
        <jdk>1.4</jdk>
      </activation>

      <repositories>
        <repository>
          <id>jdk14</id>
          <name>Repository for JDK 1.4 builds</name>
          <url>http://www.myhost.com/maven/jdk14</url>
          <layout>default</layout>
          <snapshotPolicy>always</snapshotPolicy>
        </repository>
      </repositories>
    </profile>
    -->

    <!--
     | Here is another profile, activated by the system property 'target-env' with a value of 'dev',
     | which provides a specific path to the Tomcat instance. To use this, your plugin configuration
     | might hypothetically look like:
     |
     | ...
     | <plugin>
     |   <groupId>org.myco.myplugins</groupId>
     |   <artifactId>myplugin</artifactId>
     |
     |   <configuration>
     |     <tomcatLocation>${tomcatPath}</tomcatLocation>
     |   </configuration>
     | </plugin>
     | ...
     |
     | NOTE: If you just wanted to inject this configuration whenever someone set 'target-env' to
     |       anything, you could just leave off the <value/> inside the activation-property.
     |
    <profile>
      <id>env-dev</id>

      <activation>
        <property>
          <name>target-env</name>
          <value>dev</value>
        </property>
      </activation>

      <properties>
        <tomcatPath>/path/to/tomcat/instance</tomcatPath>
      </properties>
    </profile>
    -->
  </profiles>

  <!-- activeProfiles
   | List of profiles that are active for all builds.
   |
  <activeProfiles>
    <activeProfile>alwaysActiveProfile</activeProfile>
    <activeProfile>anotherAlwaysActiveProfile</activeProfile>
  </activeProfiles>
  -->
</settings>

修改的位置分别为:

  1. maven 本地仓库的位置:
<localRepository>/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/MavenRepository</localRepository>
  1. mvn 打包 docker 的插件,不添加会报错
<pluginGroup>com.spotify</pluginGroup>
  1. 阿里云镜像加速
 <mirror>
   <id>alimaven</id>
   <name>aliyun maven</name>
   <mirrorOf>central</mirrorOf>
   <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
 </mirror>

2.3.2 配置环境变量

系统管理-> 系统设置

添加环境变量

image7.png

添加的环境变量为:

MAVEN_HOME
/var/jenkins_home/tools/hudson.tasks.Maven_MavenInstallation/maven_3.6.1
Path
$Path:$MAVEN_HOME/bin:

2. SpringBoot 项目配置

3.1 Dockerfile 文件编写

FROM java:latest

ENV SERVER_PORT 8080
ENV CONSUL_SERVER 127.0.0.1
ENV JVM_MEMORY 512M

COPY ./target/*.jar /tmp

RUN cp -f ./tmp/*.jar /app.jar

EXPOSE 8080

CMD echo "The application is starting..." && \
    java -Xmx${JVM_MEMORY} -jar /app.jar

3.2 pom 文件编写

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.1.6.RELEASE</version>
		<relativePath/> <!-- lookup parent from repository -->
	</parent>
	<groupId>com.tao</groupId>
	<artifactId>jenkins</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>jenkins</name>
	<description>Demo project for Spring Boot</description>

	<properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
		<java.version>1.8</java.version>
        <docker.image.prefix>SpringBoot-jenkins</docker.image.prefix>
	</properties>

	<dependencies>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-freemarker</artifactId>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>

	<repositories>
		<repository>
			<id>aliyun-repos</id>
			<url>http://maven.aliyun.com/nexus/content/groups/public/</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

	<build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>

            <plugin>
                <groupId>com.spotify</groupId>
                <artifactId>docker-maven-plugin</artifactId>
                <version>0.4.11</version>
                <configuration>
					<imageName>mytest/${project.artifactId}</imageName>
					<dockerDirectory>./</dockerDirectory>
					<resources>
						<resource>
							<targetPath>/</targetPath>
							<directory>${project.build.directory}</directory>
							<include>${project.build.finalName}.jar</include>
						</resource>
					</resources>
                </configuration>
            </plugin>
        </plugins>
	</build>

</project>

3.3 项目 github 地址

Github 地址

https://github.com/boolean-dev/jenkins.git

3. Jenkins 部署

3.1 源码管理

填写 Github 的项目地址即可

image8.png

3.2 项目构建参数

  1. maven 打包

选择 maven 的版本,并且执行 maven 构建命令

clean install -Dmaven.test.skip=true

  1. 执行 shell

    mvn docker:build
    echo "which docker"
    docker -v
    echo "当前docker 镜像:"
    echo "启动容器----->"
    docker images 
    docker run --name springboot -p 8080:8080 -d mytest/jenkins
    echo "启动服务成功!"
    

image9.png

注:第一次执行 shell 的时候,因为 springboot 容器还未运行,所以无需停止和移除。所以第二次构建容器的时候,运行前需提前停止和移除容器,所以采用以下的 shell

mvn docker:build
echo "which docker"
docker -v
echo "当前docker 镜像:"
echo "启动容器----->"
docker stop springboot
echo "移除旧容器"
docker rm springboot
docker images 
docker run --name springboot -p 8080:8080 -d mytest/jenkins
echo "启动服务成功!"

3.3 构建项目

可能在构建的过程中还会存在部分 bug,只需查看相应日志,再 google,一般都能解决。

构建完成后,在宿主机上执行 docker ps 查看容器是否运行

image11.png

如图,部署成功了

image10.png

4. 后记

本篇博客实现了简单的 SpringBoot、jenkins 和 docker 继承部署,基本上全是运行在 docker 容器中,由此可见 docker 确实十分强大。

但是本篇博客之讲了简单的集成部署,并且采用的是自由式风格的编排,现主流的编排是使用流水线,那样更加便捷,并且功能更加强大。

现阶段还存在的缺点:

  • 使用自由式风格以及 shell 的编排模块,部署大量项目时繁杂
  • 本次部署是 Jenkins 部署项目是在宿主机上,具有很大的局限性
  • 历史镜像尚未保存
  • 不能够多分枝部署
  • 未实现 github 提交代码,自动更新
  • 镜像存储在本地,未存储在阿里云等镜像仓库中

后期可能进行的优化:

  • 镜像存储在阿里云镜像仓库中,并且根据 git 的 tag 对镜像进行备份
  • 多分枝集成部署
  • 实现 github 钩子程序
  • docker 运行采用 swarm 集群或者 K8s 集群,便于管理集群
  • ...

5. 参考链接

使用 Jenkins 和 Docker 持续集成 java 项目

解放双手 | Jenkins + gitlab + maven 自动打包部署项目

使用 Jenkins 自动部署 Docker 服务(一、Jenkins 搭建篇)

使用 Jenkins 自动部署 Docker 服务(二、构建部署篇)

基于 Jenkins,docker 实现自动化部署(持续交互)

CentOS7 中 Docker 文件挂载,容器中的权限问题

SpringBoot | 第十四章:基于 Docker 的简单部署

  • Jenkins

    Jenkins 是一套开源的持续集成工具。它提供了非常丰富的插件,让构建、部署、自动化集成项目变得简单易用。

    53 引用 • 37 回帖 • 1 关注
  • Docker

    Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的操作系统上。容器完全使用沙箱机制,几乎没有性能开销,可以很容易地在机器和数据中心中运行。

    491 引用 • 917 回帖
  • 集成部署
    1 引用 • 4 回帖

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...
  • someone34810

    很清晰 😄

  • 其他回帖
  • someone
    作者

    谢谢夸奖 ❤️

  • someone
    作者

    谢谢鼓励 ❤️

  • wky181

    很赞 👍