🐳

Chainguard imagesについて調べてみた

2023/12/05に公開

※この記事は3-shake Advent Calendar 2023 シリーズ1の12月5日の記事です

最近Chainguard imagesというdistrolessコンテナイメージについて知ったので、簡単に調べてみました。

Chainguard imagesとは?

Chainguard imagesはChainguard社によって提供されているdistrolessを中心としたセキュアなコンテナイメージ群だ、という理解です。

Wolfiという(おそらくこれもChainguard社が開発している)コンテナ・クラウドネイティブ用途向けのLinux undistroなOSを利用して各Chainguard imagesのコンテナイメージが提供されているようです。

Wolfi OS

Wolfiの特徴は下記のようです。

  • SBOM をすべてのパッケージに標準で提供
  • 必要最小限のパッケージのみを使用
  • apk パッケージ形式
  • melangeというapkパッケージを宣言的にビルドするツールを使用してビルドを行う
  • glibcとmuslをサポート

Chainguard images

このWolfi OSを使用して作成されているのがChainguard imagesで提供されているコンテナイメージであり、Chainguard Images Reference ページを見ると

  • Go
  • Ruby
  • PHP

のような僕ら開発者が開発などで利用するような一般的なイメージから

  • etcd
  • MariaDB

のようなミドルウェア用のイメージもあれば

  • aws-cli
  • kubectl

のようなCLI用のコンテナイメージもあるようです。

中には

  • aws-ebs-csi-driver
  • calico-kube-controllers
  • cert-manager-controller

といったKubernetes Operator用のイメージも提供されているようで、Googleが提供するdistrolessイメージと比べるとかなり多くの種類のコンテナイメージを提供しているようです。

Wolfi OSをベースとしたこれらのChainguard imagesですが、特徴としては下記のようなことが挙げられています

  • 不要なソフトウェアによる肥大化が無い
  • イメージ内の全てのアーティファクトの出所をSBOMで確認可能
  • Sigstoreによる検証可能な署名をOCIイメージに実施
  • 自動化されたビルドによって利用可能なセキュリティパッチが含まれたイメージを提供
  • apkoというDockerfileを用いずにapkパッケージから直接OCIイメージをビルドするツールを使用
  • 前述のapkoとOCIコンテナへの署名を行うCosignによってコンテナイメージのビルドを再現可能

apkoによるOCIイメージのビルド

apkoのREADMEにかかれているものをだいたいそのまま引用してるだけですが、こんな感じでapkoのインストールからAlpineのコンテナイメージのビルドまでができちゃうらしいです。

$ brew install apko # go install chainguard.dev/apko@latest でも行けるとのこと
$ cat << EOS > alpine-base.yaml
contents:
  repositories:
    - https://dl-cdn.alpinelinux.org/alpine/edge/main
  packages:
    - alpine-base

entrypoint:
  command: /bin/sh -l

# optional environment configuration
environment:
  PATH: /usr/sbin:/sbin:/usr/bin:/bin
EOS
$ apko build alpine-base.yaml apko-alpine:test apko-alpine.tar

僕の場合、ベースイメージを使わずに1からコンテナイメージを構築してみるのとかは以前TenForwardさんにここで書かれているような感じでVM上にダウンロードしたLinuxのパッケージ?でpivot_rootとかをやるくらいを教えてもらったことしかやったことが無いので、こんな感じで宣言的なファイルを1つ作ってビルドするだけでコンテナのベースイメージが作れちゃうのはすごいなーという感じです。

コンテナイメージのビルドを再現

次もここの記事の引用でしかないのであれですが、特徴にあげられていた「コンテナイメージのビルドを再現可能」というのはこういう感じらしいです。

$ brew install cosign # Mac以外の場合はこちらからバイナリをダウンロードのよう: https://github.com/sigstore/cosign/releases/tag/v2.2.1
$ IMAGE_NAME=cgr.dev/chainguard/wolfi-base
$ cosign verify-attestation \
  --type https://apko.dev/image-configuration \
  --certificate-oidc-issuer https://token.actions.githubusercontent.com \
  --certificate-identity https://github.com/chainguard-images/images/.github/workflows/release.yaml@refs/heads/main \
  "${IMAGE_NAME}" | jq -r .payload | base64 -d | jq .predicate > latest.apko.json
$ apko build latest.apko.json wolfi-base:local wolfi-base.tar
...
INFO[0000] Generating arch image SBOMs
ℹ️            | Generating image SBOM for amd64
ℹ️            | Generating image SBOM for arm64
ℹ️            | Generating index SBOM
INFO[0000] Final index tgz at: wolfi-base.tar

あんまわかってないけどすごい簡単にビルドできますね。
ディレクトリを確認してみると下記のようにSBOMのファイルも色々生成されていました。

$ ls -1
latest.apko.json
sbom-aarch64.cdx
sbom-aarch64.spdx.json
sbom-index.cdx
sbom-index.spdx.json
sbom-x86_64.cdx
sbom-x86_64.spdx.json
wolfi-base.tar

cosignで生成された latest.apko.json を見るとこんな感じになっていて、どうやらコンテナに設定されているユーザー/グループやパッケージ情報などが入っているようでした。

$ cat latest.apko.json
{
  "accounts": {
    "groups": [
      {
        "gid": 65532,
        "groupname": "nonroot",
        "members": []
      }
    ],
    "run-as": "0",
    "users": [
      {
        "gid": 65532,
        "uid": 65532,
        "username": "nonroot"
      }
    ]
  },
  "annotations": {
    "org.opencontainers.image.authors": "Chainguard Team https://www.chainguard.dev/",
    "org.opencontainers.image.source": "https://github.com/chainguard-images/images/tree/main/images/wolfi-base",
    "org.opencontainers.image.url": "https://edu.chainguard.dev/chainguard/chainguard-images/reference/wolfi-base/"
  },
  "archs": [
    "amd64",
    "arm64"
  ],
  "cmd": "/bin/sh -l",
  "contents": {
    "keyring": [
      "https://packages.wolfi.dev/os/wolfi-signing.rsa.pub"
    ],
    "packages": [
      "apk-tools=2.14.0-r0",
      "busybox=1.36.1-r2",
      "ca-certificates-bundle=20230506-r0",
      "glibc=2.38-r6",
      "glibc-locale-posix=2.38-r6",
      "ld-linux=2.38-r6",
      "libcrypt1=2.38-r5",
      "libcrypto3=3.2.0-r0",
      "libssl3=3.2.0-r0",
      "openssl-config=3.2.0-r0",
      "wolfi-base=1-r3",
      "wolfi-baselayout=20230201-r6",
      "wolfi-keys=1-r5",
      "zlib=1.3-r2"
    ],
    "repositories": [
      "https://packages.wolfi.dev/os"
    ]
  },
  "entrypoint": {
    "command": "",
    "services": {},
    "shell-fragment": "",
    "type": ""
  },
  "environment": {},
  "include": "",
  "options": {},
  "os-release": {
    "bug-report-url": "",
    "home-url": "",
    "id": "",
    "name": "",
    "pretty-name": "",
    "version-id": ""
  },
  "paths": [],
  "stop-signal": "",
  "vcs-url": "",
  "volumes": [],
  "work-dir": ""
}

Chainguard imagesとサポート

ここまで紹介してきたChainguard imagesですが、デフォルトでは latest タグのみしか利用できないようで、ツールなどによってはこのあたりがネックになってくるのかなという印象です。

任意のタグを利用するためにはエンタープライズサポートに加入する必要があり、サポートには下記が含まれているようでした。

  • イメージのメジャー/マイナーバージョンタグ利用
  • SLA
  • カスタマーサポート

コンテナイメージに対するエンタープライズサポートは個人的には珍しい気がしていて、僕の知っている限り他にはRedHat UBIイメージがOpenShift上でサポートされているくらいしか無い気がしたのでかなり珍しいなという印象でした。

その他のサービス

Chainguardはimages以外にもChainguard EnforceというKubernetes上で動作するサプライチェーンセキュリティがあるらしい。

Chainguard EnforceはKubernetesクラスターにインストール~ポリシーを設定することで、クラスター内で実行されているイメージを分析して設定したポリシーを満たしているかを判断してくれるよう。

まとめ

Chainguard imagesについて調べたことをまとめさせて頂きました。
「Chainguardはコンテナイメージのエンタープライズサポートをしているらしいぞ」くらいの気持ちで調べてみたのですが、調べてみるとWolfi OSというAlpineベースなイメージを提供するとこから始まり、このOS自体のビルドやWolfi OSをベースとしたChainguard imagesのビルドに宣言的な設定ファイルなどを元にビルドを再現可能なツールを開発していたりとかなり興味深かったです。
また別の機会にこれらのツールについての深掘りをしてみようと思いました。

参考リンク一覧

Discussion