如何在Ubuntu 14.04服務器上自動化部署Spring Boot的應用

這篇文章主要講解我在Ubuntu 14.04服務器上如何部署Spring Boot的網站應用的經驗。如下以個人博客項目https://github.com/Raysmond.com/SpringBlog爲例子。主要的部署需求以下:java

  • 如何在服務器上運行Spring Boot的應用,並使用production環境的配置文件application-production.ymlpython

  • 如何經過Gradle構建和發佈Spring Boot的項目;mysql

  • 如何在本地自動化部署網站到production環境中。git

1. 在Ubuntu中安裝Java8

如下是一個簡單的安裝方法。github

$ sudo add-apt-repository ppa:webupd8team/java
$ sudo apt-get update
$ sudo apt-get install oracle-java8-installer

$ java -version
java version "1.8.0_60"
Java(TM) SE Runtime Environment (build 1.8.0_60-b27)
Java HotSpot(TM) 64-Bit Server VM (build 25.60-b23, mixed mode)

2. 本地使用Gradle發佈Spring Boot應用

我這裏使用Jetty9做爲內置的服務器。web

// ...
bootRun {
    systemProperties = System.properties
}

configurations {
    compile.exclude module: "spring-boot-starter-tomcat"
}

dependencies {
    // spring boot
    compile "org.springframework.boot:spring-boot-starter-web:1.3.0.M5"
    compile "org.springframework.boot:spring-boot-starter-jetty"
    // ...
}

//...

在本地運行默認使用src/main/resources/application.yml做爲配置文件,而在production環境中咱們系統它支持提供外部的配置文件application-production.ymlredis

./gradlew bootRun # 開發環境下默認使用項目裏的application.yml

# 在本地測試使用外部配置文件
./gradlew bootRun -Dspring.config.location=/path/to/application-production.yml 

# 發佈
./gradlew build 

# 運行
java -jar build/libs/SpringBlog-0.1.jar  # 默認使用jar包裏面的application.yml配置文件

# 使用外部配置文件
java -jar build/libs/SpringBlog-0.1.jar --spring.config.location=/path/to/application-production.yml

3. 在Ubuntu服務器上部署Spring Boot應用

# 上傳SpringBlog-0.1.jar到服務器
scp build/libs/SpringBlog-0.1.jar root@your_server_ip:/root/spring-blog/current

# 在服務器上配置生產環境的配置文件
scp application-production.yml root@your_server_ip:/root/spring-blog/current

而後SSH登陸服務器,修改配置文件application-production.yml,試運行應用。spring

ssh root@your_server_ip

cd spring-blog/current

java -jar SpringBlog-0.1.jar --spring.config.location=application-production.yml
# application-production.yml

server:
    address: raysmond.com # 使用域名或者IP,啓動以後就能夠這個域名或IP訪問網站了
    port: 80
    contextPath:
    
spring:
    profiles:
        active: production

    thymeleaf:
        cache: true

    jade4j:
        caching: true

    dataSource:
      driverClassName: com.mysql.jdbc.Driver
      url: jdbc:mysql://127.0.0.1/spring_blog
      username: root
      password:

    hibernate:
      dialect: org.hibernate.dialect.MySQLDialect
      hbm2ddl.auto: update
      show_sql: false

    redis:
      host: localhost
      port: 6379

4. 如何在Ubuntu中後臺運行Spring Boot應用?

推薦使用nohup這個命令。sql

cd /root/spring-blog/current
nohup java -jar SpringBlog-0.1.jar --spring.config.location=application-production.yml \
> ../logs/production.log 2> ../logs/production.err &

在Ubuntu還能夠/etc/init.d目錄下新建一個腳本,把SpringBlog做爲service來運行,這樣不用每次都打這麼繁瑣的命令了。新建一個/etc/init.d/spring_blog文件,內容以下:shell

#!/bin/sh
SERVICE_NAME=spring_blog
HOME=/root/spring-blog
PATH_TO_JAR=$HOME/current/SpringBlog-0.1.jar
PID_PATH_NAME=/tmp/spring_blog.pid
LOG=$HOME/logs/production.log
ERROR_LOG=$HOME/logs/production.err
CONFIG=$HOME/application-production.yml
case $1 in
    start)
        echo "Starting $SERVICE_NAME ..."
        if [ ! -f $PID_PATH_NAME ]; then
            cd $HOME/current
            nohup java -jar $PATH_TO_JAR --spring.config.location=application-production.yml > $LOG 2> $ERROR_LOG &
                        echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is already running ..."
        fi
    ;;
    stop)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stoping ..."
            kill $PID;
            echo "$SERVICE_NAME stopped ..."
            rm $PID_PATH_NAME
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
    restart)
        if [ -f $PID_PATH_NAME ]; then
            PID=$(cat $PID_PATH_NAME);
            echo "$SERVICE_NAME stopping ...";
            kill $PID;
            echo "$SERVICE_NAME stopped ...";
            rm $PID_PATH_NAME
            echo "$SERVICE_NAME starting ..."
            cd $HOME/current
            nohup java -jar $PATH_TO_JAR --spring.config.location=application-production.yml > $LOG 2> $ERROR_LOG &
                        echo $! > $PID_PATH_NAME
            echo "$SERVICE_NAME started ..."
        else
            echo "$SERVICE_NAME is not running ..."
        fi
    ;;
esac

如今就能夠使用service的方式來運行網站了。

sudo service spring_blog start

sudo service spring_blog stop

sudo service spring_blog restart

5. 在本地自動化部署網站到遠程服務器

在本地我用了一個shell腳本和一個python腳原本配合自動化部署。

  • deploy.sh 使用gradle的命令發佈jar包,使用scp命令吧jar包上傳到服務器上;

  • deploy.py 使用SSH遠程登陸服務器,並在服務器上執行部署命令。

# deploy.sh

#!/bin/bash

SERVER="your_server_ip"
JAR="build/libs/SpringBlog-0.1.jar"

echo "Building $JAR..."
./gradlew build

echo "Upload $JAR to server $SERVER..."
scp $JAR root@$SERVER:/root/spring-blog/

python deploy.py

deploy.py主要使用了一個paramiko庫,用於SSH遠程登陸服務器,並執行命令。這個腳本會把服務器上/root/spring-blog/current/SpringBlog-0.1.jar備份到/root/spring-blog/releases中,並把新發布的jar包放到/root/spring-blog/current中,而後重啓spring_blog服務。

#!/usr/bin/python

import paramiko
import threading
import time

ip = 'your_server_ip'
user = 'root'
password = ''
jar = 'SpringBlog-0.1.jar'
home='/root/spring-blog'
current=home+"/current"
releases=home+"/releases"

def execute_cmds(ip, user, passwd, cmd):
    try:
        ssh = paramiko.SSHClient()
        ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
        ssh.connect(ip,22,user,passwd,timeout=5)
        for m in cmd:
            print m
            stdin, stdout, stderr = ssh.exec_command(m)
#           stdin.write("Y")
            out = stdout.readlines()
            for o in out:
                print o,
        print '%s\tOK\n'%(ip)
        ssh.close()
    except :
        print '%s\tError\n'%(ip)


if __name__=='__main__':
    print 'Start deploying %s to server %s'%(jar, ip)

    now = time.strftime("%Y%m%d%H%M%S")
    cmd = [
        'echo Stop spring_blog service... && service spring_blog stop',
        'echo Flush all redis cache data... && redis-cli -r 1 flushall',
        'echo Stop redis server... && service redis_6379 stop',
        'echo Use new jar... ' + \
        ' && mv ' + current + '/' + jar + ' ' + releases + '/' + now + '_' + jar ,
        'mv ' + home + '/' + jar + ' ' + current + '/' + jar,
        'echo Stop redis... && service redis_6379 start',
        'echo Start spring_blog service... && service spring_blog start ' + \
        ' && echo All done.'
    ]
    a=threading.Thread(target=execute_cmds, args=(ip,user,password,cmd))
    a.start()

配置完之後,在本地寫完代碼就能夠運行./deploy.sh一鍵部署到遠程服務器了。

以上就是我部署 http://raysmond.com 網站的一些經驗。項目源代碼已開源放在Github上:https://github.com/Raysmond/SpringBlog

相關文章
相關標籤/搜索