Dockerラベル / OCIコンテナアノテーションの使い方と使いどき
2021年11月3日
0 分で読めますほとんどのコンテナイメージは、OCI準拠イメージのレイヤーを構築するために、FROM、RUN、COPY、ENTRYPOINTなどの命令を組み合わせたDockerfileを使ってビルドされます。しかし、意外なほどあまり使われていない命令がLABELです。この記事では、ラベル(OCI Image Specificationでは「アノテーション」と呼ばれます)とは何か、標準化された用途、そしてコンテナのセキュリティ態勢を強化するために活用できる方法について掘り下げます。
この記事では、アノテーションではなく、より一般的に使われている「ラベル」という呼び方を使います。それでは始めましょう。
Dockerイメージのラベルとは?
Dockerイメージのラベルを使うと、イメージ自体にキーと値のペアでメタデータを追加できます。このデータはイメージを使って実行するコンテナには公開されませんが、イメージのソースコードの場所、サポート担当者、イメージを作成したCIビルドなどを記録するのに役立ちます。
Docker / OCIイメージのメタデータを解説
ソフトウェアパッケージを作成したことがあれば、一般に、パッケージにはソフトウェア、設定、場合によっては機能データと、パッケージ自体に関するメタデータが含まれることをご存じでしょう。
たとえば、Javaの.jarファイルは基本的に.zipアーカイブですが、どのファイルにも最上位のMETA-INFディレクトリがあり、Java 2 Platform specによると、「Java 2 Platformがアプリケーション、拡張機能、クラスローダー、サービスを設定するために認識し、解釈する」複数のファイルやディレクトリが含まれています。人気のビルドツールMavenで作成された.jarを開くと、通常はmavenディレクトリがあり、その中には.jarのビルドに使われた有効なMavenのpom.xmlやpom.propertiesなどが含まれています。(ちなみに「POM」はMavenのProject Object Modelの略です)
RPM、APT、NPMをはじめとするほとんどのパッケージ管理ツールにも、同様のメタデータが格納されています。これらは、含まれるソフトウェアのインストールや実行時にツールが使用したり、リポジトリや実行時監視システムが利用したりします。

コンテナイメージのレイヤーにもメタデータが格納されています。イメージの「履歴」を一覧表示すると、ファイルシステムに変更を加えず、実行時に使われるメタデータだけを含むため、サイズが0バイトのレイヤーがよく見つかります。こうしたメタデータは、一般に次のDockerfileコマンドで追加されます。
USER:プロセスを実行するユーザーENV:プロセス環境に設定する変数とその値ARG:コンテナのビルド環境に渡され、ビルドの範囲内で環境変数のように使われるビルド引数CMD:プロセスの起動に使うコマンドやパラメーター(ENTRYPOINTも同様)LABEL:実行エンジンでは使用されないキーと値のペア
これらの多くは広く知られており、あらゆるDockerfileで使われています。しかし、ラベルのメタデータはコンテナの実行に必須ではないため、見落とされがちです。
コンテナイメージのラベルを使うべき理由
イメージにラベルを使う理由はさまざまです。バージョン情報の記録、プロジェクトのメンテナーへの連絡先の追加、実行時の利用情報の記録などに活用できます。最も一般的な用途の1つは、イメージの構築に関する情報を記録し、イメージ成果物のソフトウェアサプライチェーン情報として利用することです。
Dockerラベル / OCIイメージアノテーションのメタデータの種類
標準化されたラベル
イメージの作成元や由来に関するメタデータは広く使われているため、OCIチームは「org.opencontainers.image.」をプレフィックスとする標準のキーセットを公開しています。たとえば次のようなキーがあります。
source:イメージのビルドに使うソースコードのURLrevision:パッケージ化されたソフトウェアのソース管理リビジョン識別子base.digest:このイメージのベースとなるイメージのダイジェスト(ハッシュ)base.name:このイメージのベースとなるイメージの参照情報version:パッケージ化されたソフトウェアのバージョン
カスタムラベル
単純なキーと値のペアなので、プロジェクトや組織のニーズに合わせてほぼ自由に指定できます。たとえば、次のような項目が考えられます(いずれも「com.mycorp.myteam.」のようなプレフィックスを付けられます)。
ci-build:イメージを生成したCIプロジェクトの実行URLreleasenotes:パッケージ化されたソフトウェアのリリースノートhealthz:ヘルスチェック用のHTTPエンドポイントdocker.run:このイメージを実行するDockerコマンドの例k8s.deployment:このイメージを使ったKubernetesデプロイ用のBase64エンコード済みYAML
最後の例は興味深いものです。実際、ラベルキーの値には、Base64でエンコードできるものならほぼ何でも保存できます。つまり、イメージをプルして次のようなコマンドを実行すれば、Kubernetesクラスターで使えるサンプルのYAMLデプロイファイルを取得できます。
これをそのままkubectlにパイプして、すぐにデプロイすることもできます。Helmチャートも、Gitリポジトリ内の個別のYAMLファイルも必要ありません。
Dockerラベル / OCIアノテーションを活用する
ご想像のとおり、ラベルにはCIシステムがアクセスできる任意の値を設定できます。ラベルを確認するだけで、イメージや実行中のコンテナをそのソースやドキュメントなどと関連付けられます。たとえば、組織がOCI標準のorg.opencontainers.image.sourceラベルを使って、イメージのソースとなるSCMリポジトリのURLを登録しているとします。特定のDockerホスト上で稼働しているイメージのリポジトリをすべて調べたい場合は、次のようなコマンドを実行できます。
出力には実行中の2つのコンテナIDが表示され、そのうちラベルが付いたコンテナについては、その値も出力されています。
Kubernetesクラスターで実行する場合は、少し複雑になります。通常、クラスターのノード上にあるコンテナエンジンのソケットにはアクセスできないためです。残念ながら、kubectlからこれらのラベルにアクセスするAPIはありません。そのため、少し工夫が必要です。次のbashスクリプトは、現在のコンテキストの名前空間で実行中のイメージを見つけ、イメージレジストリに問い合わせてイメージのメタデータを取得し、ラベル情報を返します。
ここでは、優れたオープンソースのregclientプロジェクトが提供するregctlツールを使っています。イメージをローカル環境にプルして調査する必要がなく、レジストリから直接イメージ情報を取得できます。また、コンテナランタイムエンジンがなくても、どこでもこのスクリプトを実行できます。
では、これをクラスターに対して実行し、クラスター内で稼働しているイメージのリポジトリを確認してみましょう。
ご覧のとおり、現在クラスター内では、org.opencontainers.image.sourceラベルが付いたイメージが2つ、Pod内で実行されています。
ここでは比較的シンプルな例を紹介しましたが、考え方を応用して、組織のニーズに合ったスクリプトやAPI呼び出しを作成できるはずです。
Snykとのインテグレーション
セキュリティの観点から特に興味深いのは、Snykのイメージスキャンで、イメージラベルを使ってスキャンしたイメージとそのDockerfileを自動的に関連付けられるようになったことです。
Snykのソースコードリポジトリとのインテグレーションでは、コード内のDockerfileを静的に検出してスキャンできるほか、コンテナレジストリからインポートしたイメージもスキャンできます。しかし、最近まで両者の相互参照は自分で管理する必要がありました。Dockerfileへの参照をイメージに手動で追加するか、API呼び出しによる独自の自動化を実装する必要があったのです。
今では、DockerfileにOCI標準のorg.opencontainers.image.sourceラベルを追加し、Dockerfileを含むリポジトリのURLを指定するだけで、イメージのインポート時にSnykが自動で相互参照します。

自動的にリンクされたイメージスキャンプロジェクトの例
まとめ
まとめると、見過ごされがちなイメージのラベル/アノテーションは、イメージに直接メタデータを埋め込める強力なツールです。標準化されたキーを使えば、イメージの出所を記録できるだけでなく、デプロイツールやセキュリティツールに活用して、デプロイ環境をより的確に把握できます。
アカウント内でスキャンしているDockerfileに、OCI標準のorg.opencontainers.image.sourceラベルを追加するだけで、Snykのイメージ自動リンク機能を今すぐ利用できます。Snykアカウントをお持ちでない方は、無料で登録してすぐにお試しください。
皆さんがラベルをどのように活用しているのか気になります。今回紹介したアイデアは新しいものでしょうか。それとも、すでにプロジェクトで使っていますか?ほかにどんな方法でイメージにアノテーションを付けていますか?Snykや他のツールに実装してほしい新しいインテグレーションはありますか?アイデアをTwitterで教えてください(@ericsmalling)。ぜひお聞かせください。
開発者ファーストのコンテナセキュリティ
Snykは、コンテナイメージとKubernetesワークロードの脆弱性を検出し、自動的に修正します。
