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タグIDは変数にできる

<table id=" <%=var1%>">、var1...

数百万のデータに対して MySQL クエリを最適化する 4 つの方法

目次1. 時間が経つにつれて限界が遅くなる理由2. 百万データシミュレーション1. 従業員テーブルと...

Linuxは、単一のIPをバインドするためにデュアルネットワークカードを実装するためにボンドを使用します。サンプルコード

ネットワークの高可用性を実現するには、複数のネットワーク カードを仮想ネットワーク カードにバインド...

Windows で Nginx を使用して https サーバーとリバース プロキシを構成する際の問題

リクエストロジックフロントエンド --> https経由でnginxをリクエストnginx -...

リンク更新ページと js 更新ページの使用例

1. リンクの使用方法:コードをコピーコードは次のとおりです。 <a href="j...

LinuxにComposerをインストールする方法

1. インストールスクリプト(composer-setup.php)を現在のディレクトリにダウンロー...

Linux lnコマンドの使用

1. コマンドの紹介ln コマンドは、ファイルのリンクを作成するために使用されます。リンクは、ハード...

CentOS インストール mysql5.7 詳細チュートリアル

この記事では、参考までに、centOSにmysql5.7をインストールする詳細な手順を紹介します。具...

25 個の CSS フレームワーク、ツール、ソフトウェア、テンプレートを共有

スプライトカウダウンロード CSS リントダウンロード プレフィックスダウンロード 1140px C...

表の最初の行と最初の列を固定し、適応型ウィンドウを実現するための CSS の例コード

今日のキャンパス採用筆記試験では、固定された最初の行と最初の列を実装し、幅をウィンドウの変更に適応さ...

MySQL におけるデータタイムとタイムスタンプの違い

MySQL には 3 つの日付型があります。日付(年-月-日)テーブル test(hiredate ...

SQL実装 LeetCode (176. 2番目に高い給与)

[LeetCode] 176. 2番目に高い給与従業員テーブルから 2 番目に高い給与を取得する ...

Zabbix 5.0 ディスク自動検出と読み取り/書き込み監視の問題を分析する

ディスクを自動的に検出する構成キーの値注: このキー値は Linux プラットフォームでのみサポート...

要素 el-button ボタンコンポーネントの使用の詳細な説明

1. 背景ボタンは非常によく使われており、Element のボタン機能は非常に包括的です。この記事で...

CSSはletter-spacingプロパティを通じて単語間の間隔を制御します。

letter-spacing プロパティ: 文字間のスペース (文字間隔) を増減します。このプロ...