Contents
はじめに
近年、チーム開発では 「環境の差異」 が原因で起きるバグやセットアップ工数がボトルネックになることが多く報告されています。Docker と Docker Compose を導入すれば、「コードとしてインフラを管理」 でき、全員が同一の開発環境を瞬時に構築できます。本稿では、実務で即座に活用できる手順と注意点を具体例を交えて解説します。
Docker / Docker Compose がもたらす主なメリット
| 項目 | 具体的な効果 |
|---|---|
| 環境の一貫性 | OS、ライブラリ、ランタイムがイメージに閉じ込められるため、開発マシン間・OS 間で「動く/動かない」の差異が解消します。 |
| インフラをコード化 | docker-compose.yml にサービス構成・ネットワーク・ボリュームを宣言でき、Git 管理下に置くだけで再現性の高いスタックが共有できます。 |
| 高速なセットアップ | 新規メンバーはリポジトリをクローンし docker compose up --build すれば、必要なミドルウェア(JDK・Maven・DB 等)が自動で立ち上がります。 |
| 依存関係の明示化 | Dockerfile と Compose に記述したバージョン情報がそのまま実行環境になるため、ライブラリ衝突や「ローカルにインストールしたものと違う」問題を防げます。 |
| テスト・CI の統一基盤 | 同じコンテナイメージを CI ランナーでも使用できるので、ローカルでの動作確認と本番環境へのデプロイが一致します。 |
ポイント
Docker Compose は「宣言的に」複数サービスを管理するツールです。docker compose up1 回でappとdbが同時に起動し、依存関係の解決やネットワーク設定まで自動化されます。
前提条件とインストール手順
必要なツール一覧
| ツール | 推奨バージョン | 用途 |
|---|---|---|
| Docker Desktop | 4.30 以上(Docker Engine 24 系) | コンテナ実行基盤、Compose の実装体 |
| Visual Studio Code | 1.88 以上 | エディタ/Dev Container 拡張でコンテナ内開発 |
| Git | 2.40 以上 | ソースコード管理 |
| OpenJDK 17 (コンテナイメージ) | - | Java 実行環境(Dockerfile で取得) |
インストール手順
- Docker Desktop
- 公式サイト https://www.docker.com/products/docker-desktop からインストーラをダウンロードし、指示に従ってインストール。
-
Windows の場合は「WSL 2 ベースのエンジン」を有効にし、Kubernetes は オフ にしておきます(本ガイドでは使用しません)。
-
VS Code
-
https://code.visualstudio.com/ から取得。起動後、拡張機能パネルで以下をインストールします。
- Remote - Containers(または Dev Containers)
- Docker
-
Git
git --versionが表示されない場合は公式サイト https://git-scm.com/ から最新版を取得し、PATH を通してください。
動作確認
|
1 2 3 4 5 |
docker version # Docker Engine のバージョン情報 docker compose version # Compose プラグインのバージョン code --version # VS Code のバージョン git --version # Git のバージョン |
すべてのコマンドがバージョン情報を返せれば、準備完了です。
プロジェクト構成例とマルチステージ Dockerfile の作り方
ディレクトリ構成(サンプル)
|
1 2 3 4 5 6 7 8 9 |
my-spring-app/ ├─ src/ # Java ソースコード │ └─ main/java/com/example ├─ pom.xml # Maven ビルド定義 ├─ docker/ │ ├─ Dockerfile # マルチステージビルド用 │ └─ devcontainer.json # VS Code 用設定(後述) └─ .gitignore |
マルチステージ Dockerfile
以下は JDK 17 と Maven を同一イメージで扱う例です。ビルド段階と実行段階を分離することで、最終イメージに不要なツールが残らず 軽量化 できます(Alpine ベースのイメージはサイズが数十 MB 程度になることが多いですが、プロジェクト固有の依存関係により変動します)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# ---------- Stage 1: Build ---------- FROM eclipse-temurin:17-jdk-alpine AS build WORKDIR /app # Maven のキャッシュを活用するために pom.xml と .mvn ディレクトリだけ先にコピー COPY pom.xml . COPY .mvn/ .mvn/ RUN apk add --no-cache maven \ && mvn -B dependency:go-offline # 依存 JAR をローカルキャッシュへ取得 # ソースコード全体をコピーしてビルド COPY src/ src/ RUN mvn -B package -DskipTests # ---------- Stage 2: Runtime ---------- FROM eclipse-temurin:17-jre-alpine AS runtime WORKDIR /app # ビルド済み JAR を抽出 COPY --from=build /app/target/*.jar app.jar EXPOSE 8080 ENV JAVA_OPTS="-XX:+UseContainerSupport -Dspring.devtools.restart.enabled=true" ENTRYPOINT ["sh","-c","java $JAVA_OPTS -jar /app/app.jar"] |
ポイント解説
| 項目 | 内容 |
|---|---|
| マルチステージ | build ステージで Maven と JDK を使いビルドし、runtime では最小限の JRE のみを残すことでイメージサイズを削減します。 |
| Alpine ベース | -alpine 系イメージは公式に保守されており、脆弱性情報が追跡しやすい点もメリットです。 |
| ビルドキャッシュ活用 | 依存取得を最初の層で実行するため、ソースコードだけが変更された場合はこの層が再利用され、ビルド時間が短縮します(具体的な削減率はプロジェクトごとに異なるため、数値は記載しません)。 |
| DevTools 用オプション | JAVA_OPTS に DevTools を有効化するフラグを入れ、コード変更時の自動再起動を実現します。 |
docker‑compose.yml の書き方とリソース制限に関する注意点
基本構成(version 3.8)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
version: "3.8" services: app: build: context: . dockerfile: docker/Dockerfile ports: - "8080:8080" environment: SPRING_PROFILES_ACTIVE: dev JAVA_OPTS: "-Dspring.devtools.restart.enabled=true" volumes: # ソースコードのリアルタイム同期(ホットリロード用) - ./src:/app/src:cached restart: unless-stopped db: image: postgres:15-alpine environment: POSTGRES_USER: app_user POSTGRES_PASSWORD: secret POSTGRES_DB: app_db volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" restart: unless-stopped volumes: pgdata: |
リソース制限に関する重要な注意点
deploy.resources.limits は Docker Swarm モードでのみ有効です。
ローカル開発(Compose のデフォルトモード)では以下のように記述しても無視されます。
|
1 2 3 4 5 6 7 |
# ❌ 例:このままでは何も制限されません deploy: resources: limits: cpus: "1.0" memory: "512M" |
開発環境で CPU / メモリの上限を設定したい場合は、Compose の version: "2" 系で提供されているオプション(mem_limit, cpus)や Docker Desktop の「Resource Limits」設定を利用してください。 ただし、これらは ホスト全体に対する上限ではなく、コンテナ単位の制約 になる点に注意が必要です。
実務的な提案
- 開発マシンのリソースが十分であれば、明示的な制限は設定しない。
- 本番環境やステージングで Swarm / Kubernetes にデプロイする際にのみdeploy.resourcesを記述する。
開発効率を高めるベストプラクティス(2024 年版)
| # | ベストプラクティス | 実装例・ポイント |
|---|---|---|
| 1 | リソース制限は本番/ステージングでのみ | deploy.resources は Swarm 用に残す。ローカルでは mem_limit 等を検討。 |
| 2 | イメージの最小化 | マルチステージビルド、Alpine ベース、不要ファイルは .dockerignore に列挙。 |
| 3 | 脆弱性スキャンの自動化 | docker scan <image> を CI の一段階に組み込み、定期的にベースイメージを更新。 |
| 4 | 非 root ユーザーで実行 | 本番用 Dockerfile に USER appuser(UID 1000)を追加し、最小権限で起動。開発時は省略可。 |
| 5 | シークレット管理 | DB パスワード等は .env ファイルか Docker Compose の environment: ではなく、Docker Secret / GitHub Actions の暗号化変数を使用。 |
| 6 | ビルドキャッシュの有効活用 | COPY pom.xml . && mvn -B dependency:go-offline を最初に実行し、ソースコード変更時は依存取得層が再利用されるようにする。 |
| 7 | テストコンテナの活用 | Unit テストはローカルで走らせつつ、統合テストは Testcontainers や docker compose -f docker-compose.test.yml up -d で実行。 |
| 8 | ログ出力の標準化 | Spring の logging.level.root=INFO をデフォルトにし、必要に応じて application-dev.yml に DEBUG を上書き。コンテナは標準出力へ直接出すので docker logs -f <svc> が即時閲覧可能。 |
| 9 | CI/CD パイプラインへの組み込み | ビルド・テスト・イメージプッシュを一連のジョブで実行し、docker compose pull && docker compose up -d によるステージングデプロイを自動化。 |
| 10 | IDE とコンテナのシームレス連携 | VS Code の Dev Container を利用すれば、ローカル環境に依存せず IDE が直接コンテナ内で起動し、拡張機能やデバッグがそのまま使える。 |
VS Code Dev Container の設定例とトラブルシューティング
ディレクトリ構成
|
1 2 3 4 5 6 |
my-spring-app/ ├─ .devcontainer/ │ ├─ devcontainer.json │ └─ Dockerfile # 上記マルチステージ Dockerfile を流用 └─ docker-compose.yml |
devcontainer.json
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "name": "Spring Boot Dev Container", "dockerComposeFile": ["../docker-compose.yml"], "service": "app", "workspaceFolder": "/workspaces/my-spring-app", "extensions": [ "vscjava.vscode-java-pack", "pivotal.vscode-boot-dev-pack" ], "settings": { "java.home": "/usr/lib/jvm/java-17-openjdk" }, "postCreateCommand": "mvn -B dependency:go-offline" } |
dockerComposeFileに上位ディレクトリの Compose ファイルを指定し、appサービスに対して VS Code が自動でdocker compose upを実行します。postCreateCommandで依存取得だけを先行させることで、IDE 起動後すぐにコード補完が利用可能です。
よくあるエラーと対処法
| エラーメッセージ | 原因例 | 対策 |
|---|---|---|
Failed to resolve dependencies |
ネットワーク障害、Maven リポジトリへのアクセス不可 | プロキシ設定を確認し、ホスト側で mvn -U dependency:go-offline を手動実行してキャッシュを作成 |
Port 8080 is already allocated |
ローカルに同じポートが既にバインドされている | docker compose down 後、lsof -i :8080 で占有プロセスを特定し停止 |
permission denied while trying to connect to the Docker daemon socket |
Docker Desktop が起動していない、またはユーザー権限が不足 | Docker Desktop を再起動する。Linux 環境では sudo usermod -aG docker $USER && newgrp docker を実行 |
Cannot locate DevContainer configuration file |
.devcontainer ディレクトリの位置が誤っている |
VS Code のワークスペースルートがプロジェクト直下になるようフォルダ構成を確認 |
コンテナ間通信の確認
|
1 2 |
docker compose exec app curl -s http://db:5432 || echo "DB 接続失敗" |
appからサービス名dbが DNS 名として解決できれば、ネットワークは正常です。- エラーが出た場合は Compose の
depends_on設定や起動順序を見直してください。
CI/CD への組み込み例(GitHub Actions)
以下は GitHub Actions でビルド・テスト・イメージプッシュ・ステージングデプロイまで行うサンプルです。実際のリポジトリに合わせて DOCKER_REGISTRY や STAGING_SERVER を変更してください。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
name: CI/CD Pipeline on: push: branches: [ main ] pull_request: jobs: build-test: runs-on: ubuntu-latest steps: - name: Checkout code uses: actions/checkout@v4 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v3 - name: Cache Maven dependencies uses: actions/cache@v4 with: path: ~/.m2/repository key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }} restore-keys: | ${{ runner.os }}-maven- - name: Build Docker image run: | docker compose -f docker-compose.yml build - name: Run unit tests inside container run: | docker compose -f docker-compose.yml run --rm app mvn test push-image: needs: build-test runs-on: ubuntu-latest steps: - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASSWORD }} - name: Push image run: | IMAGE_TAG=ghcr.io/${{ github.repository }}:${{ github.sha }} docker tag my-spring-app_app:latest $IMAGE_TAG docker push $IMAGE_TAG deploy-staging: needs: push-image runs-on: ubuntu-latest if: github.ref == 'refs/heads/main' steps: - name: SSH to staging server & deploy uses: appleboy/ssh-action@v1.0.3 with: host: ${{ secrets.STAGING_HOST }} username: ${{ secrets.STAGING_USER }} key: ${{ secrets.STAGING_SSH_KEY }} script: | cd /opt/my-spring-app docker compose pull docker compose up -d --remove-orphans |
- キャッシュ:Maven のローカルリポジトリを
actions/cacheで保存し、ビルド時間を短縮。 - テスト実行はコンテナ内で走らせることで、ローカルと同一環境の検証が可能です。
- イメージプッシュは GitHub Container Registry(または Docker Hub)へ自動的にタグ付けして保存します。
まとめ
- Docker + Compose によって「コードとしてインフラ」を実現し、全員が同一の開発環境を瞬時に構築できます。
- マルチステージ Dockerfile と Alpine ベース の組み合わせでイメージサイズとビルド時間を最適化します(具体的な数値はプロジェクトごとに測定してください)。
deploy.resourcesは Swarm 用 であり、ローカル開発では無視されます。リソース制限が必要な場合は Compose v2 系のオプションか Docker Desktop の設定を利用しましょう。- ベストプラクティス(2024 年版) を取り入れることで、セキュリティ・パフォーマンス・可搬性のすべてを高められます。
- VS Code の Dev Container 機能で IDE とコンテナがシームレスに連携し、開発者体験が向上します。
- CI/CD パイプラインへ Docker ビルド・テスト・デプロイを自動化すれば、ローカルと本番のギャップがなくなります。
実践への第一歩
このリポジトリをクローンし、docker compose up --buildを実行するだけで、完全にコンテナ化された Spring Boot アプリ開発環境が立ち上がります。ぜひ手元のプロジェクトでも試してみてください。
本稿は執筆時点(2024 年)でのベストプラクティスを元に作成しています。Docker、Compose、Java のバージョンが更新された場合は公式ドキュメントをご参照ください。