如何在Ubuntu 14.04服務器上自動化部署Spring Boot的應用
這篇文章主要講解我在Ubuntu 14.04服務器上如何部署Spring Boot的網站應用的經驗。以下以我的博客項目 https://github.com/Raysmond.com/SpringBlog 為例子。主要的部署需求如下:
-
如何在服務器上運行Spring Boot的應用,并使用production環境的配置文件application-production.yml;
</li> -
如何通過Gradle構建和發布Spring Boot的項目;
</li> -
如何在本地自動化部署網站到production環境中。
</li> </ul>1. 在Ubuntu中安裝Java8
以下是一個簡單的安裝方法。
$ 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)</pre>
2. 本地使用Gradle發布Spring Boot應用
我這里使用Jetty9作為內置的服務器。
// ... 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.yml。
./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</pre>
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</pre>
然后SSH登錄服務器,修改配置文件application-production.yml,試運行應用。
ssh root@your_server_ip
cd spring-blog/current
java -jar SpringBlog-0.1.jar --spring.config.location=application-production.yml</pre>
# 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這個命令。
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文件,內容如下:
#!/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</pre>
5. 在本地自動化部署網站到遠程服務器
在本地我用了一個shell腳本和一個python腳本來配合自動化部署。
-
deploy.sh使用gradle的命令發布jar包,使用scp命令吧jar包上傳到服務器上;
</li> -
deploy.py使用SSH遠程登錄服務器,并在服務器上執行部署命令。
</li> </ul># 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</pre>
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 redis6379 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()</pre>
配置完以后,在本地寫完代碼就可以運行./deploy.sh一鍵部署到遠程服務器了。
以上就是我部署 http://raysmond.com 網站的一些經驗。項目源代碼已開源放在Github上: https://github.com/Raysmond/SpringBlog 。
-