概要
- シンプルな Spring Boot アプリケーションを systemd でプロセス管理する
- systemd によって起動・停止・OS再起動時の自動起動などが可能になる
- 今回の環境: Ubuntu 19.10 Eoan Ermine + Java 11 + Spting Boot 2.2.6
Spring Boot アプリケーションを用意
サンプルとしてシンプルな Spring Boot アプリケーションを用意する。
ファイル一覧
├── build.gradle
├── settings.gradle
└── src
└── main
└── java
└── com
└── example
└── MyApp.java
build.gradle
Gradle のビルド設定ファイル。
plugins {
id 'org.springframework.boot' version '2.2.6.RELEASE'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
id 'java'
}
group = 'com.example'
version = '0.0.1'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
}
settings.gradle
Gradle のビルド設定ファイル。
rootProject.name = 'myapp'
src/main/java/com/example/MyApp.java
サンプルとなる Spring Boot アプリケーションのソースコード。
HTTP レスポンスとして JSON を返す。
package com.example;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.Map;
@SpringBootApplication
@RestController
public class MyApp {
public static void main(String[] args) {
SpringApplication.run(MyApp.class, args);
}
@GetMapping("/")
public Map index() {
return Map.of("message", "Hello, world.");
}
}
Gradle でビルドして JAR ファイルを作成
$ gradle bootJar
$ ls build/libs/myapp-0.0.1.jar
build/libs/myapp-0.0.1.jar
起動用シェルスクリプトを用意
今回は起動時に柔軟に設定ができるように起動用のシェルスクリプトを用意する。
任意のファイル名 startup.sh で以下ような内容を保存しておく。
#!/bin/sh
# 同じディレクトリ内の JAR ファイル
java -jar `dirname $0`/myapp-0.0.1.jar --server.port=8888
Spring Boot ではシェルスクリプトが不要な JAR を使用することも可能なので、必要に応じてこちらを使うのも良い。
Spring Boot アプリケーションのデプロイ - ドキュメント
完全に実行可能な jar は、ファイルの先頭に追加のスクリプトを埋め込むことで機能します。
systemd の設定
Spring Boot の公式ドキュメントに具体的な設定方法が載っているので参考になる。
Spring Boot アプリケーションのデプロイ - ドキュメント
systemd は System V init システムの後継であり、現在多くの最新の Linux ディストリビューションで使用されています。init.d スクリプトを systemd で引き続き使用できますが、systemd の「サービス」スクリプトを使用して Spring Boot アプリケーションを起動することもできます。
設定ファイルを設置
サービスユニット用の設定ファイル myapp.service を作成。
[Unit]
Description=This is my application.
After=syslog.target
[Service]
User=foo
ExecStart=/home/foo/myapp/startup.sh
SuccessExitStatus=143
[Install]
WantedBy=multi-user.target
設定ファイルを /etc/systemd/system に置く。
今回はファイル自体は home ディレクトリ以下に置き、シンボリックリンクを張っている。
$ sudo ln -s /home/foo/myapp/myapp.service /etc/systemd/system/myapp.service
systemctl list-unit-files コマンドで設定できていることを確認。
$ systemctl list-unit-files --type=service | grep myapp
myapp.service linked
サービスを有効にする
systemctl enable コマンドでサービスを有効にする。
これで systemctl コマンドによる起動・停止や、OS再起動時の自動起動などが可能になる。
$ sudo systemctl enable myapp
Created symlink /etc/systemd/system/multi-user.target.wants/myapp.service → /home/foo/myapp/myapp.service.
起動確認
systemctl start コマンドでサービスを起動。
$ sudo systemctl start myapp
systemctl status コマンドでサービスの状態を確認する。ログも表示される。
$ sudo systemctl status myapp
● myapp.service - My Application
Loaded: loaded (/home/foo/myapp/myapp.service; enabled; vendor preset: enabled)
Active: active (running) since Fri 2020-04-24 05:19:49 JST; 2s ago
Main PID: 3822 (startup.sh)
Tasks: 20 (limit: 2320)
Memory: 150.3M
CGroup: /system.slice/myapp.service
├─3822 /bin/sh /home/foo/myapp/startup.sh
└─3825 java -jar /home/foo/myapp/myapp-0.0.1.jar --server.port=8888
4月 24 05:19:49 my-foo-host systemd[1]: Started My Application.
4月 24 05:19:50 my-foo-host startup.sh[3822]: . ____ _ __ _ _
4月 24 05:19:50 my-foo-host startup.sh[3822]: /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
4月 24 05:19:50 my-foo-host startup.sh[3822]: ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
4月 24 05:19:50 my-foo-host startup.sh[3822]: \\/ ___)| |_)| | | | | || (_| | ) ) ) )
4月 24 05:19:50 my-foo-host startup.sh[3822]: ' |____| .__|_| |_|_| |_\__, | / / / /
4月 24 05:19:50 my-foo-host startup.sh[3822]: =========|_|==============|___/=/_/_/_/
4月 24 05:19:50 my-foo-host startup.sh[3822]: :: Spring Boot :: (v2.2.6.RELEASE)
Spring Boot アプリケーションが動作していることを確認。
$ curl http://localhost:8888/
{"message":"Hello, world."}