🍣

Dockerのレイヤって知ってた?

2025/01/24に公開

Daily Blogging34日目

「Dockerのことなにも分かってなかったわ」ってなった1日でした

コンテナって何から作られると思う?

A. イメージってやつから作られるんでしょう

じゃあイメージって一体全体なんなんでしょうか?
...

イメージとは

Dockerfileから作成されるのがいわゆる「イメージ」
この「イメージ」が具体的になんなのかというと、
Dockerfile内に記述されているコマンド1つ1つの実行結果を「読み取り専用のレイヤ」として積み重ねて出来上がったもの。
サンプル↓

# ベースイメージの指定
FROM ruby:3.2

# 作業ディレクトリの設定
WORKDIR /app

# 必要なファイルをイメージにコピー
COPY Gemfile Gemfile.lock ./

# 必要なパッケージのインストール
RUN bundle install

# アプリケーション全体をコピー
COPY . .

# コンテナ起動時に実行するコマンドを指定
CMD ["ruby", "app.rb"]

コンテナはこの「読み取り専用レイヤ」から作られる
コンテナが作られる時は、このレイヤの上に「書き込み専用レイヤ」も作成され、コンテナ自体の変更はこっちに書き足されていくらしい

命令の書く順番によってパフォーマンスが変わる

命令文ごとに作られる「読み取り専用レイヤ」は実はキャッシュされている
なので、コンテナをもう一回作る時はこのキャッシュされたレイヤが使われるので、高速化されるらしい

ただし、キャッシュされたものは常に再利用されるわけではなく、下記の条件が満たされたときだけ再利用される

  • 命令文に変更がない
    • コマンドが全く変わってない
  • 命令文に対する入力データに変更がない
    • COPYするディレクトリやファイルに変更がない

キャッシュが利用されない時の注意点は、キャッシュが再利用できないレイヤ以降のレイヤは全部もう一度命令文が実行されるということ
例えばこういうDockerfileがあったとして

# ベースイメージの指定
FROM ruby:3.2
# 作業ディレクトリの設定
WORKDIR /app
# アプリケーション全体をコピー
COPY . .
# 必要なパッケージのインストール
RUN bundle install

COPYでプロジェクトのファイルを全部コピーするときに、1ファイルでも変更があった場合は、COPY以降のレイヤの命令文が再度実行されることになる
本来はbundle installをもう一回実行しなくても良いのに、全然関係ないファイルで変更があったときにもう一回installが実行されてしまい、非効率になる

レイヤの確認もできるよ

docker history <image name>でレイヤの確認ができるっぽい

まとめ

公式サイトの説明が結局わかりやすい
https://docs.docker.jp/build/guide/layers.html#

Discussion