📦

Artifact Registryを単体で色々試す

に公開

概要

今回は普段何気なく使っている Artifact Registry を単体で色々試してみようという試みです。gcloud CLIとTerraformを使って試してみた記事になります。

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

サポートされている形式

image1.png

Dockerだけかと思っていましたが、色々とサポートしているんですね…

サービスの有効と無効を切り替える

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

  • 現在有効になっているか確認

    gcloud services list --enabled --project={projectId} | grep artifactregistry.googleapis.com
    
  • 有効化

    gcloud services enable artifactregistry.googleapis.com --project={projectId}
    
  • 無効化

    gcloud services disable artifactregistry.googleapis.com --project={projectId}
    

Dockerイメージを保存する

リポジトリの作成

試しに Docker 形式のリポジトリを作成してみます。以下のスクリプトを作成し create_repository.sh というファイル名で保存します。

#!/bin/bash

set -e

# 使用方法の表示
usage() {
    echo "Usage: $0 <repository> <repository_format> <location> <description>"
    echo "  repository: リポジトリ名"
    echo "  location: リージョン(例: asia-northeast1)"
    echo "  repository_format: docker | npm | maven | python | apt..."
    echo "  description: リポジトリの説明"
    echo "  project_id: プロジェクトID"
    exit 1
}

# 引数のチェック
if [ $# -ne 5 ]; then
    usage
fi

# LOCATIONに関しては gcloud artifacts locations list で確認できます
REPOSITORY=$1
REPOSITORY_FORMAT=$2
LOCATION=$3
DESCRIPTION=$4
PROJECT_ID=$5

# --immutable-tags: 常に同じイメージ ダイジェストを指すタグを使用する(必要あれば)
# --async: 処理中のオペレーションの完了を待たない
# --disable-vulnerability-scanning: 脆弱性スキャンを無効にする(必要あれば有効に)
gcloud artifacts repositories create $REPOSITORY \
    --repository-format=$REPOSITORY_FORMAT \
    --location=$LOCATION \
    --description=$DESCRIPTION \
    --async \
    --disable-vulnerability-scanning \
    --project=$PROJECT_ID

ターミナルで以下のように実行するとリポジトリを作成出来ます。

$ chmod +x create_repository.sh
$ ./create_repository.sh sample-repository docker asia-northeast1 sample projectA

成功すると、コンソール画面で👇の様にリポジトリが作成できているかと思います。

image2.png

PushするDockerイメージ

シンプルな以下のDockerfileを作成し、Pushしてみます。

FROM node:22.7.0-bullseye-slim
CMD ["node", "-e", "console.log('Hello, World from Node.js in Docker!')"]

※ Pushする前に事前に各リージョンのDockerリポジトリの認証を設定する必要があります。

# 例) リージョンがasia-northeast1の場合
$ gcloud auth configure-docker asia-northeast1-docker.pkg.dev --project=projectA
Adding credentials for: asia-northeast1-docker.pkg.dev
After update, the following will be written to your Docker config file located at [/root/.docker/config.json]:
 {
  "credHelpers": {
    "asia-northeast1-docker.pkg.dev": "gcloud"
  }
}

Do you want to continue (Y/n)?  Y

Docker configuration file updated.

これをやっておかないと👇の様なエラーが発生します。

denied: Unauthenticated request. Unauthenticated requests do not have permission "artifactregistry.repositories.uploadArtifacts" on resource "projects/xxxxxx/locations/asia-northeast1/repositories/sample-repository" (or it may not exist)

準備ができたので、早速Dockerイメージをビルドして、作成したリポジトリにPushするスクリプトを書いてみます。以下の内容で build_and_push_docker.sh ファイルを作成します。

#!/bin/bash

set -e

usage() {
    echo "Usage: $0 <repository> <location> <project_id>"
    echo "  repository: リポジトリ名"
    echo "  location: リージョン(例: asia-northeast1)"
    echo "  project_id: プロジェクトID"
    echo "  app: アプリケーション名"
    exit 1
}

# 引数のチェック
if [ $# -ne 4 ]; then
    usage
fi

REPOSITORY=$1
LOCATION=$2
PROJECT_ID=$3
APP=$4

docker build -t ${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${APP}:latest .
docker push ${LOCATION}-docker.pkg.dev/${PROJECT_ID}/${REPOSITORY}/${APP}:latest

実行します。

$ chmod +x build_and_push_docker.sh
$ ./build_and_push_docker.sh sample-repository asia-northeast1 projectA my-node-app

成功すると、コンソール上で👇の様にDockerイメージがPushできているのが確認できるかと思います。

image3.png

リポジトリの削除

リポジトリの削除もスクリプトを作成して実行するようにしてみます。以下内容で delete_repository.sh ファイルを作成します。

#!/bin/bash

set -e

usage() {
    echo "Usage: $0 <repository> <location> <project_id>"
    echo "  repository: リポジトリ名"
    echo "  location: リージョン(例: asia-northeast1)"
    echo "  project_id: プロジェクトID"
    exit 1
}

# 引数のチェック
if [ $# -ne 3 ]; then
    usage
fi

REPOSITORY=$1
LOCATION=$2
PROJECT_ID=$3

gcloud artifacts repositories delete $REPOSITORY \
    --location=$LOCATION \
    --project=$PROJECT_ID \
    --async

上記を実行してリポジトリが削除されていればOKです。

$ chmod +x delete_repository.sh
$ ./delete_repository.sh sample-repository asia-northeast1 projectA

Terraformを使ってリポジトリ作成

まずはTerraform が使用する認証ファイルを作成します。

gcloud auth application-default login --no-launch-browser

~/.config/gcloud/application_default_credentials.json が作成されます。

次に xxx-tfstate バケットを作成し、TerraformのtfstateをGCSで管理できるようにします。

$ gsutil mb -l asia-northeast1 gs://xxx-tfstate
$ gsutil versioning set on gs://xxx-tfstate
$ gsutil lifecycle set tfstate_lifecycle.json gs://xxx-tfstate
$ gsutil ls # バケット一覧確認

早速 Artifact Registryのリポジトリ作成を実装してみたいと思います。

一応 modules/artifact_registry をメインから呼び出すような形で実装していきます。

  • modules/artifact_registry/main.tf
variable "location" {}
variable "repository_id" {}
variable "description" {}

resource "google_artifact_registry_repository" "docker_format_repository" {
  location      = var.location
  repository_id = var.repository_id
  description   = var.description
  format        = "DOCKER"

  docker_config {
    immutable_tags = false
  }
}
  • artifact_registry/main.tf
provider "google" {
  project = "..."
}

terraform {
  backend "gcs" {
    bucket = "xxx-tfstate"
  }
}

module "artifact_registry" {
  source        = "../../modules/artifact_registry"
  location      = "asia-northeast1"
  repository_id = "sample-repository"
  description   = "description"
}

artifact_registry/main.tf がある場所で以下コマンドを実施するとリポジトリが作成できているかと思います。

$ terraform init
$ terraform plan
$ terraform apply

npmで管理するNode.jsパッケージを保存する

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

次にNode.jsパッケージを管理できるようにしてみたいと思います。

リポジトリの作成

早速リポジトリを作成していきます。先程作成した create_repository.sh を使ってリポジトリを作成していきます。

$ ./create_repository.sh sample-npm-repository npm asia-northeast1 sample-npm projectA

成功すれば「形式」が npm のリポジトリが作成されるかと思います。

image4.png

管理するNode.jsパッケージの作成

今回は @sample-npm スコープのパッケージを作成します。スコープに関しては👇を参照して下さい。

https://docs.npmjs.com/about-scopes

$ mkdir sample-npm-package
$ cd sample-npm-package
$ npm init --scope=@sample-npm -y

この時に作成された package.json は以下になります。

{
  "name": "@sample-npm/sample-npm-package",
  "version": "1.0.0",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "description": ""
}

ただ文字列を返す hello functionがあるだけの index.js も作成しときます。

const hello = () => {
  return "Hello from Artifact Registry!";
};
module.exports = hello;

Node.jsパッケージの公開先設定

@sample-npm スコープの公開先を先程作成した sample-npm-repository に設定します。

その為に sample-npm-package/.npmrc ファイルを以下のスクリプトの出力結果の内容で作成します。

#!/bin/bash
# example: ./print_setting_npmrc.sh sample-npm-repository asia-northeast1 @sample-npm projectA

set -e

# 使用方法の表示
usage() {
    echo "Usage: $0 <repository> <location> <scope> <project_id>"
    echo "  repository: リポジトリ名"
    echo "  location: リージョン(例: asia-northeast1)"
    echo "  scope: npm スコープ (例: @sample-npm)"
    echo "  project_id: プロジェクトID"
    exit 1
}

# 引数のチェック
if [ $# -ne 4 ]; then
    usage
fi

# LOCATIONに関しては gcloud artifacts locations list で確認できます
REPOSITORY=$1
LOCATION=$2
SCOPE=$3
PROJECT_ID=$4

gcloud artifacts print-settings npm --scope=$SCOPE \
    --repository=$REPOSITORY \
    --location=$LOCATION \
    --project=$PROJECT_ID

Node.jsパッケージのアップロード

Artifact Registry リポジトリの認証情報を反映する為に、 google-artifactregistry-auth を使用します。sample-npm-package の package.json に以下を追加します。

"scripts": {
  "artifactregistry-login": "npx google-artifactregistry-auth"
}

追加したら早速実行します。

$ npm run artifactregistry-login
Retrieving application default credentials...
Retrieving credentials from gcloud...
Success!

ここまで出来たらパッケージをアップロードします。

npm publish \
    --scope=@sample-npm \
    --registry=https://asia-northeast1-npm.pkg.dev/projectA/sample-npm-repository/

成功するとコンソール上でもパッケージが確認できるかと思います。

image5.png

アップロードしたNode.jsパッケージを使う

最後にアップロードしたNode.jsパッケージを利用してみたいと思います。

$ mkdir use-sample-npm-package
$ cd use-sample-npm-package
$ npm init -y

use-sample-npm-package というパッケージを作成し、先程作成した .npmrc をこちらにもコピーします。

 cp sample-npm-package/.npmrc use-sample-npm-package/.

準備が整ったので早速インストールしてみます。

npm install @sample-npm/sample-npm-package

正しくインストールされたか use-sample-npm-package/index.js を以下の内容で作成し実行してみます。

const hello = require('@sample-npm/sample-npm-package');

console.log(hello());

正しくインストール&実行されると以下の様に出力されるかと思います。

$ node index.js
Hello from Artifact Registry!

バッドノウハウ

もしVSCodeのDevcontainerを使っていて、Docker in Docker で使っていた場合に、VSCodeのターミナルを使わず、別のターミナルでDockerイメージのビルド時に以下のエラーが発生する事があります。

ERROR: failed to solve: hayd/alpine-deno:1.10.2: failed to resolve source metadata for docker.io/hayd/alpine-deno:1.10.2:
error getting credentials - err: exit status 255, out: ``

すぐできる解決方法としてはVSCodeのターミナル上でDockerイメージをビルドしたらうまくいきます。詳細は👇を参照。

https://qiita.com/suin/items/5bab337469248e3d3a4e

FYI 料金

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

  • ストレージ
    • 月0.5GBまで無料で超えたらGB単位で $0.10 かかる
  • データ転送
    • 同一リージョンまたは同一マルチリージョン / リージョン↔同大陸マルチリージョン は無料
    • それ以外は別途料金がかかる

参考URL

https://developer.so-tech.co.jp/entry/publish-private-npm-packages-with-artifact-registry

Discussion