はじめに
概要
Dokcerにはストレージドライバという仕組みが存在します。
このストレージドライバとは何か?どんな要素が含まれているのかを紐解くことで、Dockerイメージがどのように構築されていくのかを見ていきたいと思います。
記事の目的
Dockerイメージにおけるストレージドライバを理解してDockerfileからコンテナを実行するまでの仕組みを理解する。
具体的に
ストレージドライバとは
Dockerのストレージドライバは、Dockerコンテナのイメージ、レイヤ、および書き込み可能なコンテナレイヤを管理するためのメカニズムです。ストレージドライバは、イメージとコンテナのデータを効率的に保存し、複数のコンテナ間で共有されるレイヤを効果的にキャッシュする役割を果たします。Dockerには、overlay2、aufs、devicemapper、btrfs、zfs、vfsなどの複数のストレージドライバがあります。
書籍やwiki的なもので調べるとこんな感じの説明が書かれています。
全く分かりません。。。
レイヤ?書き込み可能なコンテナレイヤ?overlay2?
ちんぷんかんぷんです。
何が分からなかったのか
それでは、私が理解できていなかった部分について紹介していきます。
今までDockerをなんとなく使用していましたが、私の中の感覚としては図のように
Dockerfileを元にDockerイメージを構築して、それを実行するとコンテナが出来上がる。
こんな認識をしていました。
しかし、ずっと引っ掛かっていたのが、Dockerイメージって本当に必要なの?Dockerfileが設計書ならコンテナが完成品でイメージはなんのために存在しているの?と感じていました。
Dockerイメージのレイヤの概念
その答えが今回のストレージドライバで管理される「レイヤ」でした。
このレイヤという考え方を取り入れることでDockerイメージの必要性が見えてきました。
それではレイヤを取り入れた図を見てみましょう。
Dockerイメージはこのように複数のレイヤが積み上がって構成されています。
下から
- ベースレイヤ
- 中間レイヤ
- 最上位レイヤ
- 書き込み可能レイヤ
です。
DokcerイメージではDockerfileで記述されたOSやパッケージ、開発者の作成したディレクトリ、コードのファイルなどを一つずつ層として積み上げていくことでDockerイメージを構築しています。
Dockerfileから作られる各レイヤ
ではDockerfileの中身を見て、Dockerイメージの各レイヤを確認しましょう。
例として、pythonをベースにFlaskをインストールして簡単なウェブアプリを作成する例を見てみましょう。
#ベースレイヤ
FROM python:3.9
# 最上位レイヤ
WORKDIR /app
# 最上位レイヤ
COPY requirements.txt .
# 中間レイヤ
RUN pip install --no-cache-dir -r requirements.txt
# 最上位レイヤ
COPY . .
# 最上位レイヤ(読み取り専用)
CMD ["flask", "run", "--host=0.0.0.0"]
図ではベースレイヤから順番にレイヤを積み上げていますが、実際はレイヤを効率的に構築するために最も最適な順番で実行されるようです。
ベースレイヤ
python3.9のインストールされたOSを構築します。
中間レイヤ
requirements.txtに記載されたフレームワークやライブラリをインストールします。ここではflaskをインストールしています。
最上位レイヤ
コンテナ内の作業用ディレクトリを作成したり、ローカル環境のディレクトリ、ファイルをコピーしたりしています。
最後のCMD
により実行されるコマンドは一旦、最上位レイヤに読み取り専用として登録されます。
その後、コンテナを起動する際に書き込み可能レイヤにて登録されたコードを実行します。
書き込み可能レイヤについて
これはDockerイメージとしてベースレイヤ〜最上位レイヤまでを組み上げた上に、コンテナとして実行した際に必要な書き込み領域として積み上げられます。
どういうことかいいますと、
立ち上がったコンテナ内に入りファイルを生成したり、データベースへデータを登録するという作業が発生するかと思います。
それらの作業により生成されたデータを格納する領域として書き込み可能レイヤというものが存在します。
それ以外に、docker-composeによりvolumeを作成する場合などもこちらを使用します。
この書き込み可能レイヤを取り外し可能な状態にすることでvolumeとしてコンテナからデータを切り離すことができるのです。
ストレージドライバのメリット
ではストレージドライバによりレイヤの構成を取ることのメリットをご紹介します。
- 他のコンテナで同じレイヤは使い回せる
- Dockerfileの変更を差分のみコンテナに反映させられる
- 各層を一つのコンポーネントとしているので環境による差異がない
これらはストレージドライバのメリットでありコンテナを使うメリットでもあるかと思います。
各レイヤを分離させることで、使い回しや変更箇所の更新などが容易となります。
一度作成したDockerイメージというのはローカル環境に保存されます。そのため、
上記のDockerfileを例にすると、他にpythonとflaskを使ったコンテナを立ち上げる際は同じベースレイヤをのイメージを使い回すことでコンテナの起動速度を上げることが可能です。
DockerHubなどからのイメージ取得
DockerHubなどからDockerイメージを取得する際は、誰か(公式など)が作成したDockerイメージをベースレイヤとしてローカルストレージへ取り込み、そこに自分の作成したい環境をレイヤとして追加していくというフローになります。
逆に自分が作成したDockerイメージをDockerHubに上げると、他の人が使う際はベースレイヤとして使用することになります。
結局ストレージドライバって何?
ここで最初に戻りますが、
ストレージドライバとは、Dockerイメージをレイヤという構造を用いて管理する仕組みのことを言います。初めに出てきたと”orverlay2”や”aufs”いうのはストレージドライバの種類です。
現在はほとんどorverlay2というのが主流だそうです。これはDockerエンジンをインストールするホストOSのファイルシステムの影響を受けるそうです。
この辺はまだ勉強不足なので引き続き勉強します。
まとめ
Dockerイメージについてモヤモヤしていたことが解消しました。
しかし、Dockerを動かすホストOSのことやファイルシステムについの要件など、調べれば調べるほど分からないことが増えます。
なんとなく使ってきたDockerを基礎から理解できる良い機会なので、本を読みながら勉強を続けたいと思います。