Artifact Registryを単体で色々試す
概要
今回は普段何気なく使っている Artifact Registry を単体で色々試してみようという試みです。gcloud CLIとTerraformを使って試してみた記事になります。
サポートされている形式
Dockerだけかと思っていましたが、色々とサポートしているんですね…
サービスの有効と無効を切り替える
-
現在有効になっているか確認
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
成功すると、コンソール画面で👇の様にリポジトリが作成できているかと思います。
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できているのが確認できるかと思います。
リポジトリの削除
リポジトリの削除もスクリプトを作成して実行するようにしてみます。以下内容で 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パッケージを保存する
次にNode.jsパッケージを管理できるようにしてみたいと思います。
リポジトリの作成
早速リポジトリを作成していきます。先程作成した create_repository.sh
を使ってリポジトリを作成していきます。
$ ./create_repository.sh sample-npm-repository npm asia-northeast1 sample-npm projectA
成功すれば「形式」が npm
のリポジトリが作成されるかと思います。
管理するNode.jsパッケージの作成
今回は @sample-npm
スコープのパッケージを作成します。スコープに関しては👇を参照して下さい。
$ 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/
成功するとコンソール上でもパッケージが確認できるかと思います。
アップロードした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イメージをビルドしたらうまくいきます。詳細は👇を参照。
FYI 料金
- ストレージ
- 月0.5GBまで無料で超えたらGB単位で
$0.10
かかる
- 月0.5GBまで無料で超えたらGB単位で
- データ転送
- 同一リージョンまたは同一マルチリージョン / リージョン↔同大陸マルチリージョン は無料
- それ以外は別途料金がかかる
参考URL
Discussion