Open5

oras cli でマルチプラットフォーム用のパッケージ(Artifact)を作成

hankei6kmhankei6km

oras に興味持ったのは「スクリプトとかで頑張らなくてもマルチプラットフォーム対応できるかな?」というのが発端。ということで、少し実験。

hankei6kmhankei6km

image index と platform

プラットフォームの指定は image index を作成することで行う(これとは別に artifact の config で os などを指定する方法などもあるようだが、今回は利用しない - マルチプラットフォームにできないと思われる)。

下記の例でいうと manifests[].platform がそれぞれの manifest(artifact) に対するプラットフォーム指定になる。

{
  "schemaVersion": 2,
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "manifests": [
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 7143,
      "digest": "sha256:e692418e4cbaf90ca69d05a66403747baa33ee08806650b51fab815ad7fc331f",
      "platform": {
        "architecture": "ppc64le",
        "os": "linux"
      }
    },
    {
      "mediaType": "application/vnd.oci.image.manifest.v1+json",
      "size": 7682,
      "digest": "sha256:5b0bcabd1ed22e9fb1310cf6c2dec7cdef19f0ad69efa1f392e94a4333501270",
      "platform": {
        "architecture": "amd64",
        "os": "linux"
      }
    }
  ],
  "annotations": {
    "com.example.key1": "value1",
    "com.example.key2": "value2"
  }
}
hankei6kmhankei6km

oras で image index を作るには

この辺は少し議論があったようで、image index に特化した機能としてはサポートしていないもよう。artifact の領分ではないから、という判断らしい(たぶん)。

https://github.com/oras-project/oras/issues/237

よって、image index を manifest として作成して oras manifest push することになる。

  1. プラットフォーム用の artifact を個別の push し各 manifest のダイジェストとサイズを控えておく
  2. image index を作るときに manifests 配列でダイジェストとサイズを使う
  3. 出来上がった image index を manifest として push する
hankei6kmhankei6km

検証

リポジトリ作ってみた。

https://github.com/hankei6km/test-oras-oras-cll-os-arch

上記の通りのシェルスクリプトを作っただけ。

push するとパッケージに OS / Arch のタブができる。

GitHub のウェブ UI でパッケージを表示しているスクリーンショット。OS / Arch のタブの横に “5” のバッジが表示されている。

pull するとどうなるかの検証は skopeo を利用(oras pull だと手動で --platform を指定しないと image index が指している artifact をすべてダウンロードしてしまう)。

ubuntu と macos ランナーで異なるファイルがダウンロードされたことを確認。

ワークフローの実行結果のスクリーンショット、linux amd64 と表示されている箇所がある

ワークフローの実行結果のスクリーンショット、darwin amd64 と表示されている箇所がある

hankei6kmhankei6km

メモ

  • manifests の記述はダイジェスト以外にサイズも必要だった
    • サイズの指定がないと oras pull でエラーになる(skopeo copy は大丈夫だった)
  • 別のパッケージのダイジェストは指定できない
    • 権限やらコンフリクトを考えると「まぁそうだよね」とは思う
  • 各プラットフォームの artifact にタグ付けてなくても良かったかも
    • image index での参照は ghcr 側でも認識してるからクリーンアップ的なことはなさそう?
  • 各プラットフォーム用のジョブはわけても大丈夫そう
    • ダイジェストとサイズさえ受け渡しできれば各プラットフォームの artifact はバラバラなタイミングで push できる
      • oras cli で pull しなければサイズはなくても良い?
  • Dev Containers の Features でなぜに install.sh 側でマルチアーキテクチャ対応をしているのか
    • 少し不思議に思っていたのだけど、上でも書いたけどやはりこの辺の話がからむのかなと、違うかな?