🐙

ECRからGHCRにMacのDocker Desktopを経由してイメージ移行する

2025/03/14に公開

はじめに

  • AWSのECRにあるイメージをpullしてきて、GitHub Container registryにPushした
  • GHEC(GitHub Enterprise Cloud)で実施

GitHubのトークンを作る

  • https://github.com/settings/tokens

    • Settings > Developer settings > Personal access tokens > Tokens (classic)
  • 公式ドキュメント参照

  • Scopeはドキュメントに記載の通りpackagesへの書き込み権限を追加
    Select Scope

  • OrganizationへのSSOが必要なためclassicトークンを作成

    • SSOが必要な場合はトークン作成後にConfigure SSOからSSO認証
    • Scopeでwrite:org, read:orgの権限は選択不要だが権限更新後は再度SSO認証が必要な模様
    • denied: permission_denied: Resource protected by organization SAML enforcement. You must grant your Personal Access token access to this organization. とエラーが出たらConfigure SSOから再認証を一度試すとよいかも

1Password(おまけ)

  • 1PasswordのCLIをインストールしてGitHub CLIと連携すると便利だったのでおまけで記載

  • 1Password CLI からダウンロードしてインストールする

    • macOS(.pkg)からインストールした
  • 1Passwordのデスクトップアプリで「設定」を開き、1Password CLIと連携にチェック

    • デスクトップアプリがない場合はユーザ名/パスワードで認証可だが
      毎回パスワード入力が必要でサービスアカウントとトークンを作成したほうが良いらしい
    • デスクトップアプリがあればop signin で生体認証が使用できるので楽
      1Password
  • ターミナルで $op signin して $op plugin init gh する

    • まだ1Passwordにトークン保存していない場合はImport into 1Passwordを選択する
    • 1Passwordに保存済の場合はSearch in 1Password で登録済リストから選択できる
  • 詳しくはこちら

Docker Desktopでcontainerdの使用をオフにする

  • これをしないと、GHCRにPushしたときに Not all multiplatform-content is present and only the available single-platform image was pushed となる

  • Docker Desktop > Settings > General

    • 下にスクロールして Use containerd for pulling and storing images のチェックを外す

Docker Desktop

ECRからpull

  • これはいつもどおり
$ aws ecr get-login-password --region ap-northeast-1 | docker login --username AWS --password-stdin <account_id>.dkr.ecr.ap-northeast-1.amazonaws.com
Login Succeeded

$ docker pull <account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/<imagename>:<tag>
  • ちなみにcontainerdを使う使わないで異なるimage idになるので変更が確認できる

GitHub Container Registoryにpush

  • タグ打っとく
$ docker tag <account_id>.dkr.ecr.ap-northeast-1.amazonaws.com/imagename:tag ghcr.io/<org_name>/imagename:tag

  • 環境変数にトークンをセットする
# 1Passwordからトークンを取得
$ export CR_PAT=$(op item get <id> --reveal --fields token)

# <id>は1Passwordのアイテムのプライベートリンクのクエリパラメータ`i=`の値
# もしくはCLIで`op item get` する
$ op item get fukuta-emi-classic-token
ID:          <id>
Title:       fukuta-emi-classic-token
Vault:       Private
....
Category:    API_CREDENTIAL
Fields:
  token:    [use 'op item get <id> --reveal' to reveal]
URLs:
website:    https://github.com/settings/tokens (primary)
  • docker login
echo $CR_PAT | docker login ghcr.io -u <username> --password-stdin
  • docker push
    • 現状他にpushできるイメージがないのでalready exists
$ docker push ghcr.io/<org_name>/imagename:tag
The push refers to repository [ghcr.io/<org_name>/imagename]
22a06bbb9d67: Layer already exists
24ed4db34015: Layer already exists
7bdc8537c862: Layer already exists
3e3a39647c34: Layer already exists
93d0935d9424: Layer already exists
533bb0c5a9ac: Layer already exists
a54f39b467ca: Layer already exists
db84e53a0deb: Layer already exists
ae17055a5b28: Layer already exists
6878eb2ade49: Layer already exists
d5e753d7e692: Layer already exists
78a822fe2a2d: Layer already exists
tag: digest:
  • 先述のSSOが切れてたり権限不足だったりするとここでpermission_deniedになる
$ docker push ghcr.io/<org_name>/imagename:tag
22a06bbb9d67: Preparing
24ed4db34015: Preparing
7bdc8537c862: Preparing
3e3a39647c34: Preparing
93d0935d9424: Preparing
533bb0c5a9ac: Waiting
a54f39b467ca: Waiting
db84e53a0deb: Waiting
ae17055a5b28: Waiting
6878eb2ade49: Waiting
d5e753d7e692: Waiting
78a822fe2a2d: Waiting
unauthorized: unauthenticated: User cannot be authenticated with the token provided.

Discussion