Docker Imageについて軽くまとめてみた

6 min read読了の目安(約6000字

Docker Imageとは

一言で表現すると、環境のスナップショットのことです。その仕組みを最初に軽く解説していきます。

Docker imageは抽象的なイメージレイヤの集まりです。一つ一つのイメージレイヤはファイルシステムのディレクトリやファイルを持っています。複数のファイルシステムのディレクトリやファイルをレイヤとして重ねて、一つの仮想的なファイルシステムとして扱う技術をユニオンファイルシステムと言います。Dockerはこの技術を採用しています。

また、コンテナ上の読み書き可能なレイヤをコンテナレイヤ、読み込み専用(書き込み不可)のレイヤをイメージレイヤと呼びます。上位のイメージレイヤは下位のファイルシステムを参照することができます。なので、ユーザーはあたかも一つのファイルシステムを動かすように操作することができます。

また、イメージレイヤはファイルシステムの他にメタ情報も持っています。メタ情報の例は下記のとおり。

  • アプリケーションの実行コマンド
  • 公開するポート番号
  • ボリューム領域

Docker Imageはファイルシステムといくつかのメタ情報を保持していることがわかりました。では、実際にイメージを手元で色々動かしてみましょう!

イメージを手元に落としてくる

今回は公開docker-hubに公開されているhello-worldイメージを手元にダウンロードしてみます。下記のコマンドを実行します。

ターミナル
$ docker pull hello-world

# 以下ログ
Using default tag: latest
latest: Pulling from library/hello-world
b8dfde127a29: Pull complete 
Digest: sha256:f2266cbfc127c960fd30e76b7c792dc23b588c0db76233517e1891a4e357d519
Status: Downloaded newer image for hello-world:latest
docker.io/library/hello-world:latest

それぞれのログを解説していきます。

latest: Pulling from library/hello-world

Dockerイメージにはタグという概念があります。主に、バージョン管理に対して使われます。特にバージョンを指定しない場合はlatestが指定されます。
例えば、rubyのページを見てみると様々なバージョンが公開されているのが確認できます。

例えば、ruby2.7.3を使いたい場合はruby:2.7.3のように指定すればOK。

latest: Pulling from library/hello-world

libraryという名前空間が付与されています。ちなみにこのlibraryDocker公式の名前空間です。docker pull時に特に指定がなければ、libraryからイメージがダウンロードされます。

b8dfde127a29: Pull complete 

b8dfde127a29というイメージレイヤのダウンロード状況です。レイヤの数だけログが流れます。

Digest: sha256:f2266cbfc127c960fd30e76b7c792dc23b588c0db76233517e1891a4e357d519

hello-worldイメージのハッシュ値です。

Status: Downloaded newer image for hello-world:latest

新しくイメージがダウンロードされました、というステータスが表示されています。

docker.io/library/hello-world:latest

ダウンロードされたイメージのまとめ情報的なやつです。

  • docker.ioDocker hubのことです。
  • library:名前空間です。レポジトリのこと。
  • hello-world:イメージ名
  • latest:バージョン

イメージを調べてみる

ローカルで保持しているイメージを確認してみます。コマンドはdocker imagesです。(余談ですが、イメージの内容が変更されていない場合、CREATEDの値は変わらないみたいですね。)

$ docker images
REPOSITORY       TAG       IMAGE ID       CREATED         SIZE
hello-world      latest    d1165f221234   2 months ago    13.3kB

次にイメージの詳細情報を見てみます。コマンドはdocker inspectです。

$ docker inspect hello-world
[
    {
        "Id": "sha256:d1165f2212346b2bab48cb01c1e39ee8ad1be46b87873d9ca7a4e434980a7726",
        "RepoTags": [
            "hello-world:latest"
        ],
        "RepoDigests": [
            "hello-world@sha256:f2266cbfc127c960fd30e76b7c792dc23b588c0db76233517e1891a4e357d519"
        ],
        "Parent": "",
        "Comment": "",
        "Created": "2021-03-05T23:25:25.230064203Z",
        "Container": "f5a78ef54769bb8490754e9e063a89f90cc8eee6a6c5a0a72655826e99df116e",
        "ContainerConfig": {
            "Hostname": "f5a78ef54769",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/bin/sh",
                "-c",
                "#(nop) ",
                "CMD [\"/hello\"]"
            ],
            "Image": "sha256:77fe0a37fa6ce641a004815f2761a9042618557d253f312cd3da61780e372c8f",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": {}
        },
        "DockerVersion": "19.03.12",
        "Author": "",
        "Config": {
            "Hostname": "",
            "Domainname": "",
            "User": "",
            "AttachStdin": false,
            "AttachStdout": false,
            "AttachStderr": false,
            "Tty": false,
            "OpenStdin": false,
            "StdinOnce": false,
            "Env": [
                "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
            ],
            "Cmd": [
                "/hello"
            ],
            "Image": "sha256:77fe0a37fa6ce641a004815f2761a9042618557d253f312cd3da61780e372c8f",
            "Volumes": null,
            "WorkingDir": "",
            "Entrypoint": null,
            "OnBuild": null,
            "Labels": null
        },
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 13336,
        "VirtualSize": 13336,
        "GraphDriver": {
            "Data": {
                "MergedDir": "/var/lib/docker/overlay2/5e42fdb1504fe6bea14a7085d37f2af1e3ef677706beb17e59d8e3fa59693e7f/merged",
                "UpperDir": "/var/lib/docker/overlay2/5e42fdb1504fe6bea14a7085d37f2af1e3ef677706beb17e59d8e3fa59693e7f/diff",
                "WorkDir": "/var/lib/docker/overlay2/5e42fdb1504fe6bea14a7085d37f2af1e3ef677706beb17e59d8e3fa59693e7f/work"
            },
            "Name": "overlay2"
        },
        "RootFS": {
            "Type": "layers",
            "Layers": [
                "sha256:f22b99068db93900abe17f7f5e09ec775c2826ecfe9db961fea68293744144bd"
            ]
        },
        "Metadata": {
            "LastTagTime": "0001-01-01T00:00:00Z"
        }
    }
]

長いのでかいつまんで解説していきます。

  • Id

イメージIDです。

  • RepoTags

イメージ名:タグの形式で表現されます。今回の場合だと、hello-world:latest

  • RepoDigests

イメージ内容のハッシュ値です。

  • Parent

親イメージです。依存関係のあるイメージがある場合はここに記述されます。

"ContainerConfig": {
  # 略
  "Env": [
     "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
   ],
   # 略

環境変数です。

"Cmd": [
  "/bin/sh",
  "-c",
  "#(nop) ",
  "CMD [\"/hello\"]"

コンテナ実行時に引数が指定してなければ、このコマンドが実行されます。

まとめ

ここまで、Dockerイメージの実態とその中身を軽く解説してきました。

【参考】