1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Spring BootアプリのDockerイメージを軽量化・高速化する手順(Maven)

1
Posted at

普段はバックエンドエンジニアとしてJavaを中心に開発をしています。
今回は勉強ついでに個人で利用する家計簿アプリを作成しており、その際にMavenプロジェクトのDockerイメージを作成する手順を整理しました。

プロジェクト構成

Spring Bootの一般的なプロジェクト構成をベースにしています。プロジェクトのルートディレクトリに、Dockerfiledocker-compose.ymlを配置するシンプルな構成です。

プロジェクトルート/
├─ src/
├─ .mvn/
├─ mvnw
├─ pom.xml
├─ Dockerfile
└─ docker-compose.yml

マルチステージビルド

1つのDockerfileの中で複数のFROM命令を使用して、コンテナの役割を分割する。

  • ビルド環境(Builder)
    maven:3.9-eclipse-temurin-21を使用。
    ソースコードをコンパイルし、.jarファイルを作成する役割をします。

  • 実行環境(Runner)
    eclipse-temurin:21-jre-alpineを使用。
    Builder環境で作成された成果物だけをCOPY --rom=builderコマンドで受け取り、実際にアプリを動かす役割をします。

マルチステージビルドの強み

  • イメージサイズの削減
    最終的なイメージには、数百MBもあるMavenやJDK、ソースコードが含まれない。動かすためだけの軽量な「JRE(Java実行環境)」と最小減のOSのみになるため、イメージのダウンロード時間やストレージ容量を節約できる。

ビルドの高速化

毎回のビルド時間を短縮するために、Dockerのキャッシュマウント機能と、Maven Wrappeer(mvnw)を使用します。これによりローカル環境で事前にビルドしておく必要がなくなります。

# Maven Wrapperをコピー
COPY .mvn/ .mvn
COPY mvnw pom.xml ./

# キャッシュをマウントして依存関係をダウンロード
RUN --mount=type=cache,target=/root/.m2 \
    ./mvnw dependency:go-offline -B

--mount=type=cache,target=/root/.m2を指定することで、Docker内部に消えない保管庫が作成されます。これにより、2回目以降のビルドでは変更されたライブラリのみをダウンロードするようになり、高速になります。

セキュリティ対策

コンテナをデフォルトの管理者(root)権限で動かすにはセキュリティリスクが高いため、必要最低限の権限を持つ「システム専用の一般ユーザ」を作成してアプリを実行させる。

# Alpine Linux用のユーザー作成コマンド(ID: 1001)
RUN addgroup -g 1001 appgroup && \
    adduser -u 1001 -G appgroup -s /bin/sh -D appuser
  • 1001:一般ユーザに割り当てられるID。
  • -D:パスワードなし設定(システム自動実行用のため)。
  • -s /bin/sh:Alpine標準の軽量シェルを指定。

最終的なDockerfileの完成形

# ==========================================
# ステージ1: ビルド環境 (Builder)
# ==========================================
FROM maven:3.9-eclipse-temurin-21 AS builder
WORKDIR /app

# Maven Wrapperとpom.xmlをコピーし、依存関係をキャッシュ
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN --mount=type=cache,target=/root/.m2 \
    ./mvnw dependency:go-offline -B

# ソースコードをコピーしてビルド
COPY src ./src
RUN --mount=type=cache,target=/root/.m2 \
    ./mvnw clean package -DskipTests

# ==========================================
# ステージ2: 実行環境 (Runner)
# ==========================================
FROM eclipse-temurin:21-jre-alpine
WORKDIR /app

# セキュリティ対策: 非rootユーザーの作成
RUN addgroup -g 1001 appgroup && \
    adduser -u 1001 -G appgroup -s /bin/sh -D appuser

# ビルドしたJARファイルをコピーし、所有権をappuserに変更
COPY --from=builder --chown=appuser:appgroup /app/target/*.jar app.jar

# 作成したユーザーに切り替え
USER appuser

EXPOSE 8080

# コンテナ起動時に上書き可能な環境変数のデフォルト値
ENV SPRING_PROFILES_ACTIVE=prod \
    JAVA_OPTS="-XX:MaxRAMPercentage=75.0"

# アプリケーションの起動
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

Docker Composeの設定とコンテナ起動

作成したDockerfileを使ってコンテナを起動・管理しやすくするために、docker-compose.ymlを作成します。

services:
  backend-app:
    build:
      context: . # カレントディレクトリのDockerfile等を使ってビルドする
    image: my-spring-boot:1.0
    container_name: my-spring-boot
    ports:
      - "8080:8080"
    restart: unless-stopped

コンテナの起動と動作確認

設定ファイルがそろったら、ターミナルでプロジェクトルートに移動し、以下コマンドを実行する。

docker compose up -d --build
  • -d:バックグラウンドでコンテナを起動します。
  • --build:Dockerfileの変更を反映して、イメージをビルドします。

起動後、ブラウザでhttp://localhost:8080にアクセスします。アプリの画面が表示されたら、無事にDocker化が完了しました。

コンテナを停止・削除して作業を終了する時は、以下のコマンドを実行します。

docker compose down

以上です。何かしらの参考になれば幸いです。

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?