Dockerの概要、仕組み、および実装について

Created on 2018-05-08
Modified on 2019-02-26
Published on 2018-05-10


この資料で解説しているDockerのバージョンは、Docker v18.03.1-ce (moby/moby@05c751b1be6785b4f8a42c412e858508b137c10e)です。

Overview

Dockerのバージョン番号からDocker engineのcommit IDを得る

  1. docker/docker-ceのbranchやtagを手がかりに、目的のバージョンをチェックアウトする。
  2. commit logをさかのぼり、 Merge component 'engine' from から始まるmerge commitを探す。
  3. このコミットの、merge元のツリーの最後のコミットのコミットメッセージを確認する。 コミットメッセージに Upstream-commit: から始まる行を探す。

もっといい方法が知りたい。

Dockerとは

コンテナ管理システムの実装の1つ。 Dockerのcore部分をコンポーネント化をするmoby projectが進められている。 ソフトウェアの名称はdockerだけど、ソースコードはmoby projectをベースにしたものが使われている。

Docker Update Channels

deprecatedなchannelを除けば、3つのchannelが存在する。

Container

広義の意味では、ホストから隔離されたプロセスの実行環境のこと。 コンテナの種類は下記の通り。

隔離されるリソースの例:

Docker Container

Security

File System

Life Cycle

so0kさんが書いた図: https://github.com/docker-saigon/blog-hugo/blob/9a36cb4df96f7e036405a0dd384c40b0df6ac4aa/static/img/event_state.png

Docker以外のコンテナ

Docker Image (Data Format)

Docker Image Specification v1.2.0 に準拠したtarballのこと。

NOTE: 2種類のDocker Image

一般にDocker Imageと呼ばれるのは2種類ある。

1つは /var/lib/docker/image/*/の下に 展開された状態のDocker Image のことである。 docker image lsを実行されたときに表示されるのがこれに相当する。 この状態のDocker Imageの扱われ方は、使用するStorage Driver (Graph Driverとも呼ぶ)によって異なる。 詳細はStorage Driverの項目で解説する。

もう1つは、 データフォーマットとしてのDocker Image である。 docker image exportしたときに出力されるのが、これに相当する。 本項で解説するのは、データフォーマットしてのDocker Imageを解説する。

含まれるデータ

Layer

root filesystemへ加えられた変更のまとまり。 具体的には、ファイル・ディレクトリの追加・更新・削除や、属性の変更などが記録される。 メタデータは含まない。

4種類のID

Tarballの中身

./repositories
./manifest.json
./${IMAGE_ID}.json
./${LAYER_ID}/layer.tar
./${LAYER_ID}/json
./${LAYER_ID}/VERSION

layer.tar

$ tar tf ${LAYER_ID}/layer.tar
root/
root/new_file
root/new_empty_directory/
root/.wh.deleted_file
root/.wh.deleted_directory

Layer Diff IDの同一性保証の仕方

tarは、ファイルの格納順序は任意である。 そのため、同じdirectory treeを記録しているのに、出力されたtarballのhash値が異なるという問題が発生しうる。

Dockerでは、格納順序をファイル名順にする(tar --sort=nameに相当)ことでこの問題を回避している [0] [1] [2]

Docker Volume

Docker Engine

Docker Engine Managed Plugin

参考: Managed plugin system

Docker Engine API

参考: Docker Engine API and SDKs

Storage Drivers (Graph Drivers)

参考: Docker storage drivers

Docker v18.03.1-ce の時点で使えそうなドライバの一覧。 ドキュメントに乗ってないドライバーがありますね。

$ ag 'graphdriver\.Register'
daemon/graphdriver/aufs/aufs.go
67:     graphdriver.Register("aufs", Init)

daemon/graphdriver/btrfs/btrfs.go
41:     graphdriver.Register("btrfs", Init)

daemon/graphdriver/devmapper/driver.go
25:     graphdriver.Register("devicemapper", Init)

daemon/graphdriver/overlay/overlay.go
109:    graphdriver.Register("overlay", Init)

daemon/graphdriver/overlay2/overlay.go
116:    graphdriver.Register(driverName, Init)

daemon/graphdriver/vfs/driver.go
23:     graphdriver.Register("vfs", Init)

daemon/graphdriver/windows/windows.go
57:     graphdriver.Register("windowsfilter", InitFilter)

daemon/graphdriver/zfs/zfs.go
32:     graphdriver.Register("zfs", Init)

daemon/graphdriver/lcow/lcow.go
85:     graphdriver.Register("lcow", InitDriver)

copy

Storage Driverではない。 DirCopy()を提供するだけのパッケージ。 DirCopy()は、タイムスタンプや属性を含めディレクトリ全体をコピーする関数。 cp -aコマンドに相当する動作をするはず。

これを使用しているStorage Driverは、overlayvfs

% ag github.com/docker/docker/daemon/graphdriver/copy
daemon/graphdriver/overlay/overlay.go
17:     "github.com/docker/docker/daemon/graphdriver/copy"

daemon/graphdriver/vfs/copy_linux.go
3:import "github.com/docker/docker/daemon/graphdriver/copy"

daemon/graphdriver/copy/copy.go
3:package copy // import "github.com/docker/docker/daemon/graphdriver/copy"

daemon/graphdriver/copy/copy_test.go
3:package copy // import "github.com/docker/docker/daemon/graphdriver/copy"

aufs

いつの間にか非推薦になってた [1]overlay2を使おう。

overlay2

/var/lib/docker/overlay2/以下のディレクトリ構造

./${LAYER_CACHE_ID}/diff/
./${LAYER_CACHE_ID}/work/    (optional)
./${LAYER_CACHE_ID}/link     (optional)
./${LAYER_CACHE_ID}/lower
./${LAYER_CACHE_ID}/merged/  (optional)
./l/${LINK_ID}               (symlink to "../${LAYER_CACHE_ID}/diff" directory)

操作

Overlayfsは、mount optionに少なくともlowerdir, upperdir, workdirを指定する必要がある。 https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/filesystems/overlayfs.txt

btrfs

vfs

union file systemではない。 新しいレイヤを作るときに、親レイヤーの中身を全てコピーしてくるため、実用的なパフォーマンスは出せないと思う。 commit済みのファイルへ多数の変更を加える用途で、コンテナの起動終了が少ないなら、こういうドライバでもいいかもしれない。

ドキュメントにも書いてある通り、テスト目的で使用されている。

$ ag github.com/docker/docker/daemon/graphdriver/vfs --ignore-dir daemon/graphdriver/vfs
daemon/graphdriver/register/register_vfs.go
5:      _ "github.com/docker/docker/daemon/graphdriver/vfs"

integration-cli/docker_cli_external_graphdriver_unix_test.go
16:     "github.com/docker/docker/daemon/graphdriver/vfs"

layer/layer_test.go
15:     "github.com/docker/docker/daemon/graphdriver/vfs"

lcow

Graph-driver for Linux Containers On Windows (LCOW) [1]

Windows分からん(´・ω・`)

Drivers

Volume Drivers

Log Drivers

Plugin

Docker Engine Managed Plugin Systemは、Docker Engineが稼働中にpluginの追加・削除を自由に行うことができるシステムのこと。 dockerの本体に手を加えずに、機能を追加できる!

Pluginの開発には、go-plugins-helpersを使うと良さそう。

実装

# Image/Layer/Graphdriver関連
image.Store
image.FSStoreBackend
layer.Store
layer.roLayer
layer.RWLayer
layer.MetadataStore
daemon.graphdriver.New

# networkやcontainer関連
container/container.go
daemon/container_operations.go
daemon/network/
daemon/network.go