私は Docker の初心者で、多くのドキュメントを読み、さまざまな方法を試したにもかかわらず、Maven を使用して Java プロジェクトを実行する方法がわかりません。
- を使用してイメージをビルドする必要がありますか
Dockerfile
? - ホストで 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
ノート
- 決定したのはエクリプス テムリンJavaベースイメージ。現在では、さまざまなOpen JDKオプションが豊富に用意されています。
- 私はDebianベースのイメージを好みます。この選択は次のように変更できます。利用可能なタグを見る
- 最終画像を小さくするために、第 2 段階で「17-jre-jammy」タグを使用します。
- Spring BootイニシャライザにはJDKだけが必要です。Mavenがオンボード
- キャッシュマウントタイプに注意してください。これはビルドキットのイノベーションビルド間の依存関係をキャッシュする
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 .
注記:
- 通常、私は「最新」タグ以上のものをプッシュします。それはこの回答の範囲外です。
参照:
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
注記:
- これはデモです。Kubernetes にデプロイする推奨方法ではありません。Helm チャートを使用します (これもこの回答の範囲外です)
更新 (2019-02-22)
この回答では、マルチステージDockerfile内でMavenを実行する手順を説明しようとしました。
1. アプリケーションを生成する
Springイニシャライザを使用してデモアプリを生成する
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 を介して他のサードパーティ リポジトリを管理できることです。