Skip to main content

コンテナイメージ形式の仕組み

著者
Headshot of Agata Krajewska

Agata Krajewska

2020年11月18日

0 分で読めます

ここ数年、Dockerのリリースを受けて、コンテナはソフトウェアを提供するための標準的な仕組みとして、ますます普及しています。

コンテナベースのソリューションは増え続けています。この分野のイノベーションは歓迎すべきものですが、形式とランタイムに関する一定の標準を確立する必要があります。

Dockerプロジェクトの急速な成長により、Dockerイメージは多くの用途で標準となりました。しかし、次のような単一のオープンなコンテナ仕様を求める声が広くあることは間違いありません。

  • 特定のクライアントやオーケストレーションスタックなど、上位レベルの構成要素に依存しない

  • 特定の商用ベンダーやプロジェクトと密接に結び付いていない

  • 多様なオペレーティングシステム、ハードウェア、CPUアーキテクチャ、パブリッククラウドなどで移植可能である

OCI(Open Container Initiative)は、OSレベルの仮想化、特にLinuxコンテナに関するオープン標準を策定するLinux Foundationのプロジェクトです。

Dockerは、ベースとなる形式とランタイムの仕様ドラフト、およびその仕様のリファレンス実装に関連するコードをOCIに寄贈しました。

現在、OCIイメージ形式は次のようなさまざまなオープンソースのビルドツールでサポートされています。

  • BuildKit:Dockerのビルドエンジンを最適化して書き直したもの

  • Podman:Dockerのコマンドラインツールの代替実装

  • Buildah:Dockerfileを記述する代わりに使えるコマンドラインツール

Snykは一般的なコンテナイメージ形式をすべてサポートしているため、エコシステム全体にわたる幅広いツールと連携できます。このブログ記事ではその一部を取り上げ、Snykがどのように連携するのかをご紹介します。

Dockerアーカイブ

まず、Dockerアーカイブ形式を見てみましょう。これは廃止されたDockerイメージ仕様v1の一部で、仕様の全文はこちらで確認できます。docker saveを実行すると、Dockerクライアントはデフォルトでこの形式を出力します。これは他のツールとの後方互換性のために使われます。コンテナレジストリでは、イメージの保存に新しい形式が使われています

Dockerをローカルで実行し、Snyk CLIまたはコンテナ連携機能を使用している場合、ローカルのDockerインスタンスを使ってイメージを取得し、ファイルシステムに保存してから解析を開始します。

このアーカイブの中身と、Snykにとって興味深い情報を見ていきましょう。

この記事ではubuntu:bionicイメージを使用します。まず、アーカイブをローカルのファイルシステムに保存しましょう。

docker save --output ubuntu-docker.tar ubuntu:bionic

bionicディストリビューションには3つのイメージレイヤーがあり、詳しく見ていきます。

tarアーカイブを展開したら、中身を確認できます。

[ubuntu-docker] ll                                                                                                               
total 24
drwxr-xr-x  5 agatakrajewska  staff   160B 25 Sep 23:33 46076a325f0de3f745254638b8b0f0de343685b34e7ca6ec5cd0b6b7930eb7fa
drwxr-xr-x  5 agatakrajewska  staff   160B 25 Sep 23:33 468327b5cd7ce539db695bd0ef05dae8a4ff77b02870a8e823ed74dedad4bd55
-rw-r--r--  1 agatakrajewska  staff   3.3K 25 Sep 23:33 56def654ec22f857f480cdcc640c474e2f84d4be2e549a9d16eaba3f397596e9.json
drwxr-xr-x  5 agatakrajewska  staff   160B 25 Sep 23:33 8bf067b107a6f7444876e33c6ed85652355f679ac98ebab97ab3ebad63f0dff3
-rw-r--r--  1 agatakrajewska  staff   356B  1 Jan  1970 manifest.json
-rw-r--r--  1 agatakrajewska  staff    89B  1 Jan  1970 repositories

manifest.jsonを見てみましょう。

[ubuntu-docker] cat manifest.json | jq                                                                                           
[
  {
    "Config": "56def654ec22f857f480cdcc640c474e2f84d4be2e549a9d16eaba3f397596e9.json",
    "RepoTags": [
      "ubuntu:bionic"
    ],
    "Layers": [
      "8bf067b107a6f7444876e33c6ed85652355f679ac98ebab97ab3ebad63f0dff3/layer.tar",
      "468327b5cd7ce539db695bd0ef05dae8a4ff77b02870a8e823ed74dedad4bd55/layer.tar",
      "46076a325f0de3f745254638b8b0f0de343685b34e7ca6ec5cd0b6b7930eb7fa/layer.tar"
    ]
  }
]

このファイルはコンテナ設定を示しており、アーキテクチャ、設定、ルートファイルシステムのレイヤーなど、非常に役立つ情報を確認できます。また、Snykの観点からおそらく最も興味深いのはLayersプロパティです。実際のイメージレイヤーを示しており、これらはアーカイブ内のディレクトリです。そのディレクトリの1つに移動すると、内容を確認できます。

[8bf067b107a6f7444876e33c6ed85652355f679ac98ebab97ab3ebad63f0dff3] ll                                                            
total 128160
-rw-r--r--  1 agatakrajewska  staff     3B 25 Sep 23:33 VERSION
-rw-r--r--  1 agatakrajewska  staff   401B 25 Sep 23:33 json
-rw-r--r--  1 agatakrajewska  staff    63M 25 Sep 23:33 layer.tar

さらに詳しく見て、layer.tarを展開してみましょう。

[layer] ll                                                                                                                       
total 0
drwxr-xr-x  87 agatakrajewska  staff   2.7K 21 Sep 18:17 bin
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 boot
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:17 dev
drwxr-xr-x  68 agatakrajewska  staff   2.1K 21 Sep 18:17 etc
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 home
drwxr-xr-x   8 agatakrajewska  staff   256B 23 May  2017 lib
drwxr-xr-x   3 agatakrajewska  staff    96B 21 Sep 18:16 lib64
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 media
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 mnt
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 opt
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 proc
drwx------   4 agatakrajewska  staff   128B 21 Sep 18:17 root
drwxr-xr-x   5 agatakrajewska  staff   160B 21 Sep 18:14 run
drwxr-xr-x  68 agatakrajewska  staff   2.1K 21 Sep 18:17 sbin
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 srv
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 sys
drwxrwxrwt   2 agatakrajewska  staff    64B 21 Sep 18:17 tmp
drwxr-xr-x  10 agatakrajewska  staff   320B 21 Sep 18:14 usr
drwxr-xr-x  13 agatakrajewska  staff   416B 21 Sep 18:17 var

上でご覧のとおり、layer.tarはイメージレイヤーのファイルシステム変更セットで、イメージの内容に応じて、すべての依存関係やその他のバイナリが含まれています。内容を抽出して解析すると

、各レイヤーの脆弱なパスの一覧を表示できます。

次に、保存したDockerアーカイブイメージに対してsnyk testを実行します。docker-archive:プレフィックスを指定すると、ローカルアーカイブをテストできます。

snyk container test docker-archive:ubuntu-docker.tarを実行するか、ローカルのDockerリポジトリからイメージをスキャンします。

snyk container test ubuntu:bionic

どちらもまったく同じ結果が出力されます。

Testing ubuntu:bionic...

✗ Low severity vulnerability found in tar
  Description: Loop with Unreachable Exit Condition ('Infinite Loop')
  Info: <https://snyk.io/vuln/SNYK-UBUNTU1804-TAR-312298>
  Introduced through: tar@1.29b-2ubuntu0.1, pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2
  From: tar@1.29b-2ubuntu0.1
  From: pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2 > debconf@1.5.66ubuntu1 > perl/perl-base@5.26.1-6ubuntu0.3 > dpkg@1.19.0.5ubuntu2.3 > tar@1.29b-2ubuntu0.1

✗ Low severity vulnerability found in tar
  Description: NULL Pointer Dereference
  Info: <https://snyk.io/vuln/SNYK-UBUNTU1804-TAR-559435>
  Introduced through: tar@1.29b-2ubuntu0.1, pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2
  From: tar@1.29b-2ubuntu0.1
  From: pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2 > debconf@1.5.66ubuntu1 > perl/perl-base@5.26.1-6ubuntu0.3 > dpkg@1.19.0.5ubuntu2.3 > tar@1.29b-2ubuntu0.1

# vuln list continues in here
...

Organization:      example-org
Package manager:   deb
Project name:      docker-image|ubuntu
Docker image:      ubuntu:bionic
Licenses:          enabled

Tested 90 dependencies for known issues, found 31 issues.

Pro tip: use `--file` option to get base image remediation advice.
Example: $ snyk test --docker ubuntu:bionic --file=path/to/Dockerfile

OCIイメージ

ここ数か月で、Snyk CLIの機能にOCIアーカイブのスキャンも追加しました。

仕様を確認して、アーカイブの中身を見てみましょう。このセクションでもubuntu:bionicを使用します。

OCIアーカイブのtarファイルを自分で確認したい場合は、次のコマンドを実行できます。

skopeo copy --override-os linux docker://ubuntu:bionic oci-archive:ubuntu.tar

ここではSkopeoを使ってイメージを保存します。これは、イメージに対するさまざまな操作を簡単に実行できるcliユーティリティです。

ubuntuイメージをOCI形式で保存するには、tar出力にoci-archive:プレフィックスを指定するだけです。

ご注意ください。--override-osフラグも使っています。使用している環境はmacOSで、公式のDocker Hub ubuntu imagesはLinux向けのみ提供されているためです。複数アーキテクチャのイメージについては、後ほど説明します。

tarアーカイブを展開したら、その内容を確認できます。

[ubuntu] ll                                                                                                                      
total 16
drwxr-xr-x  3 agatakrajewska  staff    96B 28 Oct 11:18 blobs
-rw-r--r--  1 agatakrajewska  staff   186B 28 Oct 11:18 index.json
-rw-r--r--  1 agatakrajewska  staff    31B 28 Oct 11:18 oci-layout

ルートディレクトリに興味深いindex.jsonがあります。中身を見てみましょう。

[ubuntu] cat index.json | jq                                                                                                     
{
  "schemaVersion": 2,
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "digest": "sha256:afa93a8ce255ca452ca8c88f4b5c821a466cf0a3e0148a31d0d97dfdb91d9aef",
      "size": 658
    }
  ]
}

これは(任意の)上位レベルのマニフェストで、特定のイメージマニフェストを示します。さまざまなアーキテクチャやオペレーティングシステムにまたがるイメージ群の情報が含まれています。詳しく知りたい方は、仕様の全文はこちらをご覧ください。

次に、index.jsonが示していたイメージ固有のマニフェストを、blobs/sha256ディレクトリで確認しましょう。

[sha256] cat afa93a8ce255ca452ca8c88f4b5c821a466cf0a3e0148a31d0d97dfdb91d9aef | jq                                               
{
  "schemaVersion": 2,
  "config": {
    "mediaType": "application/vnd.oci.image.config.v1+json",
    "digest": "sha256:33a51d09088285451e7a7525d4bd64fc15563264afe5a91ef84a8b3042018899",
    "size": 2426
  },
  "layers": [
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:171857c49d0f5e2ebf623e6cb36a8bcad585ed0c2aa99c87a055df034c1e5848",
      "size": 26701612
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:419640447d267f068d2f84a093cb13a56ce77e130877f5b8bdb4294f4a90a84f",
      "size": 852
    },
    {
      "mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
      "digest": "sha256:61e52f862619ab016d3bcfbd78e5c7aaaa1989b4c295e6dbcacddd2d7b93e1f5",
      "size": 162
    }
  ]
}

コンテナ設定など、興味深い内容が見えてきました。ここでは、イメージのアーキテクチャ、ベースイメージのレイヤー、設定など、多くの役立つ情報を確認できます。また、ubuntu:bionicイメージで利用できるレイヤーを示す、イメージレイヤーの情報もあります。

以下から、最初のレイヤーの内容がDockerアーカイブの場合とまったく同じだとわかります。

[171857c49d0f5e2ebf623e6cb36a8bcad585ed0c2aa99c87a055df034c1e5848] ll                                                            
total 0
drwxr-xr-x  87 agatakrajewska  staff   2.7K 21 Sep 18:17 bin
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 boot
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:17 dev
drwxr-xr-x  68 agatakrajewska  staff   2.1K 21 Sep 18:17 etc
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 home
drwxr-xr-x   8 agatakrajewska  staff   256B 23 May  2017 lib
drwxr-xr-x   3 agatakrajewska  staff    96B 21 Sep 18:16 lib64
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 media
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 mnt
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 opt
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 proc
drwx------   4 agatakrajewska  staff   128B 21 Sep 18:17 root
drwxr-xr-x   5 agatakrajewska  staff   160B 21 Sep 18:14 run
drwxr-xr-x  68 agatakrajewska  staff   2.1K 21 Sep 18:17 sbin
drwxr-xr-x   2 agatakrajewska  staff    64B 21 Sep 18:14 srv
drwxr-xr-x   2 agatakrajewska  staff    64B 24 Apr  2018 sys
drwxrwxrwt   2 agatakrajewska  staff    64B 21 Sep 18:17 tmp
drwxr-xr-x  10 agatakrajewska  staff   320B 21 Sep 18:14 usr
drwxr-xr-x  13 agatakrajewska  staff   416B 21 Sep 18:17 var

次のコマンドを実行すると、ローカルのOCIアーカイブをスキャンできます。

snyk container test oci-archive:ubuntu.tar

さまざまなプラットフォームとアーキテクチャ

DockerアーカイブとOCIイメージのマニフェストを調べたところ、どちらにもアーキテクチャ情報が含まれていました。ubuntu-dockerディレクトリにあるコンテナ設定マニフェストの内容をもう一度確認しましょう。ここにはdocker archiveを保存しました。

[sha256] cat 56def654ec22f857f480cdcc640c474e2f84d4be2e549a9d16eaba3f397596e9.json | jq
{
  ...
  "architecture": "amd64",
  "os": "linux",
  ...
}

ほかの情報とともに、アーキテクチャとOSも確認できます。この場合はamd64とlinuxです。イメージがarm64ベースの場合や、windowsプラットフォームを使っている場合はどうでしょうか。

幸い、Snyk CLIに-—platformフラグを渡せば、ほかのプラットフォームもサポートできます。

docker saveのアーカイブ形式を見てきました。次は、Docker Hubでイメージの保存に使われるv2スキーマを見てみましょう。内部の仕組みは非常に興味深いものです。これはv2スキーマの第2版で、主に2つの目的をサポートするために作られました。Dockerのドキュメントによると、次のとおりです。

1つ目は、プラットフォームごとのイメージマニフェストを参照する「ファットマニフェスト」によって、マルチアーキテクチャイメージを実現することです。2つ目は、イメージ設定をハッシュ化してイメージIDを生成できるイメージモデルをサポートし、Dockerエンジンをコンテンツアドレス可能なイメージへと移行させることです。

ローカルのDockerを使って、まず対象イメージの「ファットマニフェスト」を確認し、利用可能なプラットフォームのバリエーションを調べられます。前述のとおり、これにより1つのリポジトリで、異なるアーキテクチャ向けの複数のイメージを管理できます。

docker manifest inspect ubuntu:bionic

その結果、マニフェストの配列が表示されます。

{
   ...
  "manifests": [
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 943,
         "digest": "sha256:45c6f8f1b2fe15adaa72305616d69a6cd641169bc8b16886756919e7c01fa48b",
         "platform": {
            "architecture": "amd64",
            "os": "linux"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 943,
         "digest": "sha256:e80b8affb2361dc632c1fa8fcbf6b6514f750eb6ef99b7e7f825a55f849bfd89",
         "platform": {
            "architecture": "arm",
            "os": "linux",
            "variant": "v7"
         }
      },
      {
         "mediaType": "application/vnd.docker.distribution.manifest.v2+json",
         "size": 943,
         "digest": "sha256:01a2038b20d165ab7df81934f9849bdfbc59bd6f6322c5d11e341504f66ec266",
         "platform": {
            "architecture": "arm64",
            "os": "linux",
            "variant": "v8"
         }
      },
...

ubuntuイメージがさまざまなプラットフォーム向けに提供されていることがわかったので、arm64プラットフォームのアーキテクチャ向けにubuntuイメージをスキャンする方法を見てみましょう。

ホストのDockerで実験的機能が有効になっていることを確認して、次のコマンドを実行します。

snyk container test --platform=linux/arm64 ubuntu:bionic

出力を見てみましょう。

Testing ubuntu:bionic...

✗ Low severity vulnerability found in tar
  Description: Loop with Unreachable Exit Condition ('Infinite Loop')
  Info: <https://snyk.io/vuln/SNYK-UBUNTU1804-TAR-312298>
  Introduced through: tar@1.29b-2ubuntu0.1, pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2
  From: tar@1.29b-2ubuntu0.1
  From: pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2 > debconf@1.5.66ubuntu1 > perl/perl-base@5.26.1-6ubuntu0.3 > dpkg@1.19.0.5ubuntu2.3 > tar@1.29b-2ubuntu0.1

✗ Low severity vulnerability found in tar
  Description: NULL Pointer Dereference
  Info: <https://snyk.io/vuln/SNYK-UBUNTU1804-TAR-559435>
  Introduced through: tar@1.29b-2ubuntu0.1, pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2
  From: tar@1.29b-2ubuntu0.1
  From: pam/libpam-runtime@1.1.8-3.6ubuntu2.18.04.2 > debconf@1.5.66ubuntu1 > perl/perl-base@5.26.1-6ubuntu0.3 > dpkg@1.19.0.5ubuntu2.3 > tar@1.29b-2ubuntu0.1

# vuln list continues in here
...

Organization:      example-org
Package manager:   apk
Project name:      docker-image|ubuntu:bionic
Docker image:      alpine:3.12
Platform:          linux/arm64
Licenses:          enabled

Tested 90 dependencies for known issues, found 31 issues.

Pro tip: use `--file` option to get base image remediation advice.
Example: $ snyk test --docker ubuntu:bionic --file=path/to/Dockerfile

スキャン結果には、検出されたすべての脆弱なパスに加えて、「Platform」情報も表示されています。

この記事では、DockerとOCIの主要な2つのコンテナイメージ形式を取り上げ、複数のアーキテクチャにまたがってSnykがどちらとも連携できることをご紹介しました。

最後に、Node.jsとJavaアプリケーション向けの最適なDockerイメージを構築するためのセキュリティのベストプラクティスを確認しましょう。

  1. Dockerのセキュリティに関する10のベストプラクティス — Dockerのベースイメージを構築する際や取得する際に従うべきセキュリティ対策を詳しく解説し、Docker Content Trustについても紹介します。

  2. Java開発者の方は、こちらの資料もぜひご覧ください。Java開発者のためのDocker:セキュリティで失敗しないために知っておくべき5つのこと

  3. DockerでNode.jsウェブアプリケーションをコンテナ化するための10のベストプラクティス — Node.js開発者におすすめの、Node.jsアプリケーション向けに安全で高性能なDockerベースイメージを構築する手順を紹介するガイドです。

これらの機能はすべてSnykで無料でご利用いただけます。アカウントを登録してください。

Capture the Flagを始めよう

オンデマンドのバーチャル入門ワークショップを見て、Capture the Flagの課題の解き方を学びましょう。

カテゴリー:

続きを読む

Blog

Stadium Summer:Snyk Connect Fan Zone Tour

SnykのFan Zone Tourでは、8都市と3回のオンラインセッションで、AIセキュリティのワークショップやネットワーキング、楽しい競技を開催しました。参加者はスキルを磨き、アイデアを共有し、共に成長しました。

Blog

Snyk VulnBench JS 1.0:LLMは同じバグを2回見つけられるか?

Snyk VulnBench JS 1.0:300回の反復スキャンで、LLMのセキュリティ検出結果は実行ごとに異なる一方、SASTとモデルはそれぞれ異なる脆弱性の見落としを検出することが明らかに。

blog feature toolkit
Blog

elementary-dataのPyPIパッケージに悪意あるリリース、データエンジニアのクラウド認証情報を窃取

攻撃者はGitHub Actionsのスクリプトインジェクション脆弱性を悪用し、悪意あるバージョンのelementary-data Python CLI(v0.23.3)を公開しました。データエンジニアリング環境のdbtプロファイル、クラウドプロバイダーのキー、SSHシークレットを標的とする認証情報窃取バックドアが埋め込まれていました。