【保存版】Docker×Java開発環境構築完全ガイド2024 – 現場で使える15のベストプラクティス

目次

  1. Dockerを使用したJava開発環境の基礎知識
    • DockerでJava開発環境を構築するメリット
    • 必要な前提知識と環境準備
  2. JavaアプリケーションのDockerfile作成方法
    • 基本的なDockerfileの構造と書き方
    • マルチステージビルドによる最適化テクニック
    • 実践的なDockerfileテンプレート集
  3. Docker Composeを活用した開発環境の構築
    • docker-compose.ymlの基本設定方法
    • データベースとの連携設定
    • 開発環境と本番環境の切り替え方法
  4. 実践的なパフォーマンスチューニング
    • JVMのメモリ設定最適化
    • コンテナリソースの適切な設定方法
    • ビルド時間を短縮するテクニック
  5. セキュリティ対策とベストプラクティス
    • 脆弱性スキャンの導入方法
    • セキュアなイメージ構築のポイント
    • 権限管理とセキュリティ設定
  6. CI/CDパイプラインへの統合
    • GitHub Actionsとの連携方法
    • 自動テストと品質チェックの実装
    • 本番環境へのデプロイメント戦略
  7. トラブルシューティングガイド
    • よくあるエラーと解決方法
    • デバッグとログ収集のテクニック
    • パフォーマンス問題の診断と改善

Dockerを使用したJava開発環境の基礎知識

DockerでJava開発環境を構築するメリット

Docker(コンテナ技術)を使用してJava開発環境を構築することで、以下のような大きなメリットが得られます:

メリット

1. 環境の一貫性確保

  • 開発環境の標準化
  • 全開発者が同じJavaバージョン、同じライブラリバージョンを使用
  • 「自分の環境では動くのに」問題の解消
  • 本番環境との一致
  • 開発環境と本番環境の差異を最小化
  • デプロイメントリスクの低減

2. 迅速な環境構築

  • 新規メンバーのオンボーディング時間短縮
  • docker-compose upだけで環境構築完了
  • 複雑な設定作業が不要
  • プロジェクト切り替えの容易さ
  • 異なるJavaバージョンのプロジェクトも共存可能
  • コンテナの起動/停止で即座に切り替え

3. リソース効率の向上

  • システムリソースの最適化
  • 必要なときだけコンテナを起動
  • 複数プロジェクトの効率的な管理
  • クリーンな環境維持
  • 不要になったらdocker rmで完全削除
  • ホストマシンを汚さない

必要な前提知識と環境準備

1. 必要な前提知識

分野必要な知識レベル具体的な内容
Java基本的な理解– JDKの基礎知識
– ビルドツール(Maven/Gradle)の使用経験
Docker基本概念の理解– コンテナの概念
– イメージとコンテナの違い
– 基本的なDockerコマンド
Linux基本的なコマンド– シェルの基本操作
– ファイル操作コマンド

2. 環境準備手順

  1. Dockerのインストール
# macOSの場合(Homebrew使用)
brew install --cask docker

# Ubuntuの場合
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

# Windowsの場合
# Docker Desktop for Windowsをインストール
  1. Docker Composeのインストール(Docker Desktopには同梱)
# Linux環境での個別インストール
sudo curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
sudo chmod +x /usr/local/bin/docker-compose
  1. 動作確認
# Dockerデーモンの起動確認
docker --version
docker-compose --version

# テストコンテナの実行
docker run hello-world

3. プロジェクト固有の準備

  1. プロジェクトフォルダ構成
project-root/
├── src/
│   └── main/
│       └── java/
├── Dockerfile
├── docker-compose.yml
├── .dockerignore
└── pom.xml(または build.gradle)
  1. .dockerignoreファイルの作成
target/
.git/
.gitignore
*.md
  1. 必要なポートの確認
  • アプリケーションサーバー用ポート(デフォルト: 8080)
  • デバッグポート(デフォルト: 5005)
  • データベース接続ポート(MySQL: 3306、PostgreSQL: 5432など)

開発環境の要件確認チェックリスト

  • [ ] JDKバージョンの決定
  • [ ] 使用するビルドツールの選択(Maven/Gradle)
  • [ ] 必要なミドルウェアの特定(DB、キャッシュなど)
  • [ ] 開発ツール連携の確認(IDE、デバッガー)
  • [ ] チーム内での運用ルール策定

以上が基礎知識セクションの内容となります。次のセクションに進むべきでしょうか?

JavaアプリケーションのDockerfile作成方法

基本的なDockerfileの構造と書き方

Dockerfileは、Javaアプリケーションのコンテナイメージを作成するための設計図です。以下で、基本的な構造と重要な命令について説明します。

1. 基本構造

# ベースイメージの指定
FROM eclipse-temurin:17-jdk

# 作業ディレクトリの設定
WORKDIR /app

# ビルドに必要なファイルのコピー
COPY pom.xml .
COPY src ./src

# Mavenビルドの実行
RUN mvn clean package

# JARファイルの実行
CMD ["java", "-jar", "target/application.jar"]

2. 重要なDockerfile命令の解説

命令用途使用例
FROMベースイメージの指定FROM eclipse-temurin:17-jdk
WORKDIR作業ディレクトリの設定WORKDIR /app
COPYファイルのコピーCOPY src ./src
ADDファイルの追加(圧縮ファイルは解凍)ADD archive.tar.gz /app
RUNビルド時のコマンド実行RUN mvn package
CMDコンテナ起動時のコマンドCMD ["java", "-jar", "app.jar"]
ENTRYPOINT固定の起動コマンドENTRYPOINT ["java"]
ENV環境変数の設定ENV JAVA_OPTS="-Xmx512m"

マルチステージビルドによる最適化テクニック

マルチステージビルドを使用することで、最終的なイメージサイズを大幅に削減できます。

1. マルチステージビルドの基本構造

# ビルドステージ
FROM maven:3.8.4-eclipse-temurin-17 AS builder
WORKDIR /build
COPY pom.xml .
COPY src ./src
RUN mvn clean package

# 実行ステージ
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

2. 最適化のポイント

  • 依存関係のキャッシュ
    • レイヤーの最適化
    • 変更頻度の低いレイヤーを先に配置
    • 適切なキャッシュ戦略の採用
    • 不要なファイルの除外
# 依存関係のキャッシュ層
FROM maven:3.8.4-eclipse-temurin-17 AS deps
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline

# ビルド層
FROM deps AS builder
COPY src ./src
RUN mvn clean package

# 実行層
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app
COPY --from=builder /build/target/*.jar app.jar
ENTRYPOINT ["java", "-jar", "app.jar"]

実践的なDockerfileテンプレート集

1. Spring Bootアプリケーション用テンプレート

# ベースイメージの選択
FROM maven:3.8.4-eclipse-temurin-17 AS builder

# キャッシュ最適化のためのpom.xmlコピー
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline

# ソースコードのコピーとビルド
COPY src ./src
RUN mvn clean package -DskipTests

# 実行環境の準備
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app

# ヘルスチェック用のツール追加
RUN apk add --no-cache curl

# アプリケーションのコピー
COPY --from=builder /build/target/*.jar app.jar

# 環境変数の設定
ENV JAVA_OPTS="-XX:+UseContainerSupport -XX:MaxRAMPercentage=75.0"

# ヘルスチェックの設定
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/actuator/health || exit 1

# 起動コマンド
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

2. マイクロサービス用軽量テンプレート

# ビルドステージ
FROM maven:3.8.4-eclipse-temurin-17 AS builder
WORKDIR /build

# 依存関係の管理
COPY pom.xml .
RUN mvn dependency:go-offline

# ソースコードのビルド
COPY src ./src
RUN mvn clean package -DskipTests

# 実行ステージ
FROM eclipse-temurin:17-jre-alpine
WORKDIR /app

# セキュリティ強化
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

# アプリケーションのコピー
COPY --from=builder /build/target/*.jar app.jar

# 環境変数とポートの設定
ENV JAVA_OPTS="-Xms256m -Xmx512m"
EXPOSE 8080

# 起動コマンド
ENTRYPOINT ["sh", "-c", "java $JAVA_OPTS -jar app.jar"]

3. 開発環境用デバッグ対応テンプレート

FROM eclipse-temurin:17-jdk
WORKDIR /app

# 開発ツールのインストール
RUN apt-get update && apt-get install -y \
    maven \
    git \
    && rm -rf /var/lib/apt/lists/*

# デバッグポートの公開
EXPOSE 8080 5005

# デバッグモードでの起動スクリプト
COPY docker-entrypoint.sh /usr/local/bin/
RUN chmod +x /usr/local/bin/docker-entrypoint.sh

ENTRYPOINT ["docker-entrypoint.sh"]
# docker-entrypoint.sh
#!/bin/sh
exec java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005 \
    -jar app.jar

以上のテンプレートは、実際のプロジェクトの要件に応じてカスタマイズしてご利用ください。特に環境変数、メモリ設定、ポート番号などは、プロジェクトの要件に合わせて適切に調整することをお勧めします。

Docker Composeを活用した開発環境の構築

docker-compose.ymlの基本設定方法

Docker Composeを使用することで、複数のコンテナを一元管理し、開発環境を簡単に構築・運用できます。

1. 基本的な構造

version: '3.8'
services:
  app:
    build: 
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    environment:
      - SPRING_PROFILES_ACTIVE=dev
    volumes:
      - ./:/app
      - ~/.m2:/root/.m2
    depends_on:
      - db

2. 主要な設定項目の解説

設定項目説明使用例
versionCompose fileのバージョンversion: '3.8'
servicesコンテナの定義services: app: ...
buildビルド設定build: context: .
portsポートマッピングports: - "8080:8080"
environment環境変数設定environment: - KEY=VALUE
volumesボリュームマウントvolumes: - ./:/app
depends_on依存関係の定義depends_on: - db

データベースとの連携設定

1. データベースサービスの設定

version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    environment:
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/myapp
      - SPRING_DATASOURCE_USERNAME=postgres
      - SPRING_DATASOURCE_PASSWORD=secret
    depends_on:
      - db

  db:
    image: postgres:14-alpine
    ports:
      - "5432:5432"
    environment:
      - POSTGRES_DB=myapp
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=secret
    volumes:
      - postgres_data:/var/lib/postgresql/data
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql

volumes:
  postgres_data:

2. データベース初期化スクリプト(init.sql)

-- テーブル作成
CREATE TABLE IF NOT EXISTS users (
    id SERIAL PRIMARY KEY,
    username VARCHAR(50) NOT NULL,
    email VARCHAR(100) NOT NULL UNIQUE,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

-- 初期データ投入
INSERT INTO users (username, email) VALUES
    ('test_user', 'test@example.com');

3. データベース管理ツールの追加

  adminer:
    image: adminer
    ports:
      - "8081:8080"
    depends_on:
      - db

開発環境と本番環境の切り替え方法

1. 環境別の設定ファイル構成

project/
├── docker-compose.yml          # 基本設定
├── docker-compose.dev.yml      # 開発環境用
├── docker-compose.prod.yml     # 本番環境用
└── docker-compose.test.yml     # テスト環境用

2. 開発環境設定(docker-compose.dev.yml)

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.dev
    volumes:
      - ./:/app
      - ~/.m2:/root/.m2
    environment:
      - SPRING_PROFILES_ACTIVE=dev
      - JAVA_OPTS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005
    ports:
      - "8080:8080"
      - "5005:5005"

  db:
    ports:
      - "5432:5432"
    volumes:
      - ./init-dev.sql:/docker-entrypoint-initdb.d/init.sql

3. 本番環境設定(docker-compose.prod.yml)

version: '3.8'
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile.prod
    environment:
      - SPRING_PROFILES_ACTIVE=prod
      - JAVA_OPTS=-XX:+UseG1GC -XX:MaxRAMPercentage=75
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
    restart: always

  db:
    volumes:
      - postgres_prod_data:/var/lib/postgresql/data
    deploy:
      resources:
        limits:
          memory: 1G
    restart: always

volumes:
  postgres_prod_data:

4. 環境切り替えコマンド

# 開発環境の起動
docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

# 本番環境の起動
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up -d

# テスト環境の起動
docker-compose -f docker-compose.yml -f docker-compose.test.yml up -d

5. 環境別の設定管理のベストプラクティス

  1. 環境変数の管理
# .env.dev
POSTGRES_DB=myapp_dev
POSTGRES_USER=dev_user
POSTGRES_PASSWORD=dev_password

# .env.prod
POSTGRES_DB=myapp_prod
POSTGRES_USER=prod_user
POSTGRES_PASSWORD=${PROD_DB_PASSWORD}
  1. プロファイル別の設定
# application-dev.yml
spring:
  datasource:
    url: jdbc:postgresql://db:5432/myapp_dev
    username: dev_user
    password: dev_password

# application-prod.yml
spring:
  datasource:
    url: jdbc:postgresql://db:5432/myapp_prod
    username: prod_user
    password: ${PROD_DB_PASSWORD}

これらの設定を使用することで、開発からプロダクションまでのスムーズな環境移行が可能になります。また、各環境に特化した最適な設定を維持しながら、統一的な管理が実現できます。

実践的なパフォーマンスチューニング

JVMのメモリ設定最適化

コンテナ環境でのJavaアプリケーションのパフォーマンスを最大化するには、適切なJVMメモリ設定が不可欠です。

1. コンテナ対応のJVMオプション

ENV JAVA_OPTS="\
    -XX:+UseContainerSupport \
    -XX:MaxRAMPercentage=75.0 \
    -XX:InitialRAMPercentage=50.0 \
    -XX:+UseG1GC \
    -XX:+HeapDumpOnOutOfMemoryError \
    -XX:HeapDumpPath=/dumps"
オプション説明推奨値
UseContainerSupportコンテナリソースの認識を有効化常に有効化
MaxRAMPercentage最大ヒープサイズの割合70-80%
InitialRAMPercentage初期ヒープサイズの割合40-60%
UseG1GCG1GCの使用標準設定

2. メモリ使用量のモニタリング設定

# docker-compose.yml
services:
  app:
    environment:
      - JAVA_TOOL_OPTIONS="-Dcom.sun.management.jmxremote 
        -Dcom.sun.management.jmxremote.port=9010 
        -Dcom.sun.management.jmxremote.authenticate=false 
        -Dcom.sun.management.jmxremote.ssl=false"
    ports:
      - "9010:9010"

コンテナリソースの適切な設定方法

1. リソース制限の設定

services:
  app:
    deploy:
      resources:
        limits:
          cpus: '2'
          memory: 2G
        reservations:
          cpus: '1'
          memory: 1G

2. スケーリング戦略

services:
  app:
    deploy:
      mode: replicated
      replicas: 3
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
        max_attempts: 3
        window: 120s

3. リソースモニタリングの設定

services:
  prometheus:
    image: prom/prometheus
    volumes:
      - ./prometheus.yml:/etc/prometheus/prometheus.yml
    ports:
      - "9090:9090"

  grafana:
    image: grafana/grafana
    ports:
      - "3000:3000"
    depends_on:
      - prometheus

ビルド時間を短縮するテクニック

1. マルチステージビルドの最適化

# ベースイメージのキャッシュ
FROM maven:3.8.4-eclipse-temurin-17 AS deps
WORKDIR /build
COPY pom.xml .
RUN mvn dependency:go-offline

# ビルドステージ
FROM deps AS builder
COPY src ./src
RUN mvn package -DskipTests \
    -Dmaven.javadoc.skip=true \
    -Dmaven.source.skip=true

# 実行環境
FROM eclipse-temurin:17-jre-alpine
COPY --from=builder /build/target/*.jar app.jar

2. Mavenビルドの最適化

<!-- pom.xml -->
<properties>
    <maven.test.skip>true</maven.test.skip>
    <maven.javadoc.skip>true</maven.javadoc.skip>
    <maven.source.skip>true</maven.source.skip>
</properties>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <fork>true</fork>
                <meminitial>128m</meminitial>
                <maxmem>512m</maxmem>
            </configuration>
        </plugin>
    </plugins>
</build>

3. ビルドキャッシュの最適化戦略

Dockerビルドキャッシュの設定

# docker-compose.yml
services:
  app:
    build:
      context: .
      dockerfile: Dockerfile
      cache_from:
        - myapp:latest
      args:
        BUILDKIT_INLINE_CACHE: 1

ビルドスクリプトの例

#!/bin/bash
# build-optimized.sh

# キャッシュの活用
docker pull myapp:latest || true

# BuildKitを使用したビルド
DOCKER_BUILDKIT=1 docker build \
  --cache-from myapp:latest \
  --build-arg BUILDKIT_INLINE_CACHE=1 \
  -t myapp:latest .

# キャッシュの保存
docker push myapp:latest

4. パフォーマンス最適化チェックリスト

  1. JVMメモリ設定
    • [ ] コンテナ認識の有効化確認
    • [ ] ヒープサイズの適切な設定
    • [ ] GCログの有効化と監視
  2. コンテナリソース
    • [ ] CPU制限の確認
    • [ ] メモリ制限の確認
    • [ ] スケーリング設定の最適化
  3. ビルド最適化
    • [ ] マルチステージビルドの利用
    • [ ] キャッシュ戦略の実装
    • [ ] 不要な処理のスキップ

これらの設定とテクニックを適切に組み合わせることで、開発環境から本番環境まで、効率的なコンテナ運用が可能になります。特に、リソース使用状況を定期的にモニタリングし、必要に応じて設定を調整することが重要です。

セキュリティ対策とベストプラクティス

脆弱性スキャンの導入方法

コンテナセキュリティを確保するための第一歩は、継続的な脆弱性スキャンの実施です。

1. Trivyを使用した脆弱性スキャン

# .github/workflows/security-scan.yml
name: Security Scan

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]
  schedule:
    - cron: '0 0 * * *'

jobs:
  scan:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2

      - name: Run Trivy vulnerability scanner
        uses: aquasecurity/trivy-action@master
        with:
          image-ref: 'myapp:latest'
          format: 'table'
          exit-code: '1'
          severity: 'CRITICAL,HIGH'

2. スキャン結果の管理

services:
  defectdojo:
    image: defectdojo/defectdojo
    ports:
      - "8080:8080"
    environment:
      - DD_DATABASE_URL=postgresql://defectdojo:secret@db:5432/defectdojo
    volumes:
      - defectdojo_media:/app/media

3. 自動スキャンスクリプト

#!/bin/bash
# scan-image.sh

IMAGE_NAME=$1
TAG=${2:-latest}

# イメージのスキャン
trivy image --severity HIGH,CRITICAL \
  --output trivy-results.json \
  --format json \
  ${IMAGE_NAME}:${TAG}

# 結果の解析と報告
if [ $? -eq 0 ]; then
  echo "No security issues found"
else
  echo "Security issues detected. Check trivy-results.json"
  exit 1
fi

セキュアなイメージ構築のポイント

1. セキュアベースイメージの選択

# セキュアなベースイメージを使用
FROM eclipse-temurin:17-jre-alpine

# 必要最小限のパッケージのみインストール
RUN apk add --no-cache \
    curl \
    tzdata \
    && rm -rf /var/cache/apk/*

# 非rootユーザーの作成と切り替え
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

# アプリケーションの配置
COPY --chown=appuser:appgroup target/*.jar app.jar

# 最小限の環境変数設定
ENV JAVA_OPTS="-Djava.security.egd=file:/dev/./urandom -Dfile.encoding=UTF-8"

# ヘルスチェックの追加
HEALTHCHECK --interval=30s --timeout=3s \
  CMD curl -f http://localhost:8080/actuator/health || exit 1

ENTRYPOINT ["java", "-jar", "app.jar"]

2. マルチステージビルドでのセキュリティ強化

# ビルドステージ
FROM maven:3.8.4-eclipse-temurin-17 AS builder
WORKDIR /build

# 依存関係のチェック
COPY pom.xml .
RUN mvn dependency-check:check

# ソースコードの静的解析
COPY src ./src
RUN mvn verify -Psecurity

# 実行環境
FROM eclipse-temurin:17-jre-alpine
USER appuser
COPY --from=builder --chown=appuser:appgroup /build/target/*.jar app.jar

3. セキュリティスキャン自動化の設定

# docker-compose.security.yml
services:
  clair:
    image: quay.io/coreos/clair
    ports:
      - "6060:6060"
    depends_on:
      - clairdb

  clairdb:
    image: postgres:14-alpine
    environment:
      - POSTGRES_PASSWORD=secret

権限管理とセキュリティ設定

1. アプリケーションの権限設定

# docker-compose.yml
services:
  app:
    security_opt:
      - no-new-privileges:true
    cap_drop:
      - ALL
    cap_add:
      - NET_BIND_SERVICE
    read_only: true
    tmpfs:
      - /tmp

2. シークレット管理

version: '3.8'
services:
  app:
    environment:
      - SPRING_PROFILES_ACTIVE=prod
    secrets:
      - db_password
      - api_key

secrets:
  db_password:
    file: ./secrets/db_password.txt
  api_key:
    file: ./secrets/api_key.txt

3. ネットワークセキュリティ設定

# docker-compose.yml
networks:
  frontend:
    driver: overlay
    internal: false
  backend:
    driver: overlay
    internal: true

services:
  app:
    networks:
      - frontend
      - backend

  db:
    networks:
      - backend

セキュリティベストプラクティスチェックリスト

  1. イメージセキュリティ
    • [ ] 最小限のベースイメージ使用
    • [ ] 定期的な脆弱性スキャン実施
    • [ ] マルチステージビルド採用
    • [ ] 不要なパッケージの除去
  2. 実行時セキュリティ
    • [ ] 非rootユーザーでの実行
    • [ ] 必要最小限の権限設定
    • [ ] read-onlyファイルシステム
    • [ ] セキュアな環境変数管理
  3. アクセス制御
    • [ ] ネットワークセグメンテーション
    • [ ] シークレット管理の適切な実装
    • [ ] コンテナ間通信の制限
    • [ ] ポート公開の最小化
  4. モニタリングと監査
    • [ ] セキュリティログの収集
    • [ ] 異常検知の実装
    • [ ] 定期的なセキュリティ監査
    • [ ] インシデント対応計画の策定

これらのセキュリティ対策を適切に実装することで、コンテナ化されたJavaアプリケーションの安全性を大幅に向上させることができます。定期的なセキュリティ評価と更新を行うことも重要です。

CI/CDパイプラインへの統合

GitHub Actionsとの連携方法

GitHub Actionsを使用してJava×Dockerの継続的インテグレーション/デリバリーを実装します。

1. 基本的なCI/CDワークフロー

# .github/workflows/ci-cd.yml
name: Java Docker CI/CD

on:
  push:
    branches: [ main ]
  pull_request:
    branches: [ main ]

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3

      - name: Set up JDK 17
        uses: actions/setup-java@v3
        with:
          java-version: '17'
          distribution: 'temurin'
          cache: 'maven'

      - name: Build and Test
        run: mvn clean verify

      - name: Build Docker image
        run: docker build -t myapp:${GITHUB_SHA} .

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v2
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Push Docker image
        run: |
          docker tag myapp:${GITHUB_SHA} ghcr.io/${{ github.repository }}/myapp:${GITHUB_SHA}
          docker push ghcr.io/${{ github.repository }}/myapp:${GITHUB_SHA}

2. 環境別のデプロイメントワークフロー

# .github/workflows/deployment.yml
name: Deploy to Environment

on:
  workflow_run:
    workflows: ["Java Docker CI/CD"]
    types:
      - completed
    branches:
      - main

jobs:
  deploy-staging:
    runs-on: ubuntu-latest
    environment: staging
    steps:
      - name: Deploy to Staging
        uses: azure/webapps-deploy@v2
        with:
          app-name: myapp-staging
          images: ghcr.io/${{ github.repository }}/myapp:${GITHUB_SHA}

  deploy-production:
    needs: deploy-staging
    runs-on: ubuntu-latest
    environment: production
    steps:
      - name: Deploy to Production
        uses: azure/webapps-deploy@v2
        with:
          app-name: myapp-production
          images: ghcr.io/${{ github.repository }}/myapp:${GITHUB_SHA}

自動テストと品質チェックの実装

1. テスト自動化の設定

# .github/workflows/tests.yml
name: Automated Tests

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - name: Unit Tests
        run: mvn test

      - name: Integration Tests
        run: |
          docker-compose -f docker-compose.test.yml up -d
          mvn verify -P integration-test

      - name: Code Coverage
        run: mvn jacoco:report

      - name: SonarQube Analysis
        run: |
          mvn sonar:sonar \
            -Dsonar.host.url=${{ secrets.SONAR_URL }} \
            -Dsonar.login=${{ secrets.SONAR_TOKEN }}

2. 品質ゲートの設定

jobs:
  quality-check:
    runs-on: ubuntu-latest
    steps:
      - name: Code Style Check
        run: mvn checkstyle:check

      - name: Dependency Check
        run: mvn dependency-check:check

      - name: SpotBugs Analysis
        run: mvn spotbugs:check

      - name: Quality Gate
        run: |
          if [ $(mvn sonar:sonar -Dsonar.qualitygate.wait=true) -eq 1 ]; then
            echo "Quality Gate failed!"
            exit 1
          fi

3. テスト結果の保存と可視化

      - name: Publish Test Results
        uses: actions/upload-artifact@v3
        with:
          name: test-results
          path: |
            target/surefire-reports
            target/failsafe-reports
            target/site/jacoco

本番環境へのデプロイメント戦略

1. ブルーグリーンデプロイメントの実装

# .github/workflows/blue-green-deployment.yml
name: Blue-Green Deployment

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Deploy Green Environment
        run: |
          # 新バージョンをGreenにデプロイ
          kubectl apply -f k8s/green-deployment.yml

          # ヘルスチェック
          ./scripts/health-check.sh green

          # トラフィックの切り替え
          kubectl apply -f k8s/switch-to-green.yml

          # 古いBlue環境の削除
          kubectl delete -f k8s/blue-deployment.yml

2. デプロイメントスクリプト例

#!/bin/bash
# scripts/deploy.sh

# 環境変数の設定
ENV=$1
VERSION=$2

# イメージの準備
docker pull ghcr.io/myapp:${VERSION}

# 新環境のデプロイ
envsubst < k8s/deployment.template.yml | kubectl apply -f -

# ヘルスチェック
attempt=1
max_attempts=30
until $(curl --output /dev/null --silent --head --fail http://localhost:8080/actuator/health); do
    if [ ${attempt} -eq ${max_attempts} ]; then
        echo "Max attempts reached. Deployment failed!"
        exit 1
    fi

    printf '.'
    attempt=$(( attempt + 1 ))
    sleep 2
done

echo "Deployment successful!"

3. デプロイメント設定例

# k8s/deployment.template.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-${COLOR}
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxSurge: 1
      maxUnavailable: 0
  template:
    spec:
      containers:
      - name: myapp
        image: ghcr.io/myapp:${VERSION}
        readinessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 10
          periodSeconds: 3
        livenessProbe:
          httpGet:
            path: /actuator/health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10

デプロイメントベストプラクティス

  1. 段階的なデプロイメント戦略
    • ステージング環境での事前検証
    • カナリアリリースの活用
    • ロールバック手順の整備
  2. モニタリングと検証
    • デプロイメント前後の健全性確認
    • パフォーマンスメトリクスの収集
    • エラーレート監視
  3. セキュリティ考慮事項
    • シークレット管理の自動化
    • 環境変数の適切な取り扱い
    • アクセス制御の確保
  4. 自動化のポイント
    • デプロイメントの完全自動化
    • ロールバックの自動化
    • 通知の自動化

これらのCI/CD設定により、安全で効率的な開発・デプロイメントサイクルを実現できます。

トラブルシューティングガイド

よくあるエラーと解決方法

Docker×Java環境で発生する主なエラーとその解決方法をまとめます。

1. メモリ関連の問題

エラー原因解決策
java.lang.OutOfMemoryError: Java heap spaceJVMヒープメモリ不足– コンテナメモリ制限の確認
– JVMメモリ設定の調整
java.lang.OutOfMemoryError: Metaspaceメタスペース領域不足-XX:MaxMetaspaceSizeの増加
– 不要なクラスロードの削減
# メモリ使用状況の確認
docker stats

# JVMメモリ設定の調整例
docker run -e JAVA_OPTS="-Xmx1g -XX:MaxMetaspaceSize=256m" myapp

2. コンテナ起動の問題

# コンテナログの確認
docker logs <container_id>

# 詳細なシステム情報の取得
docker inspect <container_id>

# コンテナ内でのデバッグ実行
docker exec -it <container_id> /bin/sh

3. ネットワーク接続の問題

# docker-compose.debug.yml
services:
  app:
    networks:
      - backend
    depends_on:
      db:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/actuator/health"]
      interval: 10s
      timeout: 5s
      retries: 3

デバッグとログ収集のテクニック

1. リモートデバッグの設定

# Dockerfile.debug
FROM eclipse-temurin:17-jdk
ENV JAVA_TOOL_OPTIONS="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005"
EXPOSE 5005
# デバッグモードでの起動
docker-compose -f docker-compose.debug.yml up

2. ログ収集システムの構築

# docker-compose.logging.yml
services:
  app:
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "3"

  filebeat:
    image: docker.elastic.co/beats/filebeat:7.15.0
    volumes:
      - ./filebeat.yml:/usr/share/filebeat/filebeat.yml:ro
      - /var/lib/docker/containers:/var/lib/docker/containers:ro

  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.15.0
    environment:
      - discovery.type=single-node

  kibana:
    image: docker.elastic.co/kibana/kibana:7.15.0
    ports:
      - "5601:5601"

3. デバッグスクリプト集

#!/bin/bash
# debug-tools.sh

# ヒープダンプの取得
get_heap_dump() {
    container_id=$1
    docker exec $container_id jmap -dump:format=b,file=/dumps/heap.hprof 1
    docker cp $container_id:/dumps/heap.hprof ./heap.hprof
}

# スレッドダンプの取得
get_thread_dump() {
    container_id=$1
    docker exec $container_id jstack 1 > thread_dump.txt
}

# GCログの有効化
enable_gc_logging() {
    docker run -e JAVA_OPTS="-Xlog:gc*=debug:file=/logs/gc.log" myapp
}

パフォーマンス問題の診断と改善

1. パフォーマンス監視設定

# docker-compose.monitoring.yml
services:
  app:
    ports:
      - "8080:8080"
      - "9090:9090"  # JMX Exporter
    environment:
      - JAVA_OPTS=-javaagent:/app/jmx_prometheus_javaagent.jar=9090:/app/config.yaml
    volumes:
      - ./monitoring/jmx_prometheus_javaagent.jar:/app/jmx_prometheus_javaagent.jar
      - ./monitoring/config.yaml:/app/config.yaml

2. パフォーマンス診断スクリプト

#!/bin/bash
# performance-analysis.sh

# CPU使用率の確認
check_cpu() {
    docker stats --no-stream --format "table {{.Container}}\t{{.CPUPerc}}\t{{.MemUsage}}"
}

# ボトルネック検出
detect_bottlenecks() {
    container_id=$1
    echo "=== CPU Hot Spots ==="
    docker exec $container_id jcmd 1 VM.native_memory

    echo "=== Thread Analysis ==="
    docker exec $container_id jcmd 1 Thread.print

    echo "=== GC Analysis ==="
    docker exec $container_id jcmd 1 GC.heap_info
}

# パフォーマンステスト実行
run_performance_test() {
    docker run --rm -v $(pwd):/scripts gatling/gatling:latest \
        -sf /scripts/gatling/simulations \
        -rf /scripts/gatling/results
}

3. パフォーマンス最適化チェックリスト

  1. アプリケーションレベル
    • [ ] JVMメモリ設定の最適化
    • [ ] GC設定の調整
    • [ ] スレッドプール設定の確認
    • [ ] コネクションプール設定の確認
  2. コンテナレベル
    • [ ] リソース制限の適切な設定
    • [ ] ネットワーク設定の最適化
    • [ ] ボリュームマウントの効率化
    • [ ] キャッシュ戦略の確認
  3. 監視と分析
    • [ ] メトリクス収集の設定
    • [ ] アラート閾値の設定
    • [ ] パフォーマンステストの自動化
    • [ ] ログ分析の実装

4. トラブルシューティングフローチャート

graph TD
    A[問題発生] --> B{エラー種別判断}
    B -->|メモリエラー| C[メモリ診断]
    B -->|起動エラー| D[コンテナログ確認]
    B -->|パフォーマンス低下| E[リソース使用率確認]

    C --> F[ヒープダンプ分析]
    D --> G[Dockerfile確認]
    E --> H[モニタリング確認]

    F --> I[メモリ設定調整]
    G --> J[イメージ再ビルド]
    H --> K[リソース制限調整]

これらのトラブルシューティングツールと手順を活用することで、Docker×Java環境での問題をより効率的に解決できます。

まとめ

Docker×Java開発環境構築の重要ポイント

1. 環境構築の基本原則

  • 一貫性のある開発環境の維持
  • 適切なベースイメージの選択
  • 効率的なビルドプロセスの確立
  • セキュリティを考慮した設計

2. 実装時の注意点とベストプラクティス

開発効率の最適化

  • マルチステージビルドの活用
  • 依存関係のキャッシュ戦略
  • 開発環境と本番環境の分離
  • 適切なリソース管理

セキュリティの確保

  • 脆弱性スキャンの定期実行
  • 最小権限の原則の遵守
  • セキュアな設定の徹底
  • 監査ログの適切な管理

パフォーマンスの最適化

  • JVMの適切な設定
  • コンテナリソースの最適化
  • ビルドプロセスの効率化
  • 監視体制の確立

次のステップとリソース

1. さらなる学習のために

2. 推奨ツール

  • Container Security Scanner: Trivy
  • Performance Monitoring: Prometheus + Grafana
  • CI/CD: GitHub Actions
  • Log Management: ELK Stack

3. コミュニティリソース

  • Docker Community Forums
  • Stack Overflow – Docker タグ
  • GitHub – Java Docker サンプルプロジェクト

以上が、Docker×Java開発環境の構築から運用までの包括的なガイドでした。このガイドで紹介した手法やベストプラクティスを活用することで、効率的で安全な開発環境を構築できます。技術の進化に合わせて定期的に設定を見直し、常に最適な開発環境を維持することを推奨します。

注意: 本記事の内容は2024年時点のものです。Docker、Java、および関連ツールのバージョンアップに応じて、適宜設定を調整してください。

Last edited 5 時間前