Fix: [Dockerfile] ビルド時にキャッシュが効くよう構成変更 #8
Merged
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
変更の種類
チェックリスト:
※コーディング規約にDockerfileについて記載がないためチェックをつけていません。.editorconfigは守れてるはずです。
説明
ちょっとDockerfileの書き方解説のような部分もあるので長くなります。変更点は大きく以下の3点です。
元の
Dockerfile
ではADD ./ /code
が最初の方にあるため、ソースコード全体のどこかが変更されただけでそれ以降のレイヤーキャッシュが無効になっていました。また、ダウンロード&展開のためにaria2やxzなどサーバの実行に必要のないツールがインストールされていました。Docker イメージはADD とか RUN のコマンドごとにレイヤーが構成されるため、あとで削除しても全体のイメージサイズは削減できません。そこで、1. のマルチステージビルドを導入し、ダウンロード&展開は別ステージのイメージで行い、成果物だけを最終的な実行イメージにコピーする形にしました。3. で追加したクライアントのビルドも、node.jsなどを別ステージのイメージでインストール(というかベースイメージから取ってきてますけど)しているので、最終的な実行イメージには.htmlや.jsなどの必要なもの以外含まれません。ちなみに、マルチステージビルドになっていると、buildx をインストールすることで並列ビルドをすることもできます(各ステージを並列にビルドしていく)。
また、2. の構成順序の変更というのは、docker build するとき、Dockerfile の上から順に見ていって、以前ビルドしたことがあるコマンドだけの場合(COPY/ADDの場合はコピーされるファイルに変更がない場合)、以前ビルドした際のレイヤーを使いまわします(レイヤーキャッシュ)。基本的には変更されにくいものを上に、変更されやすいものを下に書いていくと良いです。
例えば、ダウンロードではAMDのライブラリはそれほど更新されないですが、サードパーティライブラリはリリースごとには更新されます。なので、AMDのライブラリが先に処理するように変更しました。
また、
yarn
コマンドによるnode_modules
の作成やpipenv sync
などでインストールされる依存ライブラリが変更になることはアプリケーションの更新に比べて頻度が低いはずです。そこで、依存パッケージ管理に使われるファイル(Pipfile, Pipfile.lock, package.json, yarn.lock)だけをCOPYし、依存パッケージのインストールを行い、その後あらためてアプリケーション全体のコピーを行っています。動機とコンテキスト
既存の Dockerfile ではビルド時のレイヤーキャッシュが効かないような書き方になっており、コードの変更がある度に
docker build
で各種ダウンロードなどが走って非効率的であったため、改善した。また、client ディレクトリ以下が事前に
yarn build
してあることが前提になっており、更新忘れが発生する可能性があったので、docker 内でクライアントもビルドするようにした。