はじめに
Dockerを使う時にイメージビルド時間がかかることに気づき、作成されたコンテイナーが本当に良いかみたいな疑問がありますか。
この度、セキュリティーの攻撃を防ぎ、Dockerのイメージビルドプロセスを最適化する方法を調べてみます。
良いDockerfileを書くためのベストプラクティス
1. /.dockerignoreファイルを使う
最善の方法は、Dockerfileを空のディレクトリ内に配置し、Dockerイメージの構築に必要なアプリケーションファイルと構成ファイルのみを追加することです。
ビルドのパフォーマンスを向上させるために、.dockerignoreファイルをそのディレクトリに追加することで、ファイルとディレクトリを除外することもできます。
2. 不要なパッケージをインストールしないように
Dockerイメージはできれば、無駄が無い状態を維持する必要です。移植性、ビルド時間が減ったり、複雑にならなくなったり、コンテイナーのサイズを小さくすることが出来ます。 たとえば、ほとんどの場合、コンテナにテキストエディタをインストールする必要はありません。 必須ではないアプリケーションやサービスをインストールしないでください。
3. レイヤー数を最小化する
Dockerfileの各コマンドは、Dockerイメージに該当のレイヤーを追加します。 コマンドとレイヤーの数は、ビルドのパフォーマンスと時間に最終的に影響するため、最小限に抑える必要があります。
4. イメージのバージョンを指定する。
Dockerイメージを使用する際にタグを指定しなかった場合にはlatest
タグが自動的に利用されます。ただ、latest
タグに関して、問題があります。基本的にはlatest
タグを指定したら、Docker のイメージリポジトリからの最新イメージバージョンに使用されますが、ローカルでキャッシュされるため、タグの更新を忘れていると差異が発生する可能性があります。
また、latestタグを指定する時にイメージのバージョンが変わる可能性があるため、イメージをリビルドすると不具合が生じる可能性があります。latestタグを利用して、イメージバージョンなどの指定的なタグを利用した方が良いです。
5. コマンドの結合:
イメージをビルドするとき、Dockerfileの各コマンドでイメージに1つのレイヤーを追加されます。
コマンドを組み合わせると、レイヤー数が減り、イメージのサイズが小さくなります。 コマンド組み合わせの一般的な例はRUNコマンドです。 複数のRUNコマンドを使用する代わりに、各コマンドを「&&」で組み合わせたほうが良いです。
RUN apt-get update
RUN apt-get install -y python3-pip
RUN cd ~
# Can be converted to
RUN apt-get update && apt-get install -y python3-pip && cd ~
6. マルチステージビルドを使用する。
マルチステージを使用することは、アプリケーションをデプロイするための推奨される方法です。
これにより、実行中のコンテナーでビルドの依存関係を使用する必要がなくなります。
依存関係を持つ一意のビルドイメージを使用してアプリケーションをビルドし、コンパイルされたバイナリを別のコンテナイメージに移動して実行できます。
マルチステージビルドには、最終的なイメージに必要な最小限のバイナリと依存関係のみが含まれ、中間コンテイナーやファイルなどをビルドする必要がありませんです。
# Stage 0, "build-stage", based on Node.js, to build and compile the frontend
FROM node:13.12.0 as build-stage
WORKDIR /app
COPY package*.json /app/
RUN npm install
COPY ./ /app/
RUN npm run build
# Stage 1, based on Nginx, to have only the compiled app, ready for production with Nginx
FROM nginx:1.15
COPY --from=build-stage /app/build/ /usr/share/nginx/html
上記では、Dockerfileには2つの別々の段階があります。
一つ目のステージは、Nodeイメージからノードアプリケーションをビルドするために使用されます。
二つ目のステージは、build-stage
をビルドイメージから最終的にアプリケーションにサービスを提供するWebサーバー(Nginx)イメージにコピーするために使用されます。
###参考した内容
- https://medium.com/@BeNitinAgarwal/best-practices-for-working-with-dockerfiles-fb2d22b78186
- https://medium.com/swlh/dockerfile-best-practices-for-building-an-image-6120e512b1fa
- https://matsuand.github.io/docs.docker.jp.onthefly/develop/develop-images/multistage-build/
- https://sysdig.com/blog/dockerfile-best-practices/