「Artifact RegistryにDockerイメージをプッシュしておいてほしい」と言われた時のメモ


お取引先：Artifact RegistryにDockerイメージをプッシュしてほしいです。
俺：わかりました（俺のDockerイメージがついにアーティファクトに……？）
上の人：別のプロジェクトではやってるから手順を展開するね。
俺：わかりました（わかんない……）

俺：とりあえずpushしたらDockerイメージがどっかーに行ってしまった……。

～完～

#  Artifact Registryとは

Google Cloudのサービスです。
コンテナ イメージや言語パッケージなどを管理できるサービスですね。
今回のケースでいうと、Dockerイメージ置き場として利用されています。

https://cloud.google.com/artifact-registry?hl=ja

| 使用法        | 料金 (GB 単位/月) |
| ------------- | ----------------- |
| 最大 0.5 GB   | 無料              |
| 0.5 GB 超     | $0.10             |

サイズが0.5GBを超えるとGBごとに0.1＄かかります。
Dockerイメージは結構重いのでそれなりにお金がかかりますね。

今回は、「他社のArtifact Registryに、作成したDockerイメージをプッシュする」という、**利用者としてのお話**です。

# 具体的な作業の手順

## アクセス権限をもらう

まず、よそ様の家のArtifact Registryを見に行くので、アクセス権限をもらいます。
見るための権限（Viewer 権限）と、プッシュするための権限（Writer 権限）をもらいます。

人の家のArtifact Registryに行きますので、自分の側のArtifact RegistryはEnableにする必要はありません。うっかり何かを置くと月額でお金がかかりますので、使わない場合は無効にしておくのがおすすめです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/439672/81b28271-0e42-5431-b153-6e511ccfb2ce.png)

（このシチュエーションの場合は、有効にしない……）

「ここにおいてください」という感じでURLがもらえると思うので、アクセスして、とりあえず、観覧できることを確認します。

URLの例：
`https://console.cloud.google.com/artifacts/docker/[PROJECT-ID]/[REGION]/containers`

## gcloudの設定を変更する

- 新しいgcloudのコンフィグの設定をする（初回）

インスタンスのターミナルで以下のコマンドを実行します。
細かい設定は公式資料を参照したほうが良いかと思いますが……。

https://cloud.google.com/sdk/docs/initializing?hl=ja

```
gcloud init
```
現在の設定が表示されます。

```
Settings from your current configuration [現在のコンフィグ名] are:
core:
  account: [アカウント名]
  disable_usage_reporting: 'True'
  project: [プロジェクト名]

Pick configuration to use:
 [1] Re-initialize this configuration [現在のコンフィグ名] with new settings 
 [2] Create a new configuration
 [3] Switch to and re-initialize existing configuration: [default]
 [4] Switch to and re-initialize existing configuration: [別のコンフィグ名など]
```

`[2]Create a new configuration`を実行し、適切なコンフィグ名をつけます。

アカウントを選択します。
選択肢に出てこない場合は`Log in with a new account`を選択し、アカウントを選択します。
（適宜、URLをたたいて認証する作業が必要です。）

```
Choose the account you would like to use to perform operations for this configuration:
 [1] [既存のアカウント]
 [2] [既存のアカウント]
 [3] Log in with a new account
Please enter your numeric choice:  
```

プロジェクトは、この先の作業には関係ありませんが、デフォルトで普段開発に使っているものがあればそれでよいかと思います。
お金がかかったりするので、わざわざ新規に作成しなくてよいと思いますが、選ぶ必要はあります。

```
Do you want to configure a default Compute Region and Zone? (Y/n)?  
```

これはNo(n)で構いません。

## Artifact Registoryに対する認証情報を設定する

- config.jsonを（一応）バックアップする

設定を間違ったときに戻れるようにしておきましょう。

```
cp ~/.docker/config.json ~/.docker/config.json.bak
```

- 認証情報を設定
指定したリージョンのDockerレジストリに対する認証情報を設定し、Docker CLIがそのレジストリにアクセスできるようにします。

```
gcloud auth configure-docker REGION-docker.pkg.dev
```

## Dockerイメージをpushする

さて、ここからが本番です。
インスタンスのターミナルを開いて、Dockerイメージをpushしていきます。

前準備として、ターゲットのDockerイメージにタグをつけます。

https://cloud.google.com/artifact-registry/docs/docker/pushing-and-pulling?hl=ja#tag

```
docker tag <source_image> <target_image>:<tag>
```

**この時のタグはArtifact RegistryのリポジトリのURLを含んだものになります。**

つまり、こんな感じになります。

```
docker tag IMAGE-NAME:latest REGION-docker.pkg.dev/PROJECT-ID/containers/IMAGE-NAME:TAG-NAME
```

タグをつけたら、いざpushです。

```
docker push REGION-docker.pkg.dev/PROJECT-ID/containers/IMAGE-NAME:TAG-NAME
```

成功ログが出ると、相手方のArtifact RegistoryにDockerイメージが配置されます。
ブラウザから確認します。

`https://console.cloud.google.com/artifacts/docker/[PROJECT-ID]/[REGION]/containers`

## ハマったポイント：Artifact Registryにフォルダという概念はない

Dockerのイメージ名（上の例だと`IMAGE-NAME`）＝リポジトリというのが理解できておらず、**保存場所を指定しようと思って**何度も失敗しました。たとえば、testフォルダにおいてあげようと思って、「REGION-docker.pkg.dev/PROJECT-ID/containers/test/`IMAGE-NAME`」というようなURLにしてしまっていました。

**そんなリポジトリはない**ので、「test/IMAGE-NAME」という名前のDockerイメージができるだけです。

Stackoverflowに同じ悩みを持っていた人がいました。

https://stackoverflow.com/questions/73209891/gcp-artefact-registry-does-not-allow-sub-directories-to-organise-the-images-dev

先方が「ここにおいてください」といった場合、暗にイメージ名も指定しているということになります。
（削除権限がなかったので、依頼して消してもらわないといけなかった……。）

できれば、アクセス権限の確認もかねて、本番の前にpushの練習をさせてもらうといい感じです。

## 発展：Dockerイメージのpushをスクリプトで行う

毎回やっていると人為的ミスを誘発しそうだったので、おすすめされてスクリプトにしました(Linux用)。
タグ名だけを入力してもらい、いつものリポジトリにpushするスクリプトです。
`IMAGE-NAME`や`REGION`、`PROJECT-ID`などは書き換える必要があります。
`$TAG_NAME`だけはつどの入力です。

```bash
#!/bin/bash

# 初回は権限を与える必要がある
# chmod +x push_image.sh
# イメージ名を変更したい場合は、以下のIMAGE-NAME部分を編集すること（イメージ名）

# タグ名をユーザーから入力させる
echo "Enter the tag name for the Docker image:"
read TAG_NAME

# Docker イメージをタグ付け
echo "Tagging the Docker image..."
docker tag IMAGE-NAME:latest REGION-docker.pkg.dev/PROJECT-ID/containers/IMAGE-NAME:$TAG_NAME

# タグ付けしたイメージをプッシュ
echo "Pushing the Docker image..."
docker push REGION-docker.pkg.dev/PROJECT-ID/containers/IMAGE-NAME:$TAG_NAME

if [ $? -eq 0 ]; then
    echo "Image pushed successfully with tag '$TAG_NAME'."
else
    echo "Failed to push the image."
fi
```