SUPER-G.EEK.JP

twitter: @hum_op_dev
github: ophum

任意のファイルをOCI RegistryにPushしてみる

目次

OCI レジストリはコンテナのイメージを保存するのに使うことが多いですが、コンテナイメージ以外のデータを保存することも可能です。

バイナリファイルなどビルドの成果物管理に OCI レジストリが使えると便利そうだなと思ったのでその検証をしてみました。

oras というプロジェクトがまさにそれを行っています。

oras で ghcr.io にファイルを push するワークフローを GitHub Actions で動かす

以下のような workflow を定義します。

 1name: Build binary push to github registry using oras
 2on:
 3  push:
 4    branches:
 5      - main
 6
 7jobs:
 8  build-and-push:
 9    runs-on: ubuntu-latest
10    permissions:
11      packages: write
12    steps:
13      - uses: actions/checkout@v4
14      - uses: oras-project/setup-oras@v1
15      - run: echo -n $GITHUB_TOKEN | oras login -u ${{ github.actor }} --password-stdin ghcr.io
16        env:
17          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
18      - run: date > output.txt
19      - run: oras push ghcr.io/ophum/kakisute/oras-test:${{ github.sha }} output.txt

以下のように実行できました。

Packages のページでも確認できます。

oras コマンドでファイルを pull する

public なパッケージの場合(oras)

public なパッケージだと認証なしで pull できます。

タグを確認 (oras public)

1hum@ryzen5pc:~/oras-test$ oras repo tags ghcr.io/ophum/kakisute/oras-test
23ed88f2e9ee119b0694e8cededcd7d1485e92649
3b4b9d43949141020a5a6a1205fd8047e1ff8f06d
458072af430466fddc68e557e38eea8ca4716c5f6

pull する (oras public)

1hum@ryzen5pc:~/oras-test$ ls
2hum@ryzen5pc:~/oras-test$ oras pull ghcr.io/ophum/kakisute/oras-test:b4b9d43949141020a5a6a1205fd8047e1ff8f06d
3✓ Pulled      output.txt                                                     29/29  B 100.00%  484µs
4  └─ sha256:2caee7636353b06e490e048bf0ff323347aaa7b59a4fa2a87f51e46687d3e2ee
5✓ Pulled      application/vnd.oci.image.manifest.v1+json                   589/589  B 100.00%  137µs
6  └─ sha256:6519123c64ebe8ab9b3e0593556b3786db9375e5bfbefe07155eb43d884f8dc0
7Pulled [registry] ghcr.io/ophum/kakisute/oras-test:b4b9d43949141020a5a6a1205fd8047e1ff8f06d
8Digest: sha256:6519123c64ebe8ab9b3e0593556b3786db9375e5bfbefe07155eb43d884f8dc0

output.txtが存在することと書き込まれた内容を確認します。

1hum@ryzen5pc:~/oras-test$ ls
2output.txt
3hum@ryzen5pc:~/oras-test$ cat output.txt
4Sun Jun 29 05:29:16 UTC 2025

private なパッケージの場合 (oras)

oras login

oras login するか-u, -p オプションで認証情報を指定します。

gh コマンドのトークンを利用してみます。

 1hum@ryzen5pc:~/oras-test$ gh auth login -h github.com -p https --scopes read:packages --web
 2
 3! First copy your one-time code: 156D-89E5
 4Press Enter to open github.com in your browser...
 5✓ Authentication complete.
 6- gh config set -h github.com git_protocol https
 7✓ Configured git protocol
 8! Authentication credentials saved in plain text
 9✓ Logged in as ophum
10hum@ryzen5pc:~/oras-test$ gh auth token | oras login -u ophum --password-stdin ghcr.io
11Login Succeeded

pull する(oras private)

1hum@ryzen5pc:~/oras-test$ oras pull ghcr.io/ophum/kakisute/oras-test:b4b9d43949141020a5a6a1205fd8047e1ff8f06d
2✓ Pulled      output.txt                                                     29/29  B 100.00%  667µs
3  └─ sha256:2caee7636353b06e490e048bf0ff323347aaa7b59a4fa2a87f51e46687d3e2ee
4✓ Pulled      application/vnd.oci.image.manifest.v1+json                   589/589  B 100.00%     0s
5  └─ sha256:6519123c64ebe8ab9b3e0593556b3786db9375e5bfbefe07155eb43d884f8dc0
6Pulled [registry] ghcr.io/ophum/kakisute/oras-test:b4b9d43949141020a5a6a1205fd8047e1ff8f06d
7Digest: sha256:6519123c64ebe8ab9b3e0593556b3786db9375e5bfbefe07155eb43d884f8dc0
1hum@ryzen5pc:~/oras-test$ cat output.txt
2Sun Jun 29 05:29:16 UTC 2025

curl でファイルを pull する

public なパッケージの場合 (curl)

トークンを作成 (curl public)

1hum@ryzen5pc:~/oras-test$ curl -so "token.json" "https://ghcr.io/token?service=ghcr.io&scope=repository:ophum/kakisute/oras-test:pull"

タグを確認 (curl public)

作成したトークンを Authorization ヘッダーに入れて実行します。

 1hum@ryzen5pc:~/oras-test$ curl -s -H "Authorization: Bearer $(cat token.json | jq -r .token)" https:
 2//ghcr.io/v2/ophum/kakisute/oras-test/tags/list | jq
 3{
 4  "name": "ophum/kakisute/oras-test",
 5  "tags": [
 6    "3ed88f2e9ee119b0694e8cededcd7d1485e92649",
 7    "b4b9d43949141020a5a6a1205fd8047e1ff8f06d",
 8    "58072af430466fddc68e557e38eea8ca4716c5f6"
 9  ]
10}

マニフェストを確認 (curl public)

 1hum@ryzen5pc:~/oras-test$ curl -so manifest.json \
 2    -H "Accept: application/vnd.oci.image.manifest.v1+json" \
 3    -H "Authorization: Bearer $(cat token.json | jq -r .token)" \
 4    https://ghcr.io/v2/ophum/kakisute/oras-test/manifests/3ed88f2e9ee119b0694e8cededcd7d1485e92649
 5hum@ryzen5pc:~/oras-test$ cat manifest.json | jq
 6{
 7  "schemaVersion": 2,
 8  "mediaType": "application/vnd.oci.image.manifest.v1+json",
 9  "artifactType": "application/vnd.unknown.artifact.v1",
10  "config": {
11    "mediaType": "application/vnd.oci.empty.v1+json",
12    "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
13    "size": 2,
14    "data": "e30="
15  },
16  "layers": [
17    {
18      "mediaType": "application/vnd.oci.image.layer.v1.tar",
19      "digest": "sha256:9378c2a8b36f97d973b728a0d944356874903b71c83fcdb68724ef3c19a687a1",
20      "size": 29,
21      "annotations": {
22        "org.opencontainers.image.title": "output.txt"
23      }
24    }
25  ],
26  "annotations": {
27    "org.opencontainers.image.created": "2025-06-29T05:28:08Z"
28  }
29}

output.txt をダウンロードする (curl public)

.layers[0].digest を指定してダウンロードします。

1hum@ryzen5pc:~/oras-test$ curl -L -s \
2    -H "Authorization: Bearer $(cat token.json | jq -r .token)" \
3    "https://ghcr.io/v2/ophum/kakisute/oras-test/blobs/$(cat manifest.json | jq -r '.layers[0].digest')"
4Sun Jun 29 05:28:08 UTC 2025

private なパッケージの場合

トークンを作成 (curl private)

public の時と同じ URL に Basic 認証付きで実行します。

1hum@ryzen5pc:~/oras-test$ curl -so "token.json" -u ophum:$(gh auth token) "https://ghcr.io/token?service=ghcr.io&scope=repository:ophum/kakisute/oras-test:pull"

タグを確認 (curl private)

あとは public の時と同じです。 作成したトークンを Authorization ヘッダーに入れて実行します。

1hum@ryzen5pc:~/oras-test$ curl -s -H "Authorization: Bearer $(cat token.json | jq -r .token)" https://ghcr.io/v2/ophum/kakisute/oras-test/tags/list | jq
2{
3  "name": "ophum/kakisute/oras-test",
4  "tags": [
5    "3ed88f2e9ee119b0694e8cededcd7d1485e92649",
6    "b4b9d43949141020a5a6a1205fd8047e1ff8f06d",
7    "58072af430466fddc68e557e38eea8ca4716c5f6"
8  ]
9}

マニフェストを確認 (curl private)

 1hum@ryzen5pc:~/oras-test$ curl -so manifest.json \
 2    -H "Accept: application/vnd.oci.image.manifest.v1+json" \
 3    -H "Authorization: Bearer $(cat token.json | jq -r .token)" \
 4    https://ghcr.io/v2/ophum/kakisute/oras-test/manifests/3ed88f2e9ee119b0694e8cededcd7d1485e92649
 5hum@ryzen5pc:~/oras-test$ cat manifest.json | jq
 6{
 7  "schemaVersion": 2,
 8  "mediaType": "application/vnd.oci.image.manifest.v1+json",
 9  "artifactType": "application/vnd.unknown.artifact.v1",
10  "config": {
11    "mediaType": "application/vnd.oci.empty.v1+json",
12    "digest": "sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a",
13    "size": 2,
14    "data": "e30="
15  },
16  "layers": [
17    {
18      "mediaType": "application/vnd.oci.image.layer.v1.tar",
19      "digest": "sha256:9378c2a8b36f97d973b728a0d944356874903b71c83fcdb68724ef3c19a687a1",
20      "size": 29,
21      "annotations": {
22        "org.opencontainers.image.title": "output.txt"
23      }
24    }
25  ],
26  "annotations": {
27    "org.opencontainers.image.created": "2025-06-29T05:28:08Z"
28  }
29}

output.txt をダウンロードする (curl private)

.layers[0].digest を指定してダウンロードします。

1hum@ryzen5pc:~/oras-test$ curl -L -s \
2    -H "Authorization: Bearer $(cat token.json | jq -r .token)" \
3    "https://ghcr.io/v2/ophum/kakisute/oras-test/blobs/$(cat manifest.json | jq -r '.layers[0].digest')"
4Sun Jun 29 05:28:08 UTC 2025

References