本ページはプロモーションが含まれています

Docker

DockerでJava開発!環境構築をすばやく終わらせる方法

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

Javaの開発環境構築、手間取っていませんか?

「新人のPCにJDKをインストールして、環境変数を設定して…」

「DBのバージョンが開発環境と本番環境で違って動かない!」

「私のPCでは動くのに、なぜか他の人のPCでは動かない…」

私も以前は、プロジェクト参加時の環境構築に半日(ひどい時は1日)を費やしていました。しかし、Docker を導入してからは、開発環境の構築が劇的に変わりました。

この記事は、「Dockerの名前は聞くけれど、Java開発でどう使えばいいかわからない」という方に向けて書いています。

この記事を読めば、Dockerの基本から、JavaアプリをDockerで動かす具体的な手順、さらにチーム開発を効率化するコツまで理解できます。Dockerを使って、「誰でも」「すぐに」「同じ」開発環境を手に入れる方法を学びましょう。

DockerとJavaの関係を理解しよう

そもそもDockerとは?コンテナ技術の基本

Dockerは、「コンテナ」と呼ばれる技術を使って、アプリケーションの実行環境をかんたんに構築・管理するためのプラットフォームです。

コンテナをひとことで例えるなら、「軽量な、アプリ専用の実行環境」です。

従来の開発では、自分のPC(ホストOS)に直接Java (JDK) やデータベース (MySQLなど) をインストールしていました。

Dockerを使うと、OS上に「コンテナ」という隔離された箱をいくつも作れます。そして、「Java 17が入った箱」「MySQL 8.0が入った箱」のように、必要なソフトウェアを箱ごとに分けて管理できるのです。

この「箱」には、Javaアプリの実行に必要なもの(JDK、ライブラリ、アプリ本体)がすべてパッケージングされています。そのため、この箱(コンテナ)をどこへ持っていっても、まったく同じように動作します。

Java開発にDockerを使うメリット

Java開発でDockerを使うメリットは非常に多く、とくに以下の4点が大きいです。

メリット

  1. 環境の「再現性」が手に入るこれが最大のメリットです。「私のPCでは動くのに」という問題がなくなります。「Dockerfile」という設定ファイルに環境の定義をすべて記述します。チーム全員が同じファイルを使うため、誰のPCでも100%同じ環境が動くのです。
  2. 環境構築が「高速」になる新しいPCでプロジェクトを始める場合、従来はJDK、Maven、IDE、DB…と多くのインストールが必要でした。Dockerなら、docker compose up というコマンドひとつで、JavaアプリもDBもすべて起動します。文字どおり、数分で開発を開始可能です。
  3. 環境を「分離」できる「プロジェクトAではJava 8とMySQL 5.7が、プロジェクトBではJava 17とPostgreSQL 14が必要」という状況も簡単に解決します。Dockerはコンテナごとに環境を隔離します。ホストPCを汚すことなく、複数の異なるバージョンのミドルウェアを同時に動かせるのです。
  4. 本番環境への移行が「スムーズ」になる開発環境で使ったコンテナの「設計図」をそのまま本番環境でも使えます。開発環境と本番環境の差異(OSの違い、ライブラリのバージョン違いなど)による「デプロイしたら動かない」という事故を防げます。

仮想マシンとの違いをわかりやすく比較

Dockerのコンテナとよく比較されるのが「仮想マシン (VM)」です。どちらも環境を隔離する技術ですが、根本的なしくみが違います。

仮想マシン

仮想マシン (VM)は、「OSまるごと」を仮想化します。ホストOS (WindowsやmacOS) の上に、Hypervisorという土台を置き、そこにゲストOS (Linuxなど) をインストールします。

  • 例えるなら「一軒家」です。土地(ハードウェア)の上に、まるごと家(ゲストOS)を建てます。
  • 長所: OSレベルで完全に隔離されます。
  • 短所: 起動に数分かかり、メモリやディスクの消費が非常に大きいです。

コンテナ

コンテナ (Docker)は、ホストOSの「カーネル」というOSの核となる部分を共有します。OSまるごとを仮想化するのではなく、プロセスやファイルシステムだけを隔離します。

  • 例えるなら「マンションの部屋」です。建物(ホストOSカーネル)は共有しつつ、各部屋(コンテナ)は独立しています。
  • 長所: 起動が数秒と非常に高速で、メモリ消費も少ないです。
  • 短所: OSレベルでの隔離はVMに劣ります(ただし開発用途では十分すぎます)。

Java開発においては、起動が速くリソース消費の少ないDockerコンテナが圧倒的に便利です。

DockerでJava環境を構築する手順

必要なツール(Docker Desktop・JDKなど)

DockerでJava環境を動かすために準備するものは多くありません。

  • Docker DesktopWindowsやmacOSでDockerを使うための公式アプリケーションです。これひとつインストールすれば、Dockerの実行環境がすべて整います。Linuxの場合はDocker Engineをインストールします。
  • テキストエディタ (またはIDE)Dockerfile などの設定ファイルを書くために必要です。VS CodeやIntelliJ IDEAなど、普段お使いのもので問題ありません。

ここでよくある誤解が「JDK」です。

Dockerコンテナ内でJavaアプリを動かす場合、ホストPCにJDKをインストールする必要はありません。Java (JDK) は、コンテナの中にインストールするからです。

ただし、mvn packagegradle build コマンドを使ってJavaアプリを .jar ファイルにビルドする作業をホストPCで行う場合は、ホストPCにもJDKやMaven/Gradleが必要です。(このビルド作業自体もDockerコンテナ内で行う「マルチステージビルド」という高度なテクニックもあります)

Javaアプリを動かすためのDockerfileの書き方

Dockerコンテナの「設計図」となるのが Dockerfile という名前のテキストファイルです。Javaアプリを動かすための、シンプルなDockerfileの例を見てみましょう。

target/my-app-1.0.0.jar という名前でビルド済みのSpring Bootアプリがある前提です。

# 1. ベースイメージの指定
# OpenJDK 17 の軽量版 (slim) を土台にします
FROM openjdk:17-slim

# 2. コンテナ内の作業ディレクトリを指定
WORKDIR /app

# 3. ホストのjarファイルをコンテナにコピー
# ホストの target/my-app-1.0.0.jar を
# コンテナの /app/app.jar としてコピーします
COPY target/my-app-1.0.0.jar app.jar

# 4. ポートの公開
# Spring Boot がデフォルトで使う 8080 ポートを
# コンテナの外に公開するよう指定します
EXPOSE 8080

# 5. コンテナ起動時に実行するコマンド
# java -jar app.jar コマンドでアプリを起動します
ENTRYPOINT ["java", "-jar", "app.jar"]

このファイルをプロジェクトのルートディレクトリに Dockerfile という名前で保存します。

たったこれだけの記述で、「Java 17がインストールされ、指定したjarファイルを実行する」環境が定義できました。

あわせて読む

コンテナをビルドして実行する流れ

Dockerfile を作成したら、次に2つのステップを実行します。

  1. イメージのビルドDockerfile (設計図) から、コンテナの元となる「Dockerイメージ」を作成します。ターミナルで Dockerfile があるディレクトリに移動し、以下のコマンドを実行します。docker build -t my-java-app .
    • -t my-java-app は、作成するイメージに my-java-app という名前(タグ)を付ける指定です。
    • . (ドット) は、Dockerfile が今いるディレクトリにあることを示します。
  2. コンテナの実行作成したイメージを元に、コンテナを起動します。docker run -p 8080:8080 -d my-java-app
    • -p 8080:8080 は、ホストPCの 8080 番ポートと、コンテナの 8080 番ポート(EXPOSEで指定したもの)を接続する設定です。(ホスト側):(コンテナ側) の順で書きます。
    • -d は、コンテナをバックグラウンドで(デタッチモードで)実行するオプションです。
    • my-java-app は、先ほどビルドしたイメージの名前です。

これでコンテナが起動しました。ホストPCのブラウザから http://localhost:8080 にアクセスすれば、コンテナ内で動いているJavaアプリに接続できるはずです。

docker ps コマンドを実行すると、現在起動中のコンテナ一覧が確認できます。

ホスト⇄コンテナ間のファイル共有方法

コンテナは基本的に隔離されていますが、ホストPCのファイルやディレクトリをコンテナ内から参照したい場合があります。たとえば、「コンテナ内で出力されるログファイルを、ホストPCの使い慣れたエディタで見たい」といったケースです。

この場合、「ボリュームマウント」という機能を使います。

docker run コマンドに -v オプションを追加します。

docker run -p 8080:8080 -v /Users/myname/projects/my-app/logs:/app/logs -d my-java-app
  • : の前が「ホストPCのディレクトリパス(絶対パス)」
  • : の後が「コンテナ内のディレクトリパス」です。

このように指定すると、コンテナ内の /app/logs ディレクトリへの書き込みが、実際にはホストPCの /Users/myname/projects/my-app/logs ディレクトリに書き込まれます。コンテナを削除してもログファイルがホストPCに残るため、非常に便利です。

Java+Dockerでの開発を効率化するコツ

docker-composeでマルチコンテナ環境を管理

docker run コマンドは、ポートやボリュームの指定が増えると非常に長くなり、管理が大変です。また、Javaアプリは通常、データベース など他のサービスと連携して動作します。

「Javaアプリのコンテナ」と「PostgreSQLのコンテナ」を同時に、かんたんに起動・停止したい。

この問題を解決するのが docker-compose です。

docker-compose は、複数のコンテナ構成を docker-compose.yml というYAML形式のファイルに定義して、まとめて管理できるツールです。(DockerDesktopには標準で含まれています)

docker-compose.yml の例を見てみましょう。

# docker-compose.yml
version: '3.8' # ファイル形式のバージョン

services: # ここに起動したいコンテナ(サービス)を定義
  
  # 1. Javaアプリ (Spring Boot)
  app:
    build: . # カレントディレクトリのDockerfileを使ってビルド
    ports:
      - "8080:8080" # ホストの8080とコンテナの8080を接続
    environment:
      # Javaアプリに渡す環境変数
      - SPRING_DATASOURCE_URL=jdbc:postgresql://db:5432/mydb
      - SPRING_DATASOURCE_USERNAME=user
      - SPRING_DATASOURCE_PASSWORD=pass
    depends_on:
      - db # dbサービスが起動してからappを起動する

  # 2. PostgreSQLデータベース
  db:
    image: postgres:14 # Docker HubのPostgreSQL 14イメージを使用
    ports:
      - "5432:5432" # ホストの5432とコンテナの5432を接続
    environment:
      # PostgreSQLコンテナに渡す環境変数
      - POSTGRES_DB=mydb
      - POSTGRES_USER=user
      - POSTGRES_PASSWORD=pass

このファイルをプロジェクトルートに保存し、ターミナルで以下のコマンドを実行するだけです。

# 起動 (ビルドも自動で実行)
docker-compose up -d

# 停止・削除
docker-compose down

docker-compose を使えば、JavaアプリとDBの面倒な連携設定や起動順序をすべて自動化できます。

ホットリロード・デバッグ環境の構築方法

Java開発では、コードを修正するたびに docker build を実行するのは非常に非効率です。Spring Boot DevTools のようなホットリロード(自動再起動)を Docker環境でも実現したいものです。

これは、先ほど紹介した「ボリュームマウント」を応用することで実現できます。

docker-compose.ymlvolumes を追加し、ホストPCのソースコード(またはビルド成果物)をコンテナ内にマウントします。

# docker-compose.yml (抜粋)
services:
  app:
    build: .
    ports:
      - "8080:8080"
    volumes:
      # ホストのカレントディレクトリをコンテナの/appにマウント
      - .:/app 
    # ... (environment, depends_on)

さらに、DockerfileENTRYPOINT.jar の実行から、Maven/Gradle経由での実行に変更します(Spring Boot DevToolsを有効にするため)。

# Dockerfile (ホットリロード用)
FROM openjdk:17-slim
WORKDIR /app

# 先に依存関係だけコピーしてインストール (ビルド高速化のテクニック)
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline

# ソースコード全体をコピー
COPY src ./src

# 実行コマンド (jarではなくmvn spring-boot:run)
CMD ["./mvnw", "spring-boot:run"]

こうすることで、ホストPCでJavaのソースコードを変更・保存すると、それが即座にコンテナ内に反映されます。コンテナ内で動いているSpring Boot DevToolsが変更を検知し、アプリケーションを自動で再起動してくれるのです。

また、デバッグも可能です。Dockerfiledocker-compose.yml でJavaのデバッグポート (例: 5005) を開ける設定を追加します。

# docker-compose.yml (抜粋)
    ports:
      - "8080:8080"
      - "5005:5005" # デバッグポートを追加
    environment:
      # JVMのデバッグオプションを有効化
      - JAVA_TOOL_OPTIONS=-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:5005

これにより、IntelliJ IDEAなどのIDEから localhost:5005 にリモートデバッグ接続し、コンテナ内で動いているJavaアプリにブレークポイントを張ることができます。

チーム開発でのDocker運用ポイント

チーム全員がDockerの恩恵を受けるためには、いくつかのルールを決めておくとスムーズです。

  1. Dockerfile と docker-compose.yml をGitで共有するこれら2つのファイルこそが「環境の定義書」です。これをGitリポジトリに含めることで、新しいメンバーは git clone して docker-compose up するだけで、誰でも同じ開発環境を即座に起動できます。
  2. .dockerignore ファイルを活用するDockerfile で COPY . . のようにディレクトリ全体をコピーすると、不要なファイルまでコンテナ内にコピーされてしまいます。target ディレクトリや .git ディレクトリ、IDEの設定ファイル (.idea, .vscode) などはビルドに不要です。.gitignore と同じ書式で .dockerignore ファイルを作成し、不要なファイルを除外します。これにより、Dockerイメージのビルドが高速になり、イメージサイズも小さくなります。
  3. ベースイメージのバージョンを固定するDockerfile の FROM で指定するイメージは、openjdk:17 のような「メジャーバージョン指定」ではなく、openjdk:17.0.5-slim のような「マイナーバージョンまで含めた指定」を推奨します。メジャーバージョン指定だと、ある日突然ベースイメージが更新され、ライブラリの互換性問題などでビルドが通らなくなる可能性があるためです。

よくあるエラーと対処法

「Cannot connect to the Docker daemon」と出た場合

これは初心者が最も遭遇するエラーのひとつです。

  • 原因:Dockerの本体(デーモンと呼ばれるサービス)が起動していません。
  • 対処法:
    • Windows / macOS の場合: Docker Desktop アプリケーションを起動してください。タスクトレイ(やメニューバー)のクジラのアイコンがアニメーションせず、安定している状態になれば起動完了です。
    • Linux の場合: systemctl status docker でサービスの状態を確認し、停止していれば sudo systemctl start docker で起動します。また、一般ユーザーでdockerコマンドを実行するには、ユーザーを docker グループに追加する必要があります。

ポート競合・メモリ不足エラーの原因と解決策

  • ポート競合エラー (address already in use)
    • 原因: docker-compose.ymldocker run で指定したホスト側のポート(例: 8080)が、すでに別のアプリケーションによって使用されています。ホストPCで別のJavaアプリを起動しっぱなしにしている、などのケースが多いです。
    • 対処法:
      1. 競合しているプロセスを停止する。
      2. docker-compose.yml などのポートマッピング設定を変更する (例: ports: - "8081:8080" に変え、localhost:8081 でアクセスする)。
  • メモリ不足エラー (OOM / Out of Memory)
    • 原因: Javaアプリ (JVM) が、コンテナに割り当てられたメモリ上限を超えて使用しようとしました。
    • 対処法:
      1. Docker Desktop の設定 (Settings > Resources) を開き、Dockerが使用できるメモリの割り当て量を増やします。
      2. Dockerfiledocker-compose.ymlenvironment で、Javaのヒープサイズ (-Xmx) を明示的に指定し、コンテナのメモリ上限内に収まるよう調整します。

コンテナがすぐ終了する場合のチェックポイント

docker-compose up -d を実行したのに、docker ps で見るとコンテナが一覧に表示されない(すぐに終了している)場合があります。

  • 原因:コンテナは、ENTRYPOINT や CMD で指定されたメインのプロセスが終了すると、自動的に停止します。つまり、Javaアプリが起動に失敗してクラッシュしている可能性が高いです。
  • 対処法:
    1. docker ps -a コマンドで、停止したコンテナを含む全コンテナのID(または名前)を調べます。
    2. docker logs [コンテナID] コマンドを実行します。
    3. コンテナの標準出力(ログ)が表示されます。Javaの起動時エラー(設定ファイルが見つからない、DBに接続できない、ClassNotFoundException など)が出力されているはずです。そのエラーメッセージを読んで、Javaアプリや Dockerfile の設定を修正します。

Docker+Javaを活用した応用事例

Spring BootアプリをDocker化してデプロイする例

Dockerの真価は、開発環境だけでなく本番環境へのデプロイ(展開)で発揮されます。

docker build で作成した「Dockerイメージ」は、開発PCから本番サーバーへかんたんに持ち運べます。

  1. イメージの登録 (Push)Docker Hub や、AWSの ECR, GCPの GCR といった「コンテナレジストリ」に、ビルドしたJavaアプリのイメージをアップロード(push)します。
  2. サーバーでの実行 (Pull & Run)本番サーバー(クラウド上のVMなど)で、レジストリからイメージをダウンロード(pull)し、docker run または docker-compose up で実行します。

本番サーバーにはJDKやMavenをインストールする必要が一切ありません。Dockerが動く環境さえあればよいのです。

これにより、OSやミドルウェアのバージョン差異に悩まされることなく、確実なデプロイが実現します。

CI/CD環境(GitHub Actionsなど)との連携

DockerはCI/CD (継続的インテグレーション/継続的デリバリー) パイプラインと非常に相性が良いです。

GitHub ActionsJenkins, GitLab CI といったツールと連携し、以下の流れを自動化できます。

  1. 開発者がソースコードをGitにPushする。
  2. CIツールが変更を検知し、自動でテスト (mvn test) を実行する。
  3. テストが通ったら、自動で docker build を実行し、JavaアプリのDockerイメージを作成する。
  4. 作成したイメージをコンテナレジストリ (ECRなど) にPushする。
  5. (CD)本番環境(ECSなど)に対し、新しいイメージを使ってサービスを更新するよう命令する。

この仕組みを構築することで、開発者はコードを書くことに集中でき、ビルドからデプロイまでの面倒な手作業をすべて自動化できます。

クラウド環境(AWS・GCP)への展開

現代のクラウドプラットフォーム (AWS, GCP, Azure) は、Dockerコンテナを実行するためのマネージドサービスを強力にサポートしています。

  • AWS: ECS (Elastic Container Service)EKS (Kubernetes Service)
  • GCP: GKE (Google Kubernetes Engine)Cloud Run

これらのサービスを使えば、docker run を手動で実行する必要すらありません。

たとえばGCPの Cloud Run は、Dockerイメージを指定するだけで、自動でスケーリング(負荷に応じてコンテナ数を増減)し、HTTPS化まで行ってくれるサーバーレスのコンテナ実行環境です。

Java + Dockerで作成したイメージは、こうした最新のクラウドサービスへ移行するための「パスポート」の役割を果たします。

まとめ|Dockerを使えばJava開発はもっと楽になる

開発環境の再現性と保守性が向上

Dockerは、Java開発における「環境」の悩みを根本から解決します。

Dockerfiledocker-compose.yml という2つのファイルが、アプリケーションの実行環境のすべてを定義します。

これにより、チームの誰もが数分で同じ開発環境を再現できるようになります。環境構築にかかっていた数時間、あるいは数日といった時間を、本来のアプリケーション開発に使えるようになるのです。

また、Javaのバージョンを17から21に上げたい場合も、DockerfileFROM openjdk:17-slimFROM openjdk:21-slim に書き換えてビルドし直すだけです。環境の保守性が劇的に向上します。

  • この記事を書いた人
  • 最新記事

トム

・都内自社開発IT企業勤務/javaのバックエンドエンジニア
/java歴10年以上 ・首都圏在住30代
・資格:基本情報技術者/応用情報技術者/Java Silver/Python3エンジニア認定基礎

-Docker