Maven プロジェクトを Docker 化するにはどうすればよいでしょうか? 実現する方法はいくつありますか? 質問する

Maven プロジェクトを Docker 化するにはどうすればよいでしょうか? 実現する方法はいくつありますか? 質問する

私は Docker の初心者で、多くのドキュメントを読み、さまざまな方法を試したにもかかわらず、Maven を使用して Java プロジェクトを実行する方法がわかりません。

  1. を使用してイメージをビルドする必要がありますかDockerfile?
  2. ホストで Maven プロジェクトを実行するためのコマンドは何ですかDockerfile?

ベストアンサー1

動作例。

これは Spring Boot のチュートリアルではありません。Docker コンテナ内で Maven ビルドを実行する方法に関する質問に対する最新の回答です。

この質問はもともと 8 年前に投稿されました。


更新 (2023-10-12)

この回答は、現在 Docker のデフォルトとなっている新しい Builkit エンジンを活用するように改訂されています。また、オプションの Kubernetes 機能もいくつか含まれています。

これが役に立つことを願います

1. デモアプリケーションを生成する

Spring Bootデモアプリケーションは、Spring 初期化

フォームを使用して「Maven」、「Java」を選択し、現在はデフォルトで Java 17 になっていることに注意してください。

ここに画像の説明を入力してください

2. Dockerfileを作成する

#
# Build stage
#
FROM eclipse-temurin:17-jdk-jammy AS build
ENV HOME=/usr/app
RUN mkdir -p $HOME
WORKDIR $HOME
ADD . $HOME
RUN --mount=type=cache,target=/root/.m2 ./mvnw -f $HOME/pom.xml clean package

#
# Package stage
#
FROM eclipse-temurin:17-jre-jammy 
ARG JAR_FILE=/usr/app/target/*.jar
COPY --from=build $JAR_FILE /app/runner.jar
EXPOSE 8080
ENTRYPOINT java -jar /app/runner.jar

ノート

  1. 決定したのはエクリプス テムリンJavaベースイメージ。現在では、さまざまなOpen JDKオプションが豊富に用意されています。
  2. 私はDebianベースのイメージを好みます。この選択は次のように変更できます。利用可能なタグを見る
  3. 最終画像を小さくするために、第 2 段階で「17-jre-jammy」タグを使用します。
  4. Spring BootイニシャライザにはJDKだけが必要です。Mavenがオンボード
  5. キャッシュマウントタイプに注意してください。これはビルドキットのイノベーションビルド間の依存関係をキャッシュする

3. レジストリにログイン

docker login myregistry

これは汎用コマンドです。一部のクラウド プロバイダー レジストリには、次のような代替コマンドがあります。

az acr login --name my-azure-registry

4. イメージを構築する

Buildkit は現在、Docker のデフォルトのビルド エンジンです。ここでは、これを使用して Kubernetes クラスターでビルドを実行します。

#
# (Optional) Run a build pod on your k8s cluster
#
docker buildx create --name my-builder --driver kubernetes --driver-opt replicas=1 --use

#
# Build and push the image (Buildkit "buildx" plugin is now part of Docker)
#
docker buildx build --tag  myregistry/myorg/demo:latest --push .

注記:

  1. 通常、私は「最新」タグ以上のものをプッシュします。それはこの回答の範囲外です。

参照:

5. イメージを実行する

Dockerを使用してローカルで実行する

docker run -d -p 8080:8080 myregistry/myorg/demo:latest

Kubernetes にデプロイ

kubectl create ns demo
kubectl -n demo create deployment demo --image=myregistry/myorg/demo:latest --port=8080 --replicas=1
kubectl -n demo expose deployment demo --type=LoadBalancer

注記:

  1. これはデモです。Kubernetes にデプロイする推奨方法ではありません。Helm チャートを使用します (これもこの回答の範囲外です)

更新 (2019-02-22)

この回答では、マルチステージDockerfile内でMavenを実行する手順を説明しようとしました。

1. アプリケーションを生成する

Springイニシャライザを使用してデモアプリを生成する

https://start.spring.io/

ここに画像の説明を入力してください

zipアーカイブをローカルに解凍する

2. Dockerfileを作成する

#
# Build stage
#
FROM maven:3.6.0-jdk-11-slim AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package

#
# Package stage
#
FROM openjdk:11-jre-slim
COPY --from=build /home/app/target/demo-0.0.1-SNAPSHOT.jar /usr/local/lib/demo.jar
EXPOSE 8080
ENTRYPOINT ["java","-jar","/usr/local/lib/demo.jar"]

注記

  • この例では、多段階ビルド最初のステージはコードのビルドに使用されます。2 番目のステージには、ビルドされた jar とそれを実行するための JRE のみが含まれます (ステージ間で jar がコピーされる方法に注意してください)。

3. イメージを構築する

docker build -t demo .

4. イメージを実行する

$ docker run --rm -it demo:latest

  .   ____          _            __ _ _
 /\\ / ___'_ __ _ _(_)_ __  __ _ \ \ \ \
( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
 \\/  ___)| |_)| | | | | || (_| |  ) ) ) )
  '  |____| .__|_| |_|_| |_\__, | / / / /
 =========|_|==============|___/=/_/_/_/
 :: Spring Boot ::        (v2.1.3.RELEASE)

2019-02-22 17:18:57.835  INFO 1 --- [           main] com.example.demo.DemoApplication         : Starting DemoApplication v0.0.1-SNAPSHOT on f4e67677c9a9 with PID 1 (/usr/local/bin/demo.jar started by root in /)
2019-02-22 17:18:57.837  INFO 1 --- [           main] com.example.demo.DemoApplication         : No active profile set, falling back to default profiles: default
2019-02-22 17:18:58.294  INFO 1 --- [           main] com.example.demo.DemoApplication         : Started DemoApplication in 0.711 seconds (JVM running for 1.035)

その他

ローカル リポジトリを使用して jar をキャッシュするように Maven ビルドを最適化する方法については、Docker hub のドキュメントをお読みください。


更新 (2019-02-07)

この質問は今から 4 年前のものであり、その間に Docker を使用したアプリケーションの構築は大きく変化したと言っても過言ではありません。

オプション 1: マルチステージ ビルド

この新しいスタイルにより、ビルド ツールやソース コードをカプセル化しない、より軽量なイメージを作成できるようになります。

ここでの例でも、公式メイヴン必要なバージョンの Maven を使用してビルドの最初の段階を実行するためのベース イメージ。ファイルの 2 番目の部分は、ビルドされた jar を最終出力イメージに組み立てる方法を定義します。

FROM maven:3.5-jdk-8 AS build  
COPY src /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean package

FROM gcr.io/distroless/java  
COPY --from=build /usr/src/app/target/helloworld-1.0.0-SNAPSHOT.jar /usr/app/helloworld-1.0.0-SNAPSHOT.jar  
EXPOSE 8080  
ENTRYPOINT ["java","-jar","/usr/app/helloworld-1.0.0-SNAPSHOT.jar"]  

注記:

  • 私はGoogleのディストロレスJava アプリに十分な実行時間を提供することを目的としたベース イメージ。

オプション2: ジブ

私はこのアプローチを使ったことはありませんが、Dockerfiles のような厄介なものを作成せずにイメージを構築できるため、調査する価値があるようです :-)

https://github.com/GoogleContainerTools/jib

このプロジェクトはMavenプラグインこれにより、コードのパッケージ化が Maven ワークフローに直接統合されます。


元の回答(完全性のために含まれていますが、かなり前に書かれたものです)

新しい公式イメージを使ってみてください。Maven用のものがあります。

レジストリ

このイメージを使用すると、ビルド時に Maven を実行してコンパイルされたアプリケーションを作成したり、次の例のようにコンテナー内で Maven ビルドを実行したりできます。

例 1 - コンテナ内で実行される Maven

次のコマンドは、コンテナ内で Maven ビルドを実行します。

docker run -it --rm \
       -v "$(pwd)":/opt/maven \
       -w /opt/maven \
       maven:3.2-jdk-7 \
       mvn clean install

ノート:

  • このアプローチの優れた点は、すべてのソフトウェアがコンテナ内にインストールされ、実行されることです。ホスト マシンには docker のみが必要です。
  • 見るこのバージョンのDockerfile

例2 - Nexusを使用してファイルをキャッシュする

Nexusコンテナを実行する

docker run -d -p 8081:8081 --name nexus sonatype/nexus

「settings.xml」ファイルを作成します。

<settings>
  <mirrors>
    <mirror>
      <id>nexus</id>
      <mirrorOf>*</mirrorOf>
      <url>http://nexus:8081/content/groups/public/</url>
    </mirror>
  </mirrors>
</settings>

次に、依存関係がキャッシュされるように、MavenをNexusコンテナにリンクして実行します。

docker run -it --rm \
       -v "$(pwd)":/opt/maven \
       -w /opt/maven \
       --link nexus:nexus \
       maven:3.2-jdk-7 \
       mvn -s settings.xml clean install

ノート:

  • Nexus をバックグラウンドで実行する利点は、ローカル コンテナーで実行されている Maven ビルドに対して透過的に、管理 URL を介して他のサードパーティ リポジトリを管理できることです。

おすすめ記事