Dockerイメージストレージoverlayfsの使用

Dockerイメージストレージoverlayfsの使用

1. 概要

Docker のイメージはレイヤーで設計されています。各レイヤーは「レイヤー」と呼ばれます。これらのレイヤーは /var/lib/docker/<storage-driver>/ ディレクトリに保存されます。ストレージ ドライバーには、AUFS、OverlayFS、VFS、Brtfs など、さまざまな種類があります。ストレージ ドライバーは、docker info コマンドで確認できます (著者のシステムは centos7.4 です)。

通常、Ubuntu のようなシステムではデフォルトで AUFS が使用されますが、CentOS 7.1 以降のシリーズでは OverlayFS が使用されます。この記事では、ストレージ ドライバーとして OverlayFS を使用したイメージ保存の原理とストレージ構造を紹介します。

2. オーバーレイFS導入

OverlayFS は、他のファイルシステム (ext4fs や xfs など) に依存し、それらの上に構築されたスタックファイルシステムです。ディスクスペース構造の分割には直接関与しません。元の基盤となるファイルシステム内のさまざまなディレクトリを「マージ」し、ユーザーに提示するだけです。これがジョイントマウントテクノロジです。AUFS と比較すると、OverlayFS は実装が高速でシンプルです。 Linux カーネルは、Docker 用に overlay と overlay2 という 2 種類の OverlayFS ドライバーを提供します。 Overlay2 は Overlay の改良版であり、inode の使用率の点では Overlay よりも効率的です。ただし、オーバーレイには環境要件があります: Docker バージョン 17.06.02 以上、ホスト ファイル システムは ext4 または xfs 形式である必要があります。

複合マウント

Overlayfs は、下位ディレクトリ、上位ディレクトリ、作業ディレクトリの 3 つのディレクトリを通じて実装されます。下位ディレクトリは複数存在する場合があります。作業ディレクトリは基本的な作業ディレクトリです。マウント後にその内容はクリアされ、使用中にユーザーには表示されません。最後に、ジョイントマウントが完了した後にユーザーに表示される統一されたビューは、マージされたディレクトリと呼ばれます。次の mount の使用法では、それがどのように機能するかを説明します。

次の構文で mount コマンドを使用して overlayfs をマウントします。

マウント -t オーバーレイ オーバーレイ -o 下位ディレクトリ=下位1:下位2:下位3、上位ディレクトリ=上位、作業ディレクトリ=作業 マージされたディレクトリ

3 つのディレクトリ A、B、C、およびワーカー ディレクトリを作成します。

次に、マウントの組み合わせを使用して /tmp/test にマウントします。

次に、/tmp/test ディレクトリを再度確認すると、ディレクトリ A、B、C が結合され、同じファイル名のファイルが「上書き」されていることがわかります。ここでの上書きは実際の上書きではありませんが、結合中にディレクトリ内の 2 つのファイルの名前が同じである場合、結合されたレイヤー ディレクトリには最も近いファイルが表示されます。

同時に、mount コマンドを使用してマウント オプションを表示することもできます。

上記の方法はジョイントマウント技術とも呼ばれます。

Docker のオーバーレイ ドライバー

オーバーレイ ドライバーの原理を紹介した後、Docker のオーバーレイ ストレージ ドライバーを見てみましょう。以下は、Docker の公式 Web サイトに掲載されているオーバーレイの動作原理の図です。

上の図では、lowerdir、upperdir、merged の 3 つのレイヤー構造が確認できます。Lowerdir は読み取り専用のイメージ レイヤーで、実際には rootfs です。上で示したディレクトリ A と B と比較すると、イメージ レイヤーは複数のレイヤーに分割できるため、対応する lowerdir には複数のディレクトリが存在する可能性があることがわかります。 upperdir は lowerdir の上の層です。この層は読み取り/書き込み層です。コンテナの起動時に作成されます。例の C と比較すると、コンテナ データへのすべての変更はこの層で発生します。最後に、マージされたディレクトリはコンテナのマウント ポイントであり、例の /tmp/test と比較して、ユーザーに公開される統一されたパースペクティブです。これらのディレクトリ レイヤーは、/var/lib/docker/overlay2/ または /var/lib/docker/overlay/ (オーバーレイが使用されている場合) に保存されます。

デモ

コンテナを起動する

オーバーレイ マウント ポイントを確認すると、マウントされたマージされたディレクトリ、lowerdir、upperdir、workdir を見つけることができます。

overlay2 には複数の下位ディレクトリが存在する可能性があり、それらはソフト リンクとしてマウントされます。これについては後で説明します。

仕組み

コンテナ内でデータが変更された場合、overlayfs ストレージ ドライバーはどのように機能しますか?読み書きのプロセスについては、以下で説明します。

読む:

  • ファイルがコンテナ層 (upperdir) にある場合は、ファイルを直接読み取ります。
  • ファイルがコンテナ レイヤー (upperdir) にない場合は、イメージ レイヤー (lowerdir) から読み取られます。

改訂:

  • 最初の書き込み: upperdir に存在しない場合、overlay と overlay2 は copy_up 操作を実行して、ファイルを lowdir から upperdir にコピーします。overlayfs はファイル レベルであるため (ファイルにわずかな変更しか加えられていない場合でも、copy_up 動作が生成されます)、ここでの同じファイルに対する後続の書き込み操作は、コンテナーにコピーされたファイルのコピーに対して実行されます。これは、コピーオンライトと呼ばれることがよくあります。
  • ファイルとディレクトリの削除: コンテナ内でファイルが削除されると、コンテナ レイヤー (upperdir) にホワイトアウト ファイルが作成されます。イメージ レイヤー (lowerdir) 内のファイルは読み取り専用であるため削除されませんが、without ファイルによって表示されなくなります。コンテナ内でディレクトリが削除されると、コンテナ レイヤー (upperdir) に不透明なディレクトリが作成されます。これは上記のホワイトアウトの原則と同じで、イメージ レイヤーがまだ存在する場合でも、ユーザーが引き続きアクセスできないようにします。

予防

  • copy_up 操作は、ファイルが最初に書き込まれるときにのみ実行され、その後はコピーのみが変更されます。
  • Overlayfs は 2 レベルのディレクトリにのみ適用され、AUFS よりも検索が高速です。
  • コンテナ レイヤーでのファイルの削除は、ホワイトアウト ファイルで隠された単なる「煙幕」です。イメージ レイヤーは削除されません。docker commit を使用して保存されたイメージがどんどん大きくなっていくのは、このためです。コンテナ レイヤーでデータがどのように削除されても、イメージ レイヤーは変更されません。

3. Overlay2画像保存構造

リポジトリから Ubuntu イメージをプルします。結果は、次のように合計 4 層のイメージがプルされたことを示しています。

この時点で、4 つのレイヤーは /var/lib/docker/overlay2/ ディレクトリに保存されます。

すべてのレイヤーのソフト リンクを含む追加の l ディレクトリがあります。短いリンクでは、マウント時にパラメータがページ サイズの制限に達するのを避けるために短い名前を使用します (デモでマウント コマンドを表示するときの短いディレクトリ):

最下層の画像ディレクトリには、差分ファイルとリンク ファイルが含まれています。差分ディレクトリには現在のレイヤーの画像コンテンツが保存され、リンク ファイルは対応する短い名前です。

上の画像には作業ディレクトリと下位ファイルが追加されています。下位ファイルは親レイヤーの短縮名を記録するために使用され、作業ディレクトリは指定された作業ディレクトリを共同マウントするために使用されます。これらのディレクトリと画像はどのように整理されていますか?答えはメタデータの関連付けです。メタデータは、画像メタデータとレイヤーメタデータに分かれています。

画像のメタデータ

イメージのメタデータは、/var/lib/docker/image/<storage_driver>/imagedb/content/sha256/ ディレクトリに保存されます。名前は、イメージ ID にちなんで名付けられたファイルです。イメージ ID は、docker images を通じて確認できます。これらのファイルには、イメージの rootfs 情報、イメージの作成時間、ビルド履歴情報、起動エントリポイントや CMD を含む使用されたコンテナーなどが json 形式で保存されます。たとえば、ubuntu イメージの ID は 47b19964fb50 です。

対応するメタデータ (vim :%!python -m json.tool を使用して json にフォーマット) を表示し、その rootfs の構成をキャプチャします。

上記の diff_id はイメージ レイヤーに対応しており、上から下の順に並べられ、イメージ レイヤーの最下層から最上層を表します。

diff_id はレイヤーとどのように関係していますか?具体的には、docker は rootfs 内の各 diff_id と履歴情報を使用して、対応するコンテンツ アドレス可能インデックス (chainID) を計算し、chaiID をレイヤー レイヤーに関連付け、各イメージ レイヤーのイメージ ファイルに関連付けます。

レイヤーメタデータ

レイヤーはイメージ レイヤーの概念に対応します。Docker バージョン 1.10 より前では、イメージはグラフ構造を通じて管理されていました。各イメージ レイヤーには、レイヤーのビルド情報と親イメージ レイヤー ID を記録したメタデータがありました。最上位のイメージ レイヤーには、イメージ全体のメタデータとしてさらに多くの情報が記録されます。グラフは、各イメージ レイヤーに記録されたイメージ ID (つまり、最上位のイメージ レイヤー ID) と親イメージ レイヤー ID に基づいて、ツリー状のイメージ レイヤー構造を維持します。

Docker バージョン 1.10 以降、イメージ メタデータ管理における最大の変更点の 1 つは、イメージ レイヤーのメタデータが簡素化され、特定のイメージ レイヤー ファイル パッケージのみが含まれるようになったことです。ユーザーが Docker ホストに特定のイメージ レイヤーをダウンロードすると、Docker はイメージ レイヤー ファイル パッケージとイメージ メタデータ (差分、親、サイズなど) に基づいて、ホスト上にローカル レイヤー メタデータを構築します。 Docker がホスト マシン上で生成された新しいイメージ レイヤーをレジストリにアップロードする場合、新しいイメージ レイヤーに関連するホスト マシン上のメタデータはパッケージ化されず、イメージ レイヤーと一緒にアップロードされません。

Docker は、読み取り専用レイヤーと読み取り/書き込みレイヤーの一部の操作をそれぞれ定義するために使用される、Layer と RWLayer という 2 つのインターフェースを定義します。また、上記の 2 つのインターフェースをそれぞれ実装するために、roLayer と mountedLayer も定義します。このうち、roLayer は不変のイメージ層を記述するために使用され、mountedLayer は読み取りおよび書き込み可能なコンテナ層を記述するために使用されます。具体的には、roLayer に格納される内容は、主に、イメージ レイヤーをインデックスする chainID、イメージ レイヤーの検証コード diffID、親イメージ レイヤー parent、現在のイメージ レイヤー ファイルを格納する storage_driver の cacheID、イメージ レイヤーのサイズ、その他の内容が含まれます。これらのメタデータは、/var/lib/docker/image/<storage_driver>/layerdb/sha256/<chainID>/ フォルダーに保存されます。次のように:

各 chainID ディレクトリには、cache-id、diff、zize の 3 つのファイルがあります。

キャッシュIDファイル:

docker によってランダムに生成された uuid には、イメージ レイヤーのディレクトリ インデックス (/var/lib/docker/overlay2/ 内のディレクトリ) が含まれます。そのため、対応するレイヤー ディレクトリは chainID を通じて見つけることができます。チェーンIDに対応するディレクトリはd801a12f6af7beff367268f99607376584d8b2da656dcd8656973b7ad9779ab4で、これは130ea10d6f0ebfafc8ca260992c8d0bef63a1b5ca3a7d51a5cd1b1031d23efd5であり、/var/lib/docker/overlay2/130ea10d6f0ebfafc8ca260992c8d0bef63a1b5ca3a7d51a5cd1b1031d23efd5に保存されます。

差分ファイル:

イメージメタデータの diff_id が保存されます (メタデータの diff_ids の uuid に対応)

ファイルサイズ:

画像レイヤーのサイズを節約します

レイヤーのすべての属性のうち、diffID は、SHA256 アルゴリズムを使用してイメージ レイヤー ファイル パッケージの内容に基づいて計算されます。 chainID は、コンテンツ ストレージに基づくインデックスです。現在のレイヤーとすべての祖先イメージ レイヤーの diffID に基づいて計算されます。具体的な計算は次のとおりです。

  • イメージ レイヤーが最下位レイヤー (親イメージ レイヤーなし) の場合、このレイヤーの diffID は chainID になります。
  • このイメージレイヤーの chainID 計算式は、chainID(n)=SHA256(chain(n-1) diffID(n)) です。これは、親イメージレイヤーの chainID にスペースと現在のレイヤーの diffID を追加し、SHA256 チェックサムを計算します。

MountedLayer 情報に格納される読み取り可能な init レイヤーおよびコンテナ マウント ポイント情報には、コンテナ init レイヤー ID (init-id)、ジョイント マウントに使用される ID (mount-id)、およびコンテナ レイヤーの親レイヤー イメージの chainID (parent) が含まれます。関連するファイルは、/var/lib/docker/image/<storage_driver>/layerdb/mounts/<container_id>/ ディレクトリにあります。次のように、ID 3c96960b3127 のコンテナを起動します。

対応する 3 つの mountLayer ファイルを表示します。

initID は、mountID の後に -init が追加された、/var/lib/docker/overlay2/ に保存されているディレクトリの名前であることがわかります。

また、mount コマンドを使用して、対応するマウントの mountID を直接表示することもできます。これは、overlayfs によって提供されるマージされたディレクトリでもある /var/lib/docker/overlay2/ ディレクトリに対応します。

コンテナ内にファイルが作成されます:

この時点で、ホストのマージされたディレクトリ内に対応するファイルを確認できます。

初期化層について

init 層は、uuid+-init で終わる名前で表されます。読み取り専用層と読み書き可能層の間に挟まれており、/etc/hosts や /etc/resolv.conf などの情報を格納するために使用されます。この層が必要なのは、コンテナの起動時に、ホスト名などイメージ層に属するべきファイルやディレクトリをユーザーが変更する必要があるためです。ただし、イメージ層では変更できません。そのため、起動時に別の init 層をマウントし、init 層内のファイルを変更することで、これらのファイルを変更する目的を達成します。これらの変更は多くの場合、現在のコンテナでのみ有効であり、docker commit がイメージとして送信されると、init レイヤーは送信されません。このファイル層が保存されるディレクトリは /var/lib/docker/overlay2/<init_id>/diff です。

まとめ

上記の紹介により、コンテナの完全なレイヤーは、以下に示すように 3 つの部分で構成されるはずです。

  • イメージ層: rootfs とも呼ばれ、コンテナの起動用のファイルシステムを提供します。
  • init レイヤー: /etc/hostname、/etc/resolv.conf など、コンテナー内の一部のファイルを変更するために使用されます。
  • コンテナ層: ジョイントマウントを使用して、ユーザーに統一された読み取りおよび書き込み可能なディレクトリを提供します。

IV. 結論

この記事では、ストレージ ドライバーとして overlayfs を使用したイメージ ストレージの原理を紹介します。各レイヤーのイメージ データは /var/lib/docker/overlay2/<uuid>/diff ディレクトリに保存され、init レイヤー データは /var/lib/docker/overlay2/<init-id>/diff ディレクトリに保存され、統合ビュー (コンテナ レイヤー) データは /var/lib/docker/overlay2/<mount_id>/diff ディレクトリに保存されます。Docker は、イメージ メタデータとレイヤー メタデータを通じてコン​​テンツ アドレス指定 (chainID) を使用してこれらのディレクトリを整理し、コンテナ上で実行されるファイル システムを形成します。

参照:

《overlayfs ドライバーを使用する》

《Dockerイメージのストレージ管理》

以上で、Docker イメージ保存における overlayfs の利用についての説明は終了です。Docker イメージ保存における overlayfs についての詳細は、123WORDPRESS.COM の過去の記事や以下の関連記事をご覧ください。今後とも 123WORDPRESS.COM をよろしくお願いいたします。

以下もご興味があるかもしれません:
  • Docker のホスト間コンテナ通信オーバーレイ実装プロセスの詳細な説明
  • Docker クロスホストネットワーク (オーバーレイ) の実装
  • Dockerオーバーレイネットワークの構築方法
  • Docker でオーバーレイ ネットワークの実験環境を構築する
  • Dockerにおけるオーバーレイネットワークの詳細な説明

<<:  Vueを使用してタイマー機能を実装する

>>:  Vue のリスナーの基本的な使用例

推薦する

HTMLページがincludeを使用してphpファイルをインポートした後に余分な空白行があります

インターネットで見つけた方法は効果的ですinclude によって導入されたフッター ファイルとヘッダ...

CSS3はキングをマッチングさせるときにパーティクルアニメーション効果を実現します

コーディングをしていると、多くのことが同じ結末を迎えることに気づくでしょう。問題を解決する方法は何千...

CSS3アニメーション属性に基づくWeChatタップアニメーション効果の実装

最近人気のWeChatタップ機能を見て、CSS3アニメーションを見直し、このボックスシェイクアニメー...

リアクトルーティングガード(ルーティングインターセプション)の実装

React は Vue とは異なります。ルートにメタ文字を設定することでルートインターセプションを実...

Linux jdk のインストールと環境変数の設定チュートリアル (jdk-8u144-linux-x64.tar.gz)

最初にsudo suコマンドを使用して root アカウントに切り替えることをお勧めします。そうしな...

MySQLクエリデータを時間別に表示します。データがない場合は0を入力してください。

需要背景統計インターフェースでは、フロントエンドは 2 つの配列を返す必要があります。1 つは 0 ...

HTML の 5 種類のスペースの意味

HTML には、幅の異なる 5 つのスペース エンティティが用意されています。非改行スペース ( )...

Docker+Jenkinsによる自動デプロイの実現方法

Code Cloud を使用して Git コード ストレージ ウェアハウスを構築するhttps://...

MySQL の NULL 値に関する体験談と分析チュートリアルシリーズ

目次1. テストデータ2. ヌル値による不便3. スペース、空の値、null をどのように判断すれば...

Windows で MySQL のルート パスワードを忘れた場合にリセットする方法

私のマシン環境: Windows 2008 R2 MySQL 5.6 Baidu で「Windows...

W3Cチュートリアル(1):W3Cを理解する

1994 年に設立された組織である W3C は、共通プロトコルの開発を促進し、それらの相互運用性を確...

Vueはechartsに基づいて3次元の縦棒グラフを実装します

3次元縦棒グラフは、正面、右側、上部の3つの部分で構成されています。描画するときは、正面をグラフィッ...

フレックスレイアウトではサブアイテムの高さを維持できる

Flex レイアウトを使用すると、水平に配置すると、すべての子項目の高さが同じになることがわかります...

sql_mode を変更する際の MySQL エラーの解決方法

目次ERR 1067による殺人事件2番目の問題の原因はsql_modeです3. sql_modeを設...

VirtualBox Centos7 の NAT+ホストオンリーネットワークの落とし穴のまとめ

目次1. 問題の背景2. 仮想マシン ネットワーク カードの接続方法は何ですか? 2.1 NAT 2...