私がやりたいのは、私のJavaアプリケーションですが、ほとんどのコンパイル言語では以下の考慮事項が当てはまるはずです。=
ビルドサーバーで、成果物としてアプリケーションのdockerイメージを作成します。そのためには、ビルドツール(通常はGradle、Maven、またはAnt)を使用してアプリケーションをコンパイルし、作成したJARファイルをdockerイメージに追加する必要があります。 DockerイメージでJARファイルを実行するだけなので、もちろん、Javaが既にインストールされているベースイメージから開始します。
この場合、ビルドツールがプロセス全体を制御します。そのため、JARファイルを準備し、JARを作成した後、Dockerを呼び出してイメージを作成します。これは、JARが事前に作成されるため機能し、DockerはJARの作成に必要なビルドプロセスを忘れることがあります。
しかし、私のDockerfileはもはやスタンドアロンではありません。 Dockerが機能するためには、Dockerの外部で行う手順に依存します。 Dockerfileには、JARファイルをイメージにコピーすることになっているCOPY
またはADD
ステートメントがあります。 jarが事前に作成されていない場合、このステートメントは失敗します。そのため、Dockerfileを実行するだけでは機能しない場合があります。これは、DockerHubの自動ビルド機能など、現在のDockerfileを使用してビルドするサービスと統合する場合に問題になります。
この場合、イメージの作成に必要なすべての手順がDockerfileに追加されるため、Dockerビルドを実行するだけでイメージを作成できます。
このアプローチの主な問題は、作成されているdockerイメージの外部で実行されるDockerfileコマンドに追加する方法がないことです。つまり、ソースコードとビルドツールをdockerイメージに追加し、イメージ内にJARファイルをビルドする必要があります。これにより、追加されたすべてのファイルが実行時に不要になるため、イメージが必要以上に大きくなります。これにより、画像にレイヤーが追加されます。
@ adrian-mouatがソースを追加し、アプリケーションをビルドし、1つのRUNステートメントでソースを削除すると指摘したように、Dockerイメージに不要なファイルとレイヤーを追加することを回避できました。これは、非常識な連鎖コマンドを作成することを意味します。
この場合、ビルドを2つに分割します。まず、ビルドツールを使用してJARファイルを作成し、リポジトリ(MavenまたはIvyリポジトリ)にアップロードします。次に、リポジトリからJARファイルを追加するだけの別個のDockerビルドをトリガーします。
私の意見では、より良い方法はビルドツールにプロセスを制御させるでしょう。これにより、クリーンなDockerイメージが得られます。イメージは配信するものであるため、これは重要です。動作しない可能性のあるDockerfileを回避するには、ビルドの一部として作成する必要があります。そのため、誤ってそれを使用して壊れたビルドを開始することはありません。
しかし、これではDockerHubと統合できません。
私が行方不明になっている別の方法はありますか?
Dockerレジストリハブには Mavenイメージ があり、これを使用してJavaコンテナを作成できます。
このアプローチを使用すると、ビルドマシンにJavaまたはMavenが事前にインストールされている必要はありません。Dockerはビルドプロセス全体を制御します。
├── Dockerfile
├── pom.xml
└── src
├── main
│ ├── Java
│ │ └── org
│ │ └── demo
│ │ └── App.Java
│ └── resources
│ └── log4j.properties
└── test
└── Java
└── org
└── demo
└── AppTest.Java
コンテナは次のように構築されます。
docker build -t my-maven .
そして、次のように実行します:
$ docker run -it --rm my-maven
0 [main] INFO org.demo.App - hello world
FROM maven:3.3-jdk-8-onbuild
CMD ["Java","-jar","/usr/src/app/target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]
コンテナを最適化してソースを除外する場合は、ビルドされたjarのみを含むDockerfileを作成できます。
FROM Java:8
ADD target/demo-1.0-SNAPSHOT-jar-with-dependencies.jar /opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar
CMD ["Java","-jar","/opt/demo/demo-1.0-SNAPSHOT-jar-with-dependencies.jar"]
そして、2つのステップでコンテナを構築します。
docker run -it --rm -w /opt/maven \
-v $PWD:/opt/maven \
-v $HOME/.m2:/root/.m2 \
maven:3.3-jdk-8 \
mvn clean install
docker build -t my-app .
__
Dockerに マルチステージビルド 機能が追加されました。これにより、Dockerはビルドツールを含むイメージを使用してコンテナーをビルドできますが、ランタイム依存関係のみを含むイメージを出力できます。
次の例は、この概念を示しています。最初のビルドフェーズのターゲットディレクトリからjarをコピーする方法に注意してください
FROM maven:3.3-jdk-8-onbuild
FROM Java:8
COPY --from=0 /usr/src/app/target/demo-1.0-SNAPSHOT.jar /opt/demo.jar
CMD ["Java","-jar","/opt/demo.jar"]
Java aplicationの構造)==
Demo
└── src
| ├── main
| │ ├── Java
| │ │ └── org
| │ │ └── demo
| │ │ └── App.Java
| │ └── resources
| │ └── application.properties
| └── test
| └── Java
| └── org
| └── demo
| └── App.Java
├──── Dockerfile
├──── pom.xml
Dockerfileのコンテンツ
FROM Java:8
EXPOSE 8080
ADD /target/demo.jar demo.jar
ENTRYPOINT ["Java","-jar","demo.jar"]
イメージをビルドして実行するコマンド
- プロジェクトのディレクトリに移動します。D:/ Demoと言います。
$ cd D/demo
$ mvn clean install
$ docker build demo .
$ docker run -p 8080:8080 -t demo
コンテナが実行されているかどうかを確認します
$ docker ps
出力は
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
55c11a464f5a demo1 "Java -jar demo.jar" 21 seconds ago Up About a minute 0.0.0.0:8080->8080/tcp cranky_mayer
最も簡単な方法は、ビルドツールにプロセスを制御させるです。それ以外の場合は、ビルドツールのビルドファイルを維持する必要があります(pom.xml
はMavenまたはbuild.gradle
Gradleの場合)およびDockerfile
。
Javaアプリ用のDockerコンテナを構築する簡単な方法は、 Jib を使用することです。これは、 Maven および Gradle プラグイン。
たとえば、Mavenを使用していて、実行中のDockerデーモンに対してコンテナーを構築する場合、次の1つのコマンドを実行するだけです。
mvn compile com.google.cloud.tools:jib-maven-plugin:0.9.2:dockerBuild
Dockerレジストリに直接ビルドする はJib docker
をインストールせずに、Dockerデーモン(ルート権限が必要)を実行するか、Dockerfile
。また、より高速で、イメージを再現可能に構築します。
ジブの詳細については、Githubリポジトリをご覧ください: https://github.com/GoogleContainerTools/jib
Spotify Docker Mavenプラグイン をしばらく使用しました。プラグインを使用すると、DockerビルドをMavenライフサイクルのフェーズにバインドできます。
例:ビルドされたアプリケーションをリソースとしてDockerビルドコンテキストに追加するプラグインを構成して、アプリケーションをパッケージ化(フェーズ:パッケージ)した後にDockerビルドを実行します。デプロイフェーズで、Dockerプッシュゴールを実行して、Dockerイメージをレジストリにプッシュします。これは、Nexusなどのリポジトリにアーティファクトを公開する通常のデプロイプラグインの横で実行できます。
その後、ビルドをCIサーバー上で2つの別個のジョブに分割しました。 Dockerはアプリケーションを実行する1つの方法にすぎないため(リリースされたアプリケーションはDockerだけでなく異なる環境でも必要になる場合があるため)、MavenビルドはDockerに依存するべきではありません。
そのため、最初のジョブはNexusでアプリケーションをリリースします(Mavenデプロイ経由)。 2番目のジョブ(最初のジョブのダウンストリーム依存関係である可能性があります)は、最新のリリースアーティファクトをダウンロードし、Dockerビルドを実行し、イメージをレジストリにプッシュします。最新のリリースをダウンロードするには、 Versions Maven Plugin (versions:use-latest-releases)と Maven Dependency Plugin (dependency:get anddependency:copy)を使用します。
2番目のジョブは、特定のバージョンのアプリケーションで開始して、古いリリースのDockerイメージを(再)ビルドすることもできます。さらに、両方のジョブを実行し、リリースバージョンまたはリリースアーティファクトをDockerビルドに渡すビルドパイプライン(Jenkins上)を使用できます。
いくつかのこと:
追加した同じ命令でファイルを削除しても、イメージ内のスペースは消費されません。公式画像のDockerfilesのいくつかを見ると、ソースをダウンロードし、同じステップですべてを削除します(例 https://github.com/docker-library/python/blob /0fa3202789648132971160f686f5a37595108f44/3.5/slim/Dockerfile )。これは、いくつかの迷惑な体操を行う必要があることを意味しますが、それは完全に実行可能です。
2つの別個のDockerfileに問題はありません。これの良いところは、JDKではなくJREを使用してjarをホストできることです。
jarまたはwarパッケージを実行するための代替の使用法があります
サンプルdockerfile
FROM base
ADD sample.jar renamed.jar
ENV HEAP_SIZE 256m
ENTRYPOINT exec Java -Xms$HEAP_SIZE -Xmx$HEAP_SIZE -jar renamed.jar
さらに、Tomcatでのパッケージ展開の例
FROM Tomcat7
ADD sample.war ${CATALINA_HOME}/webapps/ROOT.war
CMD ${CATALINA_HOME}/bin/catalina.sh run
イメージとしてのdockerfilesの構築
cp Tomcat.dockerfile /workingdir/Dockerfile
docker build -t name /workingdir/Dockerfile .
リスト画像
docker images
画像を使用してコンテナを作成する
docker run --name cont_name --extra-vars var1=val1 var2=val2 imagename
dockerfileを作成せずに、Jibツールを使用してJavaアプリケーションをコンテナ化します
Jibは、JavaアプリケーションのDockerイメージを構築するためにGoogleが管理するオープンソースJavaツールです。これにより、コンテナ化が簡素化されます。、dockerfileを記述する必要がないためです。そして実際には、自分でドッカー画像を作成して公開するためにドッカーをインストールする必要さえありません。
GoogleはJibをMavenとGradleの両方のプラグインとして公開しています。 https://github.com/GoogleContainerTools/jib
Mavenプロジェクトを使用してJavaアプリケーションをコンテナー化する
https://github.com/GoogleContainerTools/jib/tree/master/jib-maven-plugin#quickstart
Gradleプロジェクトを使用してJavaアプリケーションをコンテナー化する
https://github.com/GoogleContainerTools/jib/tree/master/jib-gradle-plugin#quickstart
ここ 開発環境でどのように行うかを説明します。
それが役に立てば幸い。