こんにちは、まゆみです。
Dockerについての記事をシリーズで書いています。
今回は
ビルドコンテキスト内のファイルをアップデートしたい時、アップデートする必要のないファイルがある時はどうしたら良いのか?
ということについて書いていきます。
抽象的で少しわかりにくいので、具体的に言いますね。
第8回目の記事で、ビルドコンテキスト内に『Dockerfile』『index.js』『package.json』を用意してbuild する方法をお伝えしました。
上記のような状況である時、仮に、index.jsファイルの中身のみを書き換えて、package.jsonは一番最初にbuild した時のキャッシュを利用したいという時のDockerfile の書き方を書いていきます
DockerfileからImageを作るには下記のように書く場合が多いと思います。
FROM ベースのイメージ
WORKDIR ワーキングディレクトリを指定する
COPY Containerにコピーしたいファイルを指定
RUN
このような書き方だと、その後もファイルを書き換えることはないという時は良いと思います。
ただ
①index.jsの中身を書き換えて
②再び『docker build .』する時
③Dockerfileの『COPY ./ ./』で不要なpackage.jsonまでCOPYされ、キャッシュが活用できないという事態になり、
再buildに余分な時間がかかってしまいます。
では、今回の記事の概要を伝えたところでさっそく具体的に解説していきます
#今回使うファイル
ポートマッピングをして、localhost:8080にアクセスすると、『こんにちは』と表示してくれるアプリを作りました。
うまく行っています。
ではindex.jsの中の『こんにちは』というテキストを『さようなら』に変えてみます
index.jsを保存し、localhost:8080をリロードしましたが、ファイルの変更は反映されず、表示は『こんにちは』のままです
これは、Imageを再び作りなおす必要があります
このままDockerfile を書き換えないで、一からbuild してみました。
localhost:8080をリロードすると、『さようなら』に書き換えられましたが、『COPY ./ ./』の時点で、COPYする必要のないpackage.jsonまでCOPYされ、step 3 以降のプロセスもキャッシュが活用されず、全て一から作りなおされているのが分かると思います
index.jsのたった1行を書き換えただけなのに、最初にbuildした時のキャッシュを活用できないのは、嫌ですよね。
#解決方法
では、やっと本題に入ります。
rebuildした時に、書き換えた部分のみ上書きして他の部分は最初にbuildした時のキャッシュを活用するようにDockerfileを書き換えてみます
FROM node:alpine
WORKDIR /usr/app
COPY ./package.json ./
RUN npm install
COPY ./ ./
CMD ["npm", "start"]
上記のコードを解説します
まず
3行目に
COPY ./package.json ./
とありますが、4行目でnpmをインストールするとき、package.jsonは必要なファイルなので『そのファイルのみ』は最初にCOPYしておきます
そして
RUN npm install
でnpmをインストールした後、package.json以外にも必要なファイルも『含めてすべて』COPYします。
ただその後、ファイルを書き換えてImageをrebuildする必要が出てきた場合も、
FROM node:alpine
WORKDIR /usr/app
COPY ./package.json ./
RUN npm install
上記のプロセスは、前回にbuildをした時のキャッシュが活用できるようになるのです。
COPY ./ ./
CMD ["npm", "start"]
上記の2行分のみのプロセスが作り替えられることになります
この解決法のDockerfileを使って、Imageをbuildして、index.jsの一行を書き換え、再びbuildしてみましょう
実行結果は上記のようになります。
step 5 の『COPY ./ ./』までは全て
Using cache
と書かれていて、キャッシュが活用されているのが分かります
#今回わかったこと
Docker Image が作られる時、stepごとにベースイメージに変更が加えられながら作られていきます
その後ファイルに変更が加えられ、rebuildする時、例えばstep 4で変更があれば、それ以降のプロセスは全て新しく作り直されることになります
Dockerfileの書き方によっては、rebuildの際、本来ならキャッシュを活用すべきところも、新しく作りなおされる場合もあるので、最初にDockerfile を書く時点で、あとのことも考慮に入れながら書くと良いと思います。
今回の記事は、ここで締めくくらせていただきますね。
お役に立てれば嬉しいです。