安裝 Spring Boot 應用程式
除了直接使用 java -jar
執行 Spring Boot 應用程式之外,也可以將它們作為 systemd
、init.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
請記得根據您的應用程式更改 Description 、User 、Group 、Environment 和 ExecStart 欄位。 |
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
以支援標準的 start
、stop
、restart
和 status
指令。
新增至完全可執行 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 插件 launchScript
的 properties
屬性。
預設腳本支援以下屬性替換
名稱 | 說明 | Gradle 預設值 | Maven 預設值 |
---|---|---|---|
|
腳本模式。 |
|
|
|
「INIT INFO」的 |
|
|
|
「INIT INFO」的 |
|
|
|
「INIT INFO」的 |
|
|
|
「INIT INFO」的 |
|
|
|
「INIT INFO」的 |
|
|
|
「INIT INFO」的 |
|
|
|
「INIT INFO」的 |
|
|
|
「INIT INFO」的 |
|
|
|
|
包含 jar 的資料夾 |
包含 jar 的資料夾 |
|
參考應內嵌在預設啟動腳本中的檔案腳本。這可以用於在載入任何外部設定檔之前設定環境變數,例如 |
||
|
|
||
|
|
||
|
|
||
|
|
||
|
是否應使用 |
|
|
|
|
60 |
60 |
執行腳本時的自訂
對於需要在 jar 寫入 *之後* 自訂的腳本項目,您可以使用環境變數或設定檔。
預設腳本支援以下環境屬性
變數 | 說明 |
---|---|
|
操作「模式」。預設值取決於 jar 的建置方式,但通常是 |
|
用於執行應用程式的使用者。如果未設定,則會使用 jar 檔案的擁有者。 |
|
是否使用 |
|
pid 資料夾的根名稱(預設為 |
|
放置日誌檔的資料夾名稱(預設為 |
|
讀取 .conf 檔案的資料夾名稱(預設與 jar 檔案位於同一個資料夾)。 |
|
|
|
應用程式名稱。如果 jar 檔案是從符號連結執行,腳本會猜測應用程式名稱。如果它不是符號連結,或者您想明確設定應用程式名稱,這會很有用。 |
|
要傳遞給程式(Spring Boot 應用程式)的參數。 |
|
預設情況下,會使用 |
|
啟動 JVM 時傳遞給它的選項。 |
|
jar 檔案的明確位置,以防腳本用於啟動未實際嵌入的 jar 檔案。 |
|
如果不為空,則會在 shell 程序上設定 |
|
停止應用程式時,在強制關閉之前的等待時間(以秒為單位)(預設為 |
PID_FOLDER 、LOG_FOLDER 和 LOG_FILENAME 變數僅適用於 init.d 服務。對於 systemd ,等效的客製化是透過使用「service」腳本來完成的。詳情請參閱 service 單元設定手冊頁面。 |
使用設定檔
除了 JARFILE
和 APP_NAME
之外,可以使用 .conf
檔案來設定上一節中列出的設定。該檔案預計與 jar 檔案位於同一個目錄,且名稱相同,但後綴為 .conf
而不是 .jar
。例如,名為 /var/myapp/myapp.jar
的 jar 檔案會使用名為 /var/myapp/myapp.conf
的設定檔,如下例所示
JAVA_OPTS=-Xmx1024M
LOG_FOLDER=/custom/log/folder
如果您不希望設定檔與 jar 檔案位於同一個目錄,您可以設定 CONF_FOLDER 環境變數來自訂設定檔的位置。 |
要了解如何適當保護此檔案,請參閱 保護 init.d 服務的準則。