非rootユーザでSpring Bootアプリをサービスとして起動させる
非rootユーザでSpring Bootアプリをサービスとして起動させるためにやったことを書きました。
Spring Bootとは
- Springフレームワークをより手軽に使うことができるフレームワーク
- Embedded Tomcatを持ったexecutable jarがビルドで生成され、javaコマンドに渡すことでアプリを起動できる
exucutable jarはとても魅力的な特徴で、Javaの開発とは思えないくらい簡単に、開発環境においてに開発、デバッグすることができます。
Javaの実行環境を用意さえすれば、簡単にアプリケーションを立ち上げることができます。
コンソール経由で実行する場合、特別な環境設定は不要です。(IDE経由で動かす場合は、Spring Boot系のプラグインの設定が必要)
exucatble jarを使ってアプリを起動するには以下のコマンドを使用します。
sh code snippet start
# javaコマンドから起動
$ java -jar application.jar
# Spring Boot Maven plugin経由で起動
$ cd /path/to/pom.xml
$ mvn clean spring-boot:runsh code snippet end
デフォルトの設定では、8080ポートでアプリケーションが起動されます。
fully executable jar
前述した、javaコマンドやmvnコマンドを使ったアプリケーションの起動はフォアグラウンドプロセスで起動するため、そのままStaging環境やProduction環境のアプリケーションサーバにデプロイし、サービスとして起動することができません。 しかし、Spring Bootではサービスとして起動できるビルド成果物も簡単に作成することができます。 サービスとして起動できるビルド成果物のことをfully executable jarと言います。 pom.xmlに以下の設定を記述すると、ビルド後にtargetディレクトリ配下にできるjarファイルがfully executable jarとなります。
xml code snippet start
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<mode>service</mode>
</configuration>
</plugin>xml code snippet end
開発環境ではexecutable jarを、Staging環境やProduction環境ではfully executable jarをビルドしたいときは、Mavenのプロファイル機能を使ってビル成果物を切り替えることができます。
xml code snippet start
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<properties>
<executable>false</etc.executable>
</properties>
</profile>
<profile>
<id>stg</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<executable>true</etc.executable>
</properties>
</profile>
<profile>
<id>prod</id>
<activation>
<activeByDefault>false</activeByDefault>
</activation>
<properties>
<executable>true</etc.executable>
</properties>
</profile>
</profiles>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>${executable}</executable>
<mode>service</mode>
</configuration>
</plugin>xml code snippet end
ビルドコマンド
sh code snippet start
# dev
mvn clean package
# staging
mvn clean package -P stg
# production
mvn clean package -P prodsh code snippet end
fully executable jarとしてビルドされたjarファイルは、一般的なサービススクリプトのようにプロセスを制御することができます。init.dやsystemdに登録することもできます。
sh code snippet start
$ cd /path/to/jar
$ ./application.jar [start | stop | status | restart]sh code snippet end
非rootユーザで起動させる
実運用では、Spring Bootアプリのサービスを非rootユーザで起動させるようなケースがあると思います。 しかし、default設定では、非rootユーザでfully executable jarをサービスとして起動させることができません。 理由は二つあります。
- pidファイルの出力先ディレクトリに書き込み権限がない (defaultでは/var/run)
- logの出力先ディレクトリに書き込み権限がない (defaultでは/var/log)
権限周りの設定変更がされていない限り、/var/runや/var/logには非rootユーザに書き込み権限はありません。 そこでpidファイルの出力先とlogファイルの出力先を変更する必要があります。
xml code snippet start
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
<mode>service</mode>
<embeddedLaunchScriptProperties>
<pidFolder>/path/to/pidFile</pidFolder>
<logFolder>/path/to/logFile</logFolder>
</embeddedLaunchScriptProperties>
</configuration>
</plugin>xml code snippet end
fully executable jarを起動させる非rootユーザに書き込み権限があるディレクトリを指定することで、サービスを起動できるようになります。
まとめ
Spring Bootをサービスとして起動させるには、Spring Boot Maven Pluginの設定変更をする。
- ビルド成果物がfully executable jarとなるように、
オプションをtrueにする - pidファイルとログの出力先を実行ユーザの書き込み権限のあるディレクトリに変更する(
, オプション)