はじめに
SpringBoot起動時に、Dockerコンテナを自動で立ててくれるspring-boot-docker-compose
を紹介します。
この記事でできること
SpringBootプロジェクトで、アプリ起動時にdocker-composeでPostgreSQLを起動し、初期化SQL(DDL/DML)も自動実行、CI/CDでも自動化できる構成にする。
1.spring-boot-docker-compose
の依存関係を追加
pom.xml
またはbuild.gradle
に依存関係を追加します。
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-docker-compose</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
dependencies {
developmentOnly 'org.springframework.boot:spring-boot-docker-compose'
}
2.docker-compose.yml を用意
プロジェクトルートにdocker-compose.yml
を作成します。
version: '3.8'
services:
db:
image: postgres:15
container_name: postgres_local
restart: always
ports:
- "5432:5432"
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
- postgres_data:/var/lib/postgresql/data
- ./sql:/docker-entrypoint-initdb.d
volumes:
postgres_data:
ファイル名についてはcompose.yml
でもOKでした。
それ以外のファイル名に関しては、application.ymlに明記する必要があります。
spring:
docker:
compose:
file: ../my-compose.yml
パスは絶対パスかプロジェクトルートからの相対パスにします。
3.init.sql に DDL/DML を書く
DBのテーブル作成や初期データ投入を自動化するために、init.sql を用意します。
この辺りは通常のDockerと変わりません。
CREATE TABLE IF NOT EXISTS movies (
id SERIAL PRIMARY KEY,
title VARCHAR(255) NOT NULL
);
INSERT INTO movies (title) VALUES
('The Phantom Menace'),
('Attack of the Clones'),
('Revenge of the Sith'),
('A New Hope'),
('The Empire Strikes Back'),
('Return of the Jedi'),
('The Force Awakens'),
('The Last Jedi'),
('The Rise of Skywalker');
4.application.yml
spring:
application:
name: spring-docker
docker:
compose:
file: ./my-compose.yml
skip:
in-tests: false
本来であればDataSource周りの設定が必要ですが、卒属先をDockerコンテナ上のデータベースにするのであれば、設定は不要です。
spring-boot-docker-compose
がよしなにやってくれるみたいです。
おまけ. GitHub Actions
GitHub Actionsを用いたCIに関しても以下のようにシンプルに設定できます。
name: CI
on:
push:
pull_request:
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup JDK
uses: actions/setup-java@v3
with:
distribution: temurin
java-version: 21
- name: Run tests
run: ./gradlew test
Springを起動してみる
起動前はもちろん、dockerコンテナ、イメージともに存在していません。
% docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Springを起動させると
2025-04-22 21:24:39 [INFO] - db Pulling
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜 中略 〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
2025-04-22 21:24:50 [INFO] - 56134e0541ae Pull complete
2025-04-22 21:24:50 [INFO] - db Pulled
2025-04-22 21:24:50 [INFO] - Network spring-docker_default Creating
2025-04-22 21:24:50 [INFO] - Network spring-docker_default Created
2025-04-22 21:24:50 [INFO] - Volume "spring-docker_postgres_data" Creating
2025-04-22 21:24:50 [INFO] - Volume "spring-docker_postgres_data" Created
2025-04-22 21:24:50 [INFO] - Container postgres_local Creating
2025-04-22 21:24:50 [INFO] - Container postgres_local Created
2025-04-22 21:24:50 [INFO] - Container postgres_local Starting
2025-04-22 21:24:50 [INFO] - Container postgres_local Started
2025-04-22 21:24:50 [INFO] - Container postgres_local Waiting
2025-04-22 21:24:51 [INFO] - Container postgres_local Healthy
2025-04-22 21:24:51 [INFO] - Bootstrapping Spring Data JDBC repositories in DEFAULT mode.
2025-04-22 21:24:51 [INFO] - Finished Spring Data repository scanning in 5 ms. Found 0 JDBC repository interfaces.
という具合に、通常の起動時の処理に加えて、コンテナの立ち上げ等を行ってくれます。
コンテナの様子も確認します。
% docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
76401f1dce10 postgres:15 "docker-entrypoint.s…" 5 minutes ago Up 5 minutes 0.0.0.0:5432->5432/tcp postgres_local
成功しているみたいです!
ついでにGitHubActionsも
DBとの接続が必要なテストケースをいくつか作成し、GitHubActionsで./gradlew test
を走らせてみました。
Starting a Gradle Daemon (subsequent builds will be faster)
> Task :compileJava
> Task :processResources
> Task :classes
> Task :compileTestJava
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test
BUILD SUCCESSFUL in 1m 11s
4 actionable tasks: 4 executed
こちらもうまくいっていそうです!
最後に
今回は、application.ymlに最小限の記載しかしませんでした。
実際には本番のDBをコンテナ上には置かないと思うので、プロファイルでの書き換え等必要かなと思います!