安裝 Spring Boot 應用程式
除了直接使用 java -jar
執行 Spring Boot 應用程式外,還可以將它們作為 systemd
、init.d
或 Windows 服務執行。
安裝為 systemd 服務
systemd
是 System V init 系統的繼承者,現在被許多現代 Linux 發行版使用。Spring Boot 應用程式可以使用 systemd
的“service”指令碼啟動。
假設您的 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
Type=exec
ExecStart=/path/to/java/home/bin/java -jar /var/myapp/myapp.jar
WorkingDirectory=/var/myapp
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
請記得更改適用於您的應用程式的 Description 、User 、Group 、ExecStart 和 WorkingDirectory 欄位。 |
ExecStart 欄位不宣告指令碼動作命令,這意味著預設使用 run 命令。 |
執行應用程式的使用者、PID 檔案和控制檯日誌檔案由 systemd
本身管理,因此必須使用“service”指令碼中的相應欄位進行配置。有關更多詳細資訊,請查閱 service unit configuration man page。
要將應用程式標記為在系統啟動時自動啟動,請使用以下命令:
$ 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 檔案無法設定為完全可執行。嘗試這樣做將導致一個在直接執行或使用 java -jar 時報告損壞的 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/<appname>/<appname>.pid
跟蹤應用程式的 PID -
將控制檯日誌寫入
/var/log/<appname>.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/<appname>.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 指令碼可以提供一個“description”。由於您 미리知道描述(且無需更改),因此在生成 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 時傳遞給 JVM 的選項。 |
|
jar 檔案的明確位置,以防指令碼用於啟動實際未嵌入的 jar。 |
|
如果不為空,則在 shell 程序上設定 |
|
停止應用程式前的等待時間(秒),超過該時間將強制關閉(預設為 |
PID_FOLDER 、LOG_FOLDER 和 LOG_FILENAME 變數僅對 init.d 服務有效。對於 systemd ,等效的定製透過“service”指令碼進行。有關更多詳細資訊,請查閱 service unit configuration man page。 |
使用 Conf 檔案
除了 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 服務的指南。