Dockerfile を使用して、ソースコードからコンテナイメージをビルドし、ディストリビューションやデプロイメントを行うことができます。Java アプリケーションのコンテナ化は、Go や Python などの言語と比較して、特有の課題を伴うことがよくあります。これらの課題は、通常、Maven などの自己管理の依存関係リポジトリの使用や、Docker のキャッシュ機構に不慣れなことに起因し、ビルド時間が長くなる原因となります。このトピックでは、自己ホスト型の GitLab コードベースとプライベート Maven リポジトリを含む典型的なシナリオについて説明します。Dockerfile を使用して Java プロジェクトをビルドする方法、ビルドプロセスを高速化するために最適化する方法、そして Container Registry Enterprise Edition (ACR-EE) のビルドサービスを使用してイメージ作成を自動化する方法を学びます。
前提条件
-
GitLab コードベースを作成済みであること。
-
Maven リポジトリを作成済みであること。
-
Container Registry の Enterprise Edition インスタンスを作成済みであること。詳細については、「Enterprise Edition インスタンスの作成」をご参照ください。
サンプルプロジェクトの概要
このトピックでは、相互に依存する 2 つの Java プロジェクト を使用します:
-
Provider: 他のアプリケーションが呼び出すことができるサービスを提供します。
-
Core モジュール: 共通のインターフェイスを提供します。
-
Service モジュール: サービスを実装します。
-
-
Consumer: Provider プロジェクトのサービスを呼び出します。
-
Service モジュール: Provider プロジェクトの Core モジュールに依存します。次のコードはプロジェクト構造を示しています:
. ├── consumer │ ├── Dockerfile │ ├── consumer.iml │ ├── pom.xml │ └── service │ ├── pom.xml │ ├── src │ └── target └── provider ├── Dockerfile ├── core │ ├── pom.xml │ ├── src │ └── target ├── pom.xml ├── provider.iml └── service ├── pom.xml ├── src └── target
-
ビルドアーティファクト:
-
Provider プロジェクトからビルドされたプロデューサーアプリケーションイメージ。
-
Consumer プロジェクトからビルドされたコンシューマーアプリケーションイメージ。
ステップ 1:共通依存関係のアップロード
プロジェクトをビルドする前に、共通の依存関係を自己管理の Maven リポジトリにアップロードします。この例の Provider プロジェクトでは、Provider ディレクトリで次のコマンドを実行します:
mvn clean install org.apache.maven.plugins:maven-deploy-plugin:2.8:deploy -DskipTests
ステップ 2:カスタム Maven ベースイメージの作成
コンテナビルド環境から自己管理の Maven リポジトリにアクセスするには、リポジトリ構成をベースイメージに含めます。推奨されるアプローチは、公式の Maven イメージを基に、全社共通のカスタム Maven ベースイメージを作成することです。これにより、アプリケーションプロジェクトはこのベースイメージを使用して Maven リポジトリにアクセスできます。
-
次の内容を Dockerfile として保存し、Maven リポジトリの settings.xml ファイルと同じディレクトリに配置します。
FROM maven:3.8-openjdk-8 # プロジェクトに合った Maven イメージを指定します。この例では Maven v3.8 を使用します。 ADD settings.xml /root/.m2/ # カスタム Maven リポジトリ構成を適切なディレクトリに追加します。 -
次のコマンドを実行してイメージをビルドし、リモートイメージリポジトリにプッシュします。
ls Dockerfile settings.xml docker build -t demo-registry-vpc.cn-beijing.cr.aliyuncs.com/demo/maven-base:3.8-openjdk-8 -f Dockerfile . Sending build context to Docker daemon 7.68kB Step 1/2 : FROM maven:3.8-openjdk-8 ---> a3f42bfde036 Step 2/2 : ADD settings.xml /root/.m2/ ---> db0d5a5192e3 Successfully built db0d5a5192e3 Successfully tagged demo-registry-vpc.cn-beijing.cr.aliyuncs.com/demo/maven-base:3.8-openjdk-8 docker push demo-registry-vpc.cn-beijing.cr.aliyuncs.com/demo/maven-base:3.8-openjdk-8
ステップ 3:コンシューマーアプリケーションイメージのビルド
次のコマンドを実行します。ビルドに必要なすべてのベースイメージを Alibaba Cloud のイメージリポジトリにプッシュすることを推奨します。
FROM demo-registry-vpc.cn-beijing.cr.aliyuncs.com/demo/maven-base:3.8-openjdk-8 AS builder
# pom.xml とソースコードを追加
ADD ./pom.xml pom.xml
ADD ./service service/
# jar をパッケージ化
RUN mvn clean package
# 第 2 段階:最小実行環境
FROM demo-registry-vpc.cn-beijing.cr.aliyuncs.com/demo/openjdk:8-jre-alpine
# 第 1 段階から jar をコピー
COPY --from=builder service/target/service-1.0-SNAPSHOT.jar service-1.0-SNAPSHOT.jar
EXPOSE 8080
CMD ["java", "-jar", "service-1.0-SNAPSHOT.jar"]
ステップ 4:ビルド速度の最適化
「ステップ 3:コンシューマーアプリケーションイメージのビルド (Provider プロジェクトの場合はスキップ)」では、コンテナイメージのビルドに成功しました。しかし、ソースコードを修正して再ビルドするたびに、Maven がすべての依存関係を再ダウンロードすることにお気づきかもしれません。この速度低下は、ビルドプロセスが依存関係キャッシュを使用しないために発生します。これは、Docker のレイヤーキャッシュの仕組みによるものです。ソースコードを修正すると、ADD 命令内のコンテンツのハッシュが変更されます。この変更により、プロジェクトをビルドする RUN レイヤーを含む、後続のすべてのレイヤーのキャッシュが無効になります。その結果、Maven は依存関係を再度ダウンロードします。詳細については、「Dockerfile のベストプラクティス」をご参照ください。
ビルド速度を最適化するには、Maven の依存関係がキャッシュされ、ビルド間で再利用できるようにします:
-
まず、プロジェクトの pom.xml ファイルのみをコンテナにコピーし、依存関係をダウンロードします。pom.xml ファイルが変更されない限り、後続のビルドではキャッシュされた依存関係レイヤーを再利用できます。
-
プロジェクトのソースコードをコピーしてコンパイルします。
次の例は、改善された Dockerfile を示しています。この変更により、初回ビルドには約 43 秒かかります。ソースコードのみが変更された後続のビルドは、わずか 7 秒で完了します。
FROM demo-registry-vpc.cn-beijing.cr.aliyuncs.com/demo/maven-base:3.8-openjdk-8 AS builder
# 依存関係を安全に解決するため (ソースコードが変更されても再ダウンロードしない)
ADD ./pom.xml pom.xml
ADD ./service/pom.xml service/pom.xml
RUN mvn install
ADD ./service service/
# jar をパッケージ化
RUN mvn clean package
# 第 2 段階:最小実行環境
FROM demo-registry-vpc.cn-beijing.cr.aliyuncs.com/demo/openjdk:8-jre-alpine
# 第 1 段階から jar をコピー
COPY --from=builder service/target/service-1.0-SNAPSHOT.jar service-1.0-SNAPSHOT.jar
EXPOSE 8080
CMD ["java", "-jar", "service-1.0-SNAPSHOT.jar"]
ステップ 5:ACR-EE によるビルドの自動化
Container Registry Enterprise Edition (ACR-EE) は、エンタープライズレベルのビルドサービスを提供しており、イメージビルドワークフローの自動化に推奨されます。詳細については、「Enterprise Edition インスタンスを使用したイメージのビルド」をご参照ください。
以下のセクションでは、このサービスを使用するためのいくつかのベストプラクティスについて説明します。
-
VPC セキュアビルドモードの使用
クラウドでホストされている自己管理の GitLab リポジトリの場合、VPC セキュアビルドモードを使用してイメージをビルドすることを推奨します。この方法により、サービスをパブリックインターネットに公開することを回避できます。詳細については、「VPC でのコンテナイメージのビルド」をご参照ください。
-
イミュータブルなイメージタグの使用
リポジトリに対してイミュータブルなイメージタグを有効にすることを推奨します。これにより、本番環境のイメージタグが誤って上書きされるのを防ぎます。

-
コミット ID に基づくビルドルールの作成
ビルドルールを設定して、ビルドごとに 2 つのイメージタグを生成するようにします。1 つのタグはソースコードのコミット ID を使用し、これによりイメージバージョンを対応するコードにマッピングするのが簡単になります。もう 1 つのタグは
latestで、常に最新のビルドを指します。
コードをコミットすると、ビルドが自動的にトリガーされます。次の図は、2 つの個別のコードコミットによってトリガーされる 2 つのビルドプロセスを示しています。各ビルドは 2 つのイメージを生成します。2 回目のビルドはキャッシュを効果的に使用するため、初回ビルドよりも大幅に高速です。
