そこ100万人以上いる  Dockerfiles  GitHubの今日には、すべてではないDockerfilesが均等に作成されます。効率性が重要であり、このブログのシリーズは、あなたがより良いDockerfiles書くためDockerfileベストプラクティスのための5つの分野をカバーします:インクリメンタルビルド時、画像サイズ、保守性、セキュリティ、および再現性を。あなただけドッカーで始まる場合は、この最初のブログ記事はあなたです!シリーズの次のポストは、より高度になります。

重要な注意:以下のヒントは、Mavenのに基づいて、例えば、Javaプロジェクトのために絶えず向上Dockerfilesの旅に従ってください。すべての中間のものは、特定のベスト・プラクティスを説明するためにのみ存在している間Thelast Dockerfileは、これをお勧めDockerfileです。

インクリメンタルビルド時間

ドッカーイメージを構築するときに、開発サイクルでは、コードの変更を行うこと、そして再構築、キャッシュを活用することが重要です。キャッシングは、彼らがする必要がない場合、再び手順を構築し実行しないようにできます。

ヒント#1:キャッシュ用の注文事項

ステップのキャッシュがファイルを変更したり、Dockerfile内の行を変更することで無効化されたときしかし、ビルド手順(Dockerfile命令)事項の順序は、そのキャッシュのその後の工程は解除されます。少なくともから最も頻繁にキャッシュを最適化するための手順を変更するには、あなたの手順を注文。

ヒント#2:キャッシュ胸像を制限するためのより具体的なCOPY

のみ必要なものをコピーします。可能であれば、あなたのイメージにファイルをコピーする場合、「COPY」を避けるあなたがコピーしたいかについて非常に特定であることを確認してください。コピーされたファイルへの変更は、キャッシュが壊れます。上記の例では、唯一の事前に構築されたジャーアプリケーションは、画像の内部で必要とされるので、それだけをコピーします。そのように無関係なファイルの変更は、キャッシュには影響しません。

ヒント#3:アップデート&インストールし、このようなapt-getのようにキャッシュ可能なユニットを識別

Each RUN instruction can be seen as a cacheable unit of execution. Too many of them can be unnecessary, while chaining all commands into one RUN instruction can bust the cache easily, hurting the development cycle. When installing packages from package managers, you always want to update the index and install packages in the same RUN: they form together one cacheable unit. Otherwise you risk installing outdated packages.

Reduce Image size

Image size can be important because smaller images equal faster deployments and a smaller attack surface.

Tip #4: Remove unnecessary dependencies

Remove unnecessary dependencies and do not install debugging tools. If needed debugging tools can always be installed later. Certain package managers such as apt, automatically install packages that are recommended by the user-specified package, unnecessarily increasing the footprint. Apt has the –no-install-recommends flag which ensures that dependencies that were not actually needed are not installed. If they are needed, add them explicitly.

Tip #5: Remove package manager cache

Package managers maintain their own cache which may end up in the image. One way to deal with it is to remove the cache in the same RUN instruction that installed packages. Removing it in another RUN instruction would not reduce the image size.

There are further ways to reduce image size such as multi-stage builds which will be covered at the end of this blog post. The next set of best practices will look at how we can optimize for maintainability, security, and repeatability of the Dockerfile.

Maintainability

Tip #6: Use official images when possible

Official images can save a lot of time spent on maintenance because all the installation steps are done and best practices are applied. If you have multiple projects, they can share those layers because they use exactly the same base image.

Tip #7: Use more specific tags

Do not use the latest tag. It has the convenience of always being available for official images on Docker Hub but there can be breaking changes over time. Depending on how far apart in time you rebuild the Dockerfile without cache, you may have failing builds.

Instead, use more specific tags for your base images. In this case, we’re using openjdk. There are a lot more tags available so check out the Docker Hub documentation for that image which lists all the existing variants.

Tip #8: Look for minimal flavors

Some of those tags have minimal flavors which means they are even smaller images. The slim variant is based on a stripped down Debian, while the alpine variant is based on the even smaller Alpine Linux distribution image. A notable difference is that debian still uses GNU libc while alpine uses musl libc which, although much smaller, may in some cases cause compatibility issues. In the case of openjdk, the jre flavor only contains the java runtime, not the sdk; this also drastically reduces the image size.

Reproducibility

So far the Dockerfiles above have assumed that your jar artifact was built on the host. This is not ideal because you lose the benefits of the consistent environment provided by containers. For instance if your Java application depends on specific libraries it may introduce unwelcome inconsistencies depending on which computer the application is built.

Tip #9: Build from source in a consistent environment

The source code is the source of truth from which you want to build a Docker image. The Dockerfile is simply the blueprint.

You should start by identifying all that’s needed to build your application. Our simple Java application requires Maven and the JDK, so let’s base our Dockerfile off of a specific minimal official maven image from Docker Hub, that includes the JDK. If you needed to install more dependencies, you could do so in a RUN step.

The pom.xml and src folders are copied in as they are needed for the final RUN step that produces the app.jar application with mvn package. (The -e flag is to show errors and -B to run in non-interactive aka “batch” mode).

We solved the inconsistent environment problem, but introduced another one: every time the code is changed, all the dependencies described in pom.xml are fetched. Hence the next tip.

Tip #10: Fetch dependencies in a separate step

By again thinking in terms of cacheable units of execution, we can decide that fetching dependencies is a separate cacheable unit that only needs to depend on changes to pom.xml and not the source code. The RUN step between the two COPY steps tells Maven to only fetch the dependencies.

There is one more problem that got introduced by building in consistent environments: our image is way bigger than before because it includes all the build-time dependencies that are not needed at runtime.

Tip #11: Use multi-stage builds to remove build dependencies (recommended Dockerfile)

Multi-stage builds are recognizable by the multiple FROM statements. Each FROM starts a new stage. They can be named with the AS keyword which we use to name our first stage “builder” to be referenced later. It will include all our build dependencies in a consistent environment.

第二段階は、最終的な画像になります私たちの最終段階です。それは、最小限のJRE(Javaランタイム)はアルパインに基づいて、この場合には、ランタイムのために厳密に必要なを含むであろう。仲介ビルダーのステージは、キャッシュされたが、最終的な画像には存在しないことになります。私たちの最終的な画像にアーティファクトを構築得るためには、使用  COPY --from=STAGE_NAMEこの場合、STAGE_NAMEはビルダーです。

多段階ビルド行く-にソリューションビルド時の依存関係を削除することです。

我々は一貫性キャッシュフレンドリーでありながら、一貫性のある環境で最小限のイメージの構築に肥大化した画像を建物から行ってきました。次のブログ記事では、我々は、多段階のビルドの他の用途により飛び込むます。