How to deploy spring boot jar file to EC2 using jenkins?

心不动则不痛 提交于 2019-12-22 08:23:23

问题


i am trying to deploy the spring boot app to AWS EC2 instances. i have seen lot of blog and tutorial explained deployment process completely which is understandable. i am struggling how to do continuous deployment or delivery in jenkins which main feature where spring boot app name or jar file name changes that time.

my pipeline

  pipeline {
    agent any

    tools{
       maven 'localmaven' 
    }
    stages {
        stage('Build') { 
            steps {
               sh 'mvn clean package' 
            }
            post {
               success {
                    echo 'Now Archiving...'
                    archiveArtifacts artifacts: '**/target/*.jar'
                   }
              } 
          }


    stage('Deliver') {
        steps {
             sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu'
             sh "sshpass -p password ssh -o StrictHostKeyChecking=no -i /var/lib/jenkins/secrets/mykey ubuntu@00.00.00.00 '/home/ubuntu/start.sh'"
        }
    }
}

}

Server start and stop and restart are handled in shell script.

my start.sh

#!/bin/bash
nohup java -jar /home/ubuntu/aws-0.0.1-SNAPSHOT.jar > /home/ubuntu/log.txt 2>&1 &
echo $! > /home/ubuntu/pid.file

This start my server perfectly and works fine..

here my doubt is currently in start.sh i am using same jar file name so it works fine but in production with version change jar file name also change how to handle that situation. Help me to know about that process. Where i can get that complete idea and everything thanks in advance


回答1:


I must say you should maintain you artifact’s version as a standard process for non-prod and prod deployment. Usually in non-prod environment you can plan for SNAPSHOT version and in production you should go for RELEASE version which can be generated using mvn release prepare release perform using maven-release-plugin. It will bump up your pom version for next subsequent releases. You can store your artifact to AWS S3 or Artifactory or Nexus (for high availability ) like the ubuntu machine that you are referring here.

Now I would suggest you should add one more stage named like stage('Release') where you should use using maven-release-plugin to release the version and store it to a separate path like

ubuntu@00.00.00.00:/home/ubuntu/RELEASE/${version}

and as per you stage('Build') should copy to another path like

ubuntu@00.00.00.00:/home/ubuntu/SNAPSHOT/${version}

You can execute stage 'Release' and 'Prod-Deliver' based on conditional input parameter of your Jenkins pipeline. Here would be a possible solution for a smooth CICD in your case.

   pipeline {
    agent any

    tools{
       maven 'localmaven' 
    }
    stages {
        stage('Build') { 
            steps {
               sh 'mvn clean install' 
            }
            post {
               success {
                    echo 'Now Archiving...'
                   }
              } 
          }

        stage('Release') { 
            steps {
               sh 'elease:prepare release:perform' 
            }
            post {
               success {
                    ////
                   }
              } 
          }

      stage('NonProd-Deliver') {
          steps {
               /*
               You can extract the version from pom.xml,replace you project location in jenkins workspace in the below command
               */
               sh 'version=$(echo -e 'setns x=http://maven.apache.org/POM/4.0.0\ncat /x:project/x:version/text()' | xmllint --shell ${YOUR_PROJECT_LOCATION}/pom.xml | grep -v /)'
               sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu/SNAPSHOT/${version}'
               sh "sshpass -p password ssh -o StrictHostKeyChecking=no -i /var/lib/jenkins/secrets/mykey ubuntu@00.00.00.00 '/home/ubuntu/start.sh nonprod $version'"
          }
      }

       stage('Prod-Deliver') {
        steps {
              /*
               For production release you should pass the version as a parameter to your jenkins pipeline which is going to be in production
               */
             sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu/RELEASE/${version} '
             sh "sshpass -p password ssh -o StrictHostKeyChecking=no -i /var/lib/jenkins/secrets/mykey ubuntu@00.00.00.00 '/home/ubuntu/start.sh prod ${version}'"
        }
    }

}
}

You have to add the condtion in your script file as well like below

#!/bin/bash
release_type=$1
version=$2
if [[ ${release_type} == "prod" ]]; then
  # non snapshot release to production env
  nohup java -jar /home/ubuntu/RELEASE/${version}/aws-0.0.1.jar > /home/ubuntu/log.txt 2>&1 & 
else
  # snapshot release to non production env
  nohup java -jar /home/ubuntu/SNAPSHOT/${version}/aws-0.0.1-SNAPSHOT.jar > /home/ubuntu/log.txt 2>&1 &
fi
echo $! > /home/ubuntu/pid.file



回答2:


I would say keep the name of the final artifact as a constant name using the build.finalName and have a provision to keep the build version somewhere inside the build.

As I see that you use spring boot, You can save version information part of the build by using build-info goal of spring-boot-maven-plugin as shown below.

  <build>
    <finalName>your-artifact-name</finalName>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <executions>
          <execution>
            <goals>
              <goal>build-info</goal>
            </goals>
          </execution>
        </executions>
      </plugin>
    </plugins>
  </build>

and access the maven build information via the actuator endpoint http://localhost:8080/actuator/info.

Or, You can get the version information saved in classpath:META-INF/build-info.properties by looking into the jar file by using the following command.

$> unzip -qc your-artifact-name.jar META-INF/build-info.properties
#Properties
#Fri May 04 17:43:06 IST 2018
build.time=2018-05-04T12\:13\:06.225Z
build.artifact=your-artifact-name
build.group=com.example
build.name=your-artifact-name
build.version=1.0.0.SNAPSHOT

This way the build version is not changed even when there was an accidental renaming of the file.




回答3:


You could pass the filename as an argument to the shell script, i.e. modify the shell script like so:

#!/bin/bash
nohup java -jar /home/ubuntu/$1 > /home/ubuntu/log.txt 2>&1 &
echo $! > /home/ubuntu/pid.file

and then you would need to determine the correct filename to use, based on the build version, and pass that as an argument to the script in the Deliver stage.




回答4:


You can just rename the file when you do an scp

scp filename username@remote.host.net.:filenewname

In your case something like this

sh 'scp -v -o StrictHostKeyChecking=no  -i /var/lib/jenkins/secrets/mykey target/*.jar ubuntu@00.00.00.00:/home/ubuntu:aws-0.0.1-SNAPSHOT.jar'

The above code takes whatever build version has been created by jenkins and at the time of copying it and renames it to "aws-0.0.1-SNAPSHOT.jar", so you dont have to modify your start.sh

P.S generally when you deploy your final build(JAR) ensure that only the jar name is added as the description to the filename and not "-0.0.1-SNAPSHOT"

Hope it helps :)



来源:https://stackoverflow.com/questions/50186447/how-to-deploy-spring-boot-jar-file-to-ec2-using-jenkins

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!