レイヤー(コンテナ)
コンテナのルートファイルシステムを構成するための変更差分のこと。Dockerfileの命令の一つ一つがレイヤーを作成している。
まずは以下のDockerFileをご覧ください。
FROM ubuntu:20.04
COPY ./hello.sh /hello.sh
CMD [ "/hello.sh" ]
初めの一行ではFROMでベースとなるコンテナイメージを指定していて、これをベースレイヤー(親レイヤー)という。次の行ではカレントディレクトリ配下にある./hello.shをコンテナ内の/hello.shにコピーしている。これを子レイヤーという。このように、DockerFileの命令1つ1つがレイヤーとなり、これらを積み重ねることでコンテナイメージが作成される。
上記の2つのレイヤーは読み込み専用のレイヤーであるのに対し、最後の行のCMDはコンテナレイヤーと呼ばれる読み書き可能レイヤーであり、コンテナイメージには含まれない。読み込み専用のレイヤーと読み書き可能なレイヤーを区別することで、同じホスト上で同じコンテナイメージから生成されるコンテナであっても、互いに干渉せずリソースを使用することが出来る。
参考サイト
Dockerコンテナのレイヤ構造とは? #Docker – Qiita
Dockerfileを理解して書きたくてレイヤ構造を拝んできた忘備録 #Docker – Qiita
Docker~初心者向けにコンテナの概念について~ – JBS Tech Blog
マルチステージビルド
段階を分けてイメージのビルドを行うことができる機能。
# ビルドステージ
FROM node:14 AS builder
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
# 実行ステージ
FROM node:14-alpine
COPY --from=builder /app/dist /app
CMD ["node", "app.js"]
このように、ビルドステージでnpm install, npm run buildしているが、この結果吐き出されるファイルのすべてが欲しいわけではなく、/app/distだけが欲しい。その場合、上記のようにDockerFileを書けば、npm install, npm run buildはビルドステージにて行い、そこで生成された/app/distのみを本命のコンテナイメージに含めるという芸当が可能となる。
Dockerfile内での直前のステージだけではなく 別のイメージからコピーすることも可能。
参考サイト
マルチステージビルドについて調べる
マルチステージ — Docker-docs-ja 24.0 ドキュメント
ユニオンファイルシステム(UnionFS)
同一のディレクトリから複数のディスクをマウントして1つのディレクトリとして透過的に扱うことができるようにするマウント方法を用いているファイルシステム。
通常のマウントではすでにディスクをマウントしているディレクトリ(マウントポイント)に別のディスクをマウントすると元々マウントされていたディスクの中身は参照できなくなるのが普通だが、Unionマウントという方法でマウントすることで、どちらのディスクも参照することができる。
マウントの方法は階層的であり、新たなファイルが作成される場合や、別の階層に同名のファイルが存在し、そのファイルに対して書き込み操作をする場合、より上位のディスクに対して更新操作が行われる。
参考サイト
dockerが使うUnionFileSystemを僕なりに解釈した – See the Elephant
UnionFS で Docker のレイヤ構造を理解する – Carpe Diem
アーキテクチャの理解 — Docker-docs-ja 1.9.0b ドキュメント
コピーオンライト(Copy on Write)
コピーオンライト(copy-on-write; CoW)は、ファイルの共有とコピーを最も効率よく行う方式です。 イメージ内の下の方にあるレイヤに、ファイルやディレクトリが存在していた場合に、別のレイヤ(書き込みレイヤを含む)からの読み込みアクセスが必要であるとします。 このときには、当然のことながら存在しているそのファイルを利用します。 そのファイルを修正する必要のある別のレイヤがあったとすると、これを初めて修正するとき(イメージがビルドされたときやコンテナが起動したときなど)、そのファイルはレイヤにコピーされた上で修正されます。
イメージ、コンテナ、ストレージ・ドライバについて — Docker-docs-ja 17.06 ドキュメント
何をゆうとんのや。(この文だけで理解できる人は天才ですおめでとうございます。)
一言でいうと、コンテナ内に書き込み操作が発生するときに初めて読み込みレイヤーのデータを書き込みレイヤーにコピーする、である。
コンテナは「レイヤー(コンテナ)」の項目で説明したように、下位に他のコンテナとも共有する読み込みレイヤーと、その上位に読み書きレイヤー(コンテナレイヤ―)が存在する。コピーオンライトは、この共有する読み込みレイヤーに対して新たな書き込み操作をするときの動作についての説明をしている。共有する読み込みレイヤーは当然書き込みができない。そのため、共有する読み込みレイヤーに対して書き込み操作をしたい場合は、その内容を読み書きレイヤー(コンテナレイヤ―)にコピーして、そのコピーに対して変更操作を行う。このように、書き込み操作をするときに初めて内容をコピーすることをコピーオンライトと呼ぶ。
参考サイト
dockerが使うUnionFileSystemを僕なりに解釈した – See the Elephant
containerd
シンプルさ、堅牢性、および移植性に重点を置いた業界標準の高レベルのContainer Runtimeのこと。ここでいう高レベルとは、ハードから離れているという意味の高レベルである。
dockerはcontainerdに対して命令を出し、containerdが低レベルのContainer Runtime(runCなど)に対して命令を出すことでコンテナが作成される。以前はkubernetesはdockerを介してcontainerdに対して命令を出していたが、CRIの登場によりdockerを介さずとも直接containerdに対して命令を出すことができるようになったので、kubernetesにおいてdockerは非推奨とされている。