はじめに
この記事では、Docker Compose を利用した Spring Boot / PostgreSQL の開発環境構築手順について記載します。
開発環境
開発環境は以下の通りです。
- Windows 11
- Docker Engine 29.4.0
- Docker Compose 5.1.4
- PostgreSQL 18.4
- Java (JDK) 25
- Spring Boot 4.1.0
- Spring Framework 7.0.7
- Maven 3
Spring Boot プロジェクトの作成
まずは Spring Boot プロジェクトを用意します。
Spring Initializr でプロジェクト生成
Spring Initializr を使用してプロジェクトを生成します。
設定は以下の通りです。
- Project: Maven
- Language: Java
- Spring Boot: 4.1.0
- Java: 25
- Dependencies:
- Spring Web
- Spring Data JPA
- PostgreSQL Driver
生成されたZIPを解凍すると、以下のような構成になります。
spring-postgres-crud/
├── src/
│ └── main/
│ ├── java/com/example/spring-postgres-crud/
│ │ └── SpringPostgresCrudApplication.java
│ └── resources/
│ └── application.properties
├── mvnw
├── mvnw.cmd
└── pom.xml
pom.xml の確認
生成された pom.xml は以下の通りです。
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>4.1.0</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>spring-postgres-crud</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name/>
<description/>
<url/>
<licenses>
<license/>
</licenses>
<developers>
<developer/>
</developers>
<scm>
<connection/>
<developerConnection/>
<tag/>
<url/>
</scm>
<properties>
<java.version>25</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webmvc-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
ソースコードの実装
エンティティの作成
users テーブルに対応するエンティティクラスを作成します。
package com.example.spring_postgres_crud;
import jakarta.persistence.*;
@Entity
@Table(name = "users")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false, length = 32)
private String name;
@Column(nullable = false, unique = true, length = 32)
private String email;
// Constructors
public User() {}
public User(String name, String email) {
this.name = name;
this.email = email;
}
// Getters and Setters
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
}
リポジトリの作成
Spring Data JPA の JpaRepository を継承したリポジトリインターフェースを作成します。
package com.example.spring_postgres_crud;
import org.springframework.data.jpa.repository.JpaRepository;
public interface UserRepository extends JpaRepository<User, Long> {
}
コントローラーの作成
ユーザー一覧を返すエンドポイントを実装します。
package com.example.spring_postgres_crud;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/users")
public class UserController {
private final UserRepository userRepository;
public UserController(UserRepository userRepository) {
this.userRepository = userRepository;
}
@GetMapping
public List<User> getAllUsers() {
return userRepository.findAll();
}
}
Docker 設定
アプリケーションコンテナとデータベースコンテナを定義します。
Dockerfile の作成
Spring Boot アプリのイメージをビルドするための Dockerfile を作成します。
マルチステージビルドを使って最終イメージを軽量に保ちます。
# ---- Build Stage ----
FROM eclipse-temurin:25-jdk-alpine AS builder
WORKDIR /app
COPY mvnw mvnw
COPY .mvn .mvn
COPY pom.xml ./
COPY src src
RUN chmod +x mvnw && ./mvnw package -DskipTests --no-transfer-progress
# ---- Run Stage ----
FROM eclipse-temurin:25-jre-alpine
WORKDIR /app
COPY --from=builder /app/target/*.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java", "-jar", "app.jar"]
eclipse-temurin は Eclipse Foundation が提供する OpenJDK の公式ディストリビューションです。
alpine ベースを使用することで最終イメージを軽量化しています。
-DskipTests オプションを指定することで、イメージビルド時のテスト実行をスキップしています。
DB 初期データの作成
DBコンテナ起動時に実行する初期 SQL ファイルを用意します。
CREATE TABLE IF NOT EXISTS users (
id SERIAL PRIMARY KEY,
name VARCHAR(32) NOT NULL,
email VARCHAR(32) NOT NULL
);
INSERT INTO users (name, email) VALUES ('Wyatt', 'wyatt@example.com');
INSERT INTO users (name, email) VALUES ('Billy', 'billy@example.com');
compose.yaml の作成
以下の要件を満たす compose.yaml を作成します。
- Spring Boot
- コンテナ名:
app-container - ビルド:Dockerfile
- ポート:8080
- ソースコード:ホストマシンで実装
- コンテナ名:
- PostgreSQL
- コンテナ名:
db-container - イメージ:PostgreSQL 公式イメージ
18.4-alpine - ポート:5432
- 初期データを用意
- データはコンテナを削除しても残す
- ホストマシンからDB接続可能
- コンテナ名:
- コンテナ間通信可能
- AppコンテナはDBコンテナの起動完了を待ってから起動する
サービス・コンテナ名
各コンテナのサービスとコンテナ名を定義します。
services:
app:
container_name: "app-container"
db:
container_name: "db-container"
ボリューム
PostgreSQL のデータをコンテナ削除後も保持するため、DBコンテナ用のボリュームを定義します。
services と同じ階層に定義します。
services:
...
volumes:
db-volume:
ビルド・イメージ
AppコンテナはDockerfileから、DBコンテナは公式イメージからビルドするように定義します。
services:
app:
...
build: . # Dockerfile path
db:
...
image: postgres:18.4-alpine
...
ポート
公開するポートを定義します。
services:
app:
...
ports:
- "8080:8080"
db:
...
ports:
- "5432:5432"
...
バインドマウント
DBコンテナの初期データ作成ファイルをバインドマウントします。
services:
...
db:
...
volumes:
- type: bind
source: ./db
target: /docker-entrypoint-initdb.d
...
初期データ作成ファイルのマウント先 /docker-entrypoint-initdb.d は、Docker Hub の PostgreSQL リポジトリの Initializing a fresh instance セクションに記載があります。1
ボリュームマウント
データをコンテナ削除後も保持できるようにDBボリュームをDBコンテナにマウントします。
services:
...
db:
...
volumes:
...
- type: volume
source: db-volume
target: /var/lib/postgresql
volumes:
db-volume:
マウント先の /var/lib/postgresql/data は、PostgreSQL サーバーがデータを保存するデフォルトのディレクトリです。
環境変数
DB接続情報を環境変数として定義します。
AppコンテナとDBコンテナの両方に設定することで、コンテナ間通信とホストマシンからの接続を可能にします。
services:
app:
...
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/sampledb
SPRING_DATASOURCE_USERNAME: user
SPRING_DATASOURCE_PASSWORD: userpassword
SPRING_JPA_HIBERNATE_DDL_AUTO: none
db:
...
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: userpassword
POSTGRES_DB: sampledb
SPRING_DATASOURCE_URL のホスト部分に db を指定することで、Docker Compose のサービス名を使ったコンテナ間通信が可能になります。
ヘルスチェックと起動順序の制御
DBコンテナの起動完了を待ってからAppコンテナを起動するよう、healthcheck と depends_on を設定します。
services:
app:
...
depends_on:
db:
condition: service_healthy
db:
...
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d sampledb"]
interval: 10s
timeout: 5s
retries: 5
...
depends_on に condition: service_healthy を指定することで、DBコンテナの healthcheck が通過するまでAppコンテナの起動を待機します。
単純な depends_on: db ではコンテナの起動順序しか制御できず、PostgreSQLの初期化完了を保証できないため注意が必要です。
完成
完成した compose.yaml は以下の通りです。
services:
app:
container_name: "app-container"
build: . # Dockerfile path
ports:
- "8080:8080"
environment:
SPRING_DATASOURCE_URL: jdbc:postgresql://db:5432/sampledb
SPRING_DATASOURCE_USERNAME: user
SPRING_DATASOURCE_PASSWORD: userpassword
SPRING_JPA_HIBERNATE_DDL_AUTO: none
depends_on:
db:
condition: service_healthy
db:
container_name: "db-container"
image: postgres:18.4-alpine
ports:
- "5432:5432"
volumes:
- type: bind
source: ./db
target: /docker-entrypoint-initdb.d
- type: volume
source: db-volume
target: /var/lib/postgresql
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: userpassword
POSTGRES_DB: sampledb
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d sampledb"]
interval: 10s
timeout: 5s
retries: 5
volumes:
db-volume:
application.properties の設定
src/main/resources/application.properties にDB接続情報を設定します。
コンテナ起動時は Docker Compose の環境変数が優先されますが、ローカル実行時のデフォルト値として記載しておきます。
spring.datasource.url=jdbc:postgresql://localhost:5432/sampledb
spring.datasource.username=user
spring.datasource.password=userpassword
spring.jpa.hibernate.ddl-auto=none
spring.jpa.hibernate.ddl-auto=none を指定することで、Hibernate によるテーブルの自動生成・更新を無効化し、db/init-users.sql で作成したテーブル定義を維持します。
ディレクトリ構成
ここまでの作業で、プロジェクトのディレクトリ構成は以下の通りになります。
spring-postgres-crud/
├── db/
│ └── init-users.sql
├── src/
│ └── main/
│ ├── java/com/example/spring_postgres_crud/
│ │ ├── SpringPostgresCrudApplication.java
│ │ ├── User.java
│ │ ├── UserRepository.java
│ │ └── UserController.java
│ └── resources/
│ └── application.properties
├── compose.yaml
├── Dockerfile
├── mvnw
├── mvnw.cmd
└── pom.xml
動作確認
コンテナを起動します。
docker compose up --build
DBコンテナのヘルスチェック通過後にAppコンテナが起動し、以下のようなログが出力されます。
db-container | 2026-06-20 05:38:14.933 UTC [1] LOG: database system is ready to accept connections
Container db-container Healthy
app-container |
app-container | . ____ _ __ _ _
app-container | /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
app-container | ( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
app-container | \\/ ___)| |_)| | | | | || (_| | ) ) ) )
app-container | ' |____| .__|_| |_|_| |_\__, | / / / /
app-container | =========|_|==============|___/=/_/_/_/
app-container |
app-container | :: Spring Boot :: (v4.1.0)
app-container |
app-container | 2026-06-20T05:38:25.386Z INFO 1 --- [spring-postgres-crud] [ main] c.e.s.SpringPostgresCrudApplication : Starting SpringPostgresCrudApplication v0.0.1-SNAPSHOT using Java 25.0.3 with PID 1 (/app/app.jar started by root in /app)
コンテナ一覧を確認します。
docker container ls
compose.yaml で定義した名前通りのコンテナが作成されています。
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
83e9ac60ec4f spring-postgres-crud-app "java -jar app.jar" 2 minutes ago Up 2 minutes 0.0.0.0:8080->8080/tcp, [::]:8080->8080/tcp app-container
be9bfb2103dc postgres:18.4-alpine "docker-entrypoint.s…" 2 minutes ago Up 2 minutes (healthy) 0.0.0.0:5432->5432/tcp, [::]:5432->5432/tcp db-container
API エンドポイントにアクセスして、初期データが返ることを確認します。
curl http://localhost:8080/users
初期データとして挿入したユーザーが返ります。
[
{"name":"Wyatt","email":"wyatt@example.com","id":1},
{"name":"Billy","email":"billy@example.com","id":2}
]
PostgreSQL に直接接続して確認することもできます。
docker exec -it db-container psql -U user -d sampledb
sampledb=# select * from users;
id | name | email
----+-------+-------------------
1 | Wyatt | wyatt@example.com
2 | Billy | billy@example.com
(2 rows)
参考
- Spring Boot Reference Documentation
- Spring Initializr
- Dockerfile reference
- Docker Compose file reference
- PostgreSQL Docker Hub
- eclipse-temurin Docker Hub