安裝 Spring Boot 應用程式

除了直接使用 java -jar 執行 Spring Boot 應用程式之外,也可以將它們作為 systemdinit.d 或 Windows 服務來執行。

安裝為 systemd 服務

systemd 是 System V init 系統的後繼者,現在許多現代 Linux 發行版都在使用它。Spring Boot 應用程式可以透過 systemd 的「服務」腳本來啟動。

假設您有一個 Spring Boot 應用程式打包成一個 uber jar 檔,位於 /var/myapp 中,要將其安裝為 systemd 服務,請建立一個名為 myapp.service 的腳本,並將其放置在 /etc/systemd/system 目錄中。以下腳本提供了一個範例:

[Unit]
Description=myapp
After=syslog.target network.target

[Service]
User=myapp
Group=myapp

Environment="JAVA_HOME=/path/to/java/home"

ExecStart=${JAVA_HOME}/bin/java -jar /var/myapp/myapp.jar
ExecStop=/bin/kill -15 $MAINPID
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target
請記得根據您的應用程式更改 DescriptionUserGroupEnvironmentExecStart 欄位。
ExecStart 欄位並未宣告腳本動作指令,這表示預設會使用 run 指令。

執行應用程式的使用者、PID 檔案和控制台日誌檔案是由 systemd 自行管理的,因此必須使用「服務」腳本中的相應欄位進行配置。有關更多詳細資訊,請參閱 服務單元設定說明頁面

要將應用程式標記為在系統啟動時自動啟動,請使用以下指令:

$ systemctl enable myapp.service

執行 man systemctl 以取得更多詳細資訊。

安裝為 init.d 服務 (System V)

要將您的應用程式用作 init.d 服務,請將其建置設定為產生完全可執行的 jar 檔

完全可執行的 jar 檔的工作原理是在檔案的開頭嵌入一個額外的腳本。目前,某些工具不接受這種格式,因此您可能無法始終使用這種技術。例如,jar -xf 可能會靜默地無法解壓縮已製成完全可執行的 jar 或 war 檔。建議您僅在打算直接執行 jar 或 war 檔時,才將其製成完全可執行的,而不是使用 java -jar 執行它或將其部署到 Servlet 容器。
zip64 格式的 jar 檔案無法製成完全可執行的狀態。嘗試這樣做將導致 jar 檔案在直接執行或使用 java -jar 執行時被報告為損毀。包含一個或多個 zip64 格式巢狀 jar 的標準格式 jar 檔案可以是完全可執行的。

要使用 Maven 建立「完全可執行」的 jar,請使用以下外掛程式設定

<plugin>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-maven-plugin</artifactId>
	<configuration>
		<executable>true</executable>
	</configuration>
</plugin>

以下範例顯示等效的 Gradle 設定

tasks.named('bootJar') {
	launchScript()
}

然後可以將其符號連結到 init.d 以支援標準的 startstoprestartstatus 指令。

新增至完全可執行 jar 的預設啟動腳本支援大多數 Linux 發行版,並已在 CentOS 和 Ubuntu 上進行測試。其他平台,例如 OS X 和 FreeBSD,則需要使用自訂腳本。預設腳本支援以下功能

  • 以擁有 jar 檔案的使用者身分啟動服務

  • 使用 /var/run/<應用程式名稱>/<應用程式名稱>.pid 追蹤應用程式的 PID

  • 將控制台日誌寫入 /var/log/<應用程式名稱>.log

假設您已將 Spring Boot 應用程式安裝在 /var/myapp 中,要將 Spring Boot 應用程式安裝為 init.d 服務,請建立符號連結,如下所示

$ sudo ln -s /var/myapp/myapp.jar /etc/init.d/myapp

安裝完成後,您可以照常啟動和停止服務。例如,在基於 Debian 的系統上,您可以使用以下指令啟動它

$ service myapp start
如果您的應用程式無法啟動,請檢查寫入到 /var/log/<應用程式名稱>.log 的日誌檔以找出錯誤。

您也可以使用標準作業系統工具標記應用程式以自動啟動。例如,在 Debian 上,您可以使用以下指令

$ update-rc.d myapp defaults <priority>

保護 init.d 服務的安全

以下是一組關於如何保護以 init.d 服務執行的 Spring Boot 應用程式的指導方針。它並非旨在成為強化應用程式及其執行環境所需執行之所有操作的詳盡清單。

以 root 身分執行時,例如使用 root 啟動 init.d 服務的情況,預設的可執行腳本會以 RUN_AS_USER 環境變數中指定的使用者身分執行應用程式。如果未設定環境變數,則會使用擁有 jar 檔案的使用者。您永遠不應該以 root 身分執行 Spring Boot 應用程式,因此 RUN_AS_USER 永遠不應該是 root,且您的應用程式的 jar 檔案永遠不應該由 root 擁有。而是建立一個特定使用者來執行您的應用程式,並設定 RUN_AS_USER 環境變數或使用 chown 將其設為 jar 檔案的擁有者,如下例所示

$ chown bootapp:bootapp your-app.jar

在這種情況下,預設的可執行腳本會以 bootapp 使用者身分執行應用程式。

為了降低應用程式使用者帳戶遭到入侵的可能性,您應該考慮阻止其使用登入 shell。例如,您可以將帳戶的 shell 設定為 /usr/sbin/nologin

您還應該採取措施防止修改應用程式的 jar 檔案。首先,設定其權限,使其無法被寫入,並且只能由其擁有者讀取或執行,如下例所示

$ chmod 500 your-app.jar

其次,如果您應用程式或執行它的帳戶遭到入侵,您也應該採取措施限制損害。如果攻擊者確實取得了存取權,他們可以將 jar 檔案設為可寫入並更改其內容。一種防止這種情況的方法是使用 chattr 將其設為不可變,如下例所示

$ sudo chattr +i your-app.jar

這將防止任何使用者(包括 root)修改 jar 檔案。

如果使用 root 來控制應用程式的服務,並且您使用 .conf 檔案來自訂其啟動,則 .conf 檔案會由 root 使用者讀取和評估。應該相應地保護它。使用 chmod 使檔案只能由擁有者讀取,並使用 chown 將 root 設為擁有者,如下例所示

$ chmod 400 your-app.conf
$ sudo chown root:root your-app.conf

自訂啟動腳本

Maven 或 Gradle 插件所寫入的預設內嵌啟動腳本可以透過多種方式自訂。對於大多數人來說,使用預設腳本並進行一些自訂通常就足夠了。如果您發現無法自訂所需的功能,請使用 embeddedLaunchScript 選項自行編寫整個檔案。

撰寫啟動腳本時的自訂

在將啟動腳本寫入 jar 檔案時,自訂其元素通常很有意義。例如,init.d 腳本可以提供「描述」。由於您事先知道描述(而且它不需要更改),您可以在產生 jar 時提供它。

要自訂寫入的元素,請使用 Spring Boot Maven 插件的 embeddedLaunchScriptProperties 選項,或 Spring Boot Gradle 插件 launchScriptproperties 屬性

預設腳本支援以下屬性替換

名稱 說明 Gradle 預設值 Maven 預設值

mode

腳本模式。

auto

auto

initInfoProvides

「INIT INFO」的 Provides 部分

${task.baseName}

${project.artifactId}

initInfoRequiredStart

「INIT INFO」的 Required-Start 部分。

$remote_fs $syslog $network

$remote_fs $syslog $network

initInfoRequiredStop

「INIT INFO」的 Required-Stop 部分。

$remote_fs $syslog $network

$remote_fs $syslog $network

initInfoDefaultStart

「INIT INFO」的 Default-Start 部分。

2 3 4 5

2 3 4 5

initInfoDefaultStop

「INIT INFO」的 Default-Stop 部分。

0 1 6

0 1 6

initInfoShortDescription

「INIT INFO」的 Short-Description 部分。

${project.description} 的單行版本(若無則使用 ${task.baseName}

${project.name}

initInfoDescription

「INIT INFO」的 Description 部分。

${project.description}(若無則使用 ${task.baseName}

${project.description}(若無則使用 ${project.name}

initInfoChkconfig

「INIT INFO」的 chkconfig 部分

2345 99 01

2345 99 01

confFolder

CONF_FOLDER 的預設值

包含 jar 的資料夾

包含 jar 的資料夾

inlinedConfScript

參考應內嵌在預設啟動腳本中的檔案腳本。這可以用於在載入任何外部設定檔之前設定環境變數,例如 JAVA_OPTS

logFolder

LOG_FOLDER 的預設值。僅適用於 init.d 服務

logFilename

LOG_FILENAME 的預設值。僅適用於 init.d 服務

pidFolder

PID_FOLDER 的預設值。僅適用於 init.d 服務

pidFilename

PID_FOLDER 中 PID 檔案名稱的預設值。僅適用於 init.d 服務

useStartStopDaemon

是否應使用 start-stop-daemon 命令(如果可用)來控制程序

true

true

stopWaitTime

STOP_WAIT_TIME 的預設值(以秒為單位)。僅適用於 init.d 服務

60

60

執行腳本時的自訂

對於需要在 jar 寫入 *之後* 自訂的腳本項目,您可以使用環境變數或設定檔

預設腳本支援以下環境屬性

變數 說明

MODE

操作「模式」。預設值取決於 jar 的建置方式,但通常是 auto(表示它會嘗試透過檢查它是否是名為 init.d 的目錄中的符號連結來猜測它是否是 init 腳本)。您可以將其明確設定為 service,以便 stop|start|status|restart 命令可以運作,或者設定為 run,如果您希望在前景中執行腳本。

RUN_AS_USER

用於執行應用程式的使用者。如果未設定,則會使用 jar 檔案的擁有者。

USE_START_STOP_DAEMON

是否使用 start-stop-daemon 命令(如果可用)來控制程序。預設值為 true

PID_FOLDER

pid 資料夾的根名稱(預設為 /var/run)。

LOG_FOLDER

放置日誌檔的資料夾名稱(預設為 /var/log)。

CONF_FOLDER

讀取 .conf 檔案的資料夾名稱(預設與 jar 檔案位於同一個資料夾)。

LOG_FILENAME

LOG_FOLDER 中日誌檔的名稱(預設為 <appname>.log)。

APP_NAME

應用程式名稱。如果 jar 檔案是從符號連結執行,腳本會猜測應用程式名稱。如果它不是符號連結,或者您想明確設定應用程式名稱,這會很有用。

RUN_ARGS

要傳遞給程式(Spring Boot 應用程式)的參數。

JAVA_HOME

預設情況下,會使用 PATH 尋找 java 可執行檔的位置,但如果 $JAVA_HOME/bin/java 存在可執行檔,您可以明確設定它。

JAVA_OPTS

啟動 JVM 時傳遞給它的選項。

JARFILE

jar 檔案的明確位置,以防腳本用於啟動未實際嵌入的 jar 檔案。

DEBUG

如果不為空,則會在 shell 程序上設定 -x 旗標,讓您可以查看腳本中的邏輯。

STOP_WAIT_TIME

停止應用程式時,在強制關閉之前的等待時間(以秒為單位)(預設為 60)。

PID_FOLDERLOG_FOLDERLOG_FILENAME 變數僅適用於 init.d 服務。對於 systemd,等效的客製化是透過使用「service」腳本來完成的。詳情請參閱 service 單元設定手冊頁面
使用設定檔

除了 JARFILEAPP_NAME 之外,可以使用 .conf 檔案來設定上一節中列出的設定。該檔案預計與 jar 檔案位於同一個目錄,且名稱相同,但後綴為 .conf 而不是 .jar。例如,名為 /var/myapp/myapp.jar 的 jar 檔案會使用名為 /var/myapp/myapp.conf 的設定檔,如下例所示

myapp.conf
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
如果您不希望設定檔與 jar 檔案位於同一個目錄,您可以設定 CONF_FOLDER 環境變數來自訂設定檔的位置。

要了解如何適當保護此檔案,請參閱 保護 init.d 服務的準則

Microsoft Windows 服務

可以使用 winsw 將 Spring Boot 應用程式作為 Windows 服務啟動。

一個獨立維護的範例)逐步說明如何為您的 Spring Boot 應用程式建立 Windows 服務。