AWS CodeArtifactでパッケージを共有してみる(Node.js)

はじめに

はじめまして!初投稿のtadaと申します

アプリケーション開発の中で複数のサービスから共通リソースを扱う場合など、時間をかけて開発したパッケージを使いまわしたいという場面に直面することがあるかと思います

その場合パッケージをどう共有するかが問題になりますが、デフォルトのレジストリにアップロードした場合、誤って公開設定になってしまわないかという不安がありますし、Node.js npmを例にとるとプライベートパッケージをアップロードするにはユーザー数に応じた月額費用がかかってしまいます

https://www.npmjs.com/products

かといって社内環境にプライベートリポジトリを構築・運用するには冗長化/スケール/セキュリティ...などたくさんの課題をクリアする必要があり、それだけで時間をとられてしまいます

このようにプライベートリポジトリが手軽に欲しいケースにおいて、2020年6月にGAリリースとなったAWS CodeArtifact サービスがマッチしていそうでしたので Node.js npmパッケージでCodeArtifactを使ってみました

目次

AWS CodeArtifactとは

サービス概要

CodeArtifactは、フルマネージドのアーティファクトリポジトリサービスであり、組織がアプリケーション開発に使用するソフトウェアパッケージを安全に保存および共有できるようにします

https://docs.aws.amazon.com/ja_jp/codeartifact/latest/ug/welcome.html

と記載がある通り、CodeArtifactを使うことで自作パッケージをAWS上のプライベートなリポジトリ上で共有できます

執筆時点で下記の言語 : パッケージマネージャに対応しています

  • .Net : NuGet
  • Java : Maven, Gradle
  • Node.js : npm, yarn
  • Python : pip, twine

用語:リポジトリ

リポジトリはパッケージを格納するリソースです。パッケージマネージャの接続先として指定します

リポジトリは別のリポジトリのアップストリームリポジトリとすることができ、ダウンストリームリポジトリに接続したクライアントはアップストリームリポジトリ内のパッケージへも透過的にアクセスできます

npmjs.com のようなデフォルトのパブリックリポジトリも、CodeArtifactではアップストリームリポジトリの1つとして扱います

用語:ドメイン

ドメインはリポジトリを集約管理するエンティティです

複数のリポジトリにまたがる組織的なポリシーを適用することが可能です

組織は複数のドメインを持つことができますが、チームが組織全体でパッケージを検索して共有できるように、公開されたすべてのアーティファクトを含む 単一のプロダクションドメインを使用することをお勧めします。

https://docs.aws.amazon.com/ja_jp/codeartifact/latest/ug/codeartifact-concepts.html

料金

AWS CodeArtifact に前払い料金などの義務はありません。お客様は、使用した分 (保存したアーティファクトのサイズ、行われたリクエストの数、および AWS リージョンから転送されたデータの量) についてのみ支払います。

https://aws.amazon.com/jp/codeartifact/pricing/

また無期限の無料枠として 最初の 2 GB/月のストレージ、最初の 100,000 リクエスト/月、インターネットから AWS CodeArtifact へのデータ転送 (イン)がありますので非常に安価に使い始めることができます

実践:CodeArtifactへパッケージをアップロードしてみる

パッケージ作成

それでは実際にnpmパッケージを作ってリポジトリへアップロードしてみます

作成するパッケージは単純なGetterのみを持つ Point クラスです。ソースはTypeScriptで記述し「src」ディレクトリへ格納、コンパイル後のjsファイルは「dist」に出力することとします

$ npm init -y

作成されたpackage.jsonを編集します

  "name": "@cci-techblog/point",
  "main": "./dist/index.js",
  "files": [
    "dist"
  ],

name = @名前空間 を付与しパッケージ名の衝突が起きないように修正します

main = コンパイル後のファイルを指すようにします

files = ここが重要なポイントです。デフォルトではパッケージリポジトリにアップロードされるファイルはディレクトリ内のすべてのファイルから、 .gitignore, .npmignore に記載されたファイルを引いたものになります

余分なファイルも含んでしまいますし、.gitignoreにdistディレクトリが指定されているとアップロードすることができなくなってしまいます

そのため files 設定を明示的に行い、dist ディレクトリをアップロード対象に選択しています

次に TypeScript用プロジェクトをセットアップします

$ tsc --init

作成された tsconfig.json を編集します

  "include": ["src/**/*"], /* コンパイルの入力ディレクトリ */
  "compilerOptions": {
    "outDir": "./dist", /* コンパイルの出力ディレクトリ */
    "declaration": true, /* 型宣言ファイルの生成 */

ソースを記述します

ファイル名:src\index.ts

export * from "./Point";

ファイル名:src\Point.ts

export class Point {
    private name: string;
    private x: number;
    private y: number;

    constructor(name:string, x:number, y:number) {
        this.name = name;
        this.x = x;
        this.y = y;
    }

    public getName(): string {
        return this.name;
    }

    public getX(): number {
        return this.x;
    }

    public getY(): number {
        return this.y;
    }
}

記述したソースをコンパイルし「dist」以下に.js/d.ts ファイルを生成します

$ tsc

CodeArtifact リポジトリ作成

AWS側リソースを作成していきます

まずはAWSコンソールにログインし CodeArtifact > ドメイン > ドメインを作成 を行います

CodeArtifact > リポジトリ > リポジトリを作成 を行います。パブリックアップストリームリポジトリに「npm-store」を指定します

Nextを押すとドメイン選択画面が出ますので「このAWSアカウント(アカウントID)」を選択し、先ほど作成したドメインを選択します

確認画面ではパッケージフローを視覚的に表示してくれます。設定値を確認しリポジトリを作成します

パッケージアップロード

まずはAWS CLIを使用し CodeArtifact に認証を通す必要があります

$ aws codeartifact login --tool npm --repository test-repo --domain test-domain --domain-owner 111122223333

※domain-ownerはAWSアカウントID

このコマンドは、 ~/.npmrc ファイルに次の変更を加えます:

・AWS 認証情報を使用して CodeArtifact からそれを取得した後、認可トークンを追加します。

・npm レジストリを、--repository オプションで指定されたリポジトリに設定します。

npm 6 以下の場合: を追加します。"always-auth=true"したがって、認可トークンはすべての npm コマンドに対して送信されます。

https://docs.aws.amazon.com/ja_jp/codeartifact/latest/ug/npm-auth.html

loginコマンドによりnpmレジストリがCodeArtifactリポジトリに設定されましたので $ npm publish で npmパッケージをアップロードします

$ npm publish
npm notice
npm notice 📦  @cci-techblog/point@1.0.0
npm notice === Tarball Contents ===
npm notice 26B  dist/index.d.ts
npm notice 645B dist/index.js
npm notice 204B dist/Point.d.ts
npm notice 394B dist/Point.js
npm notice 269B package.json
npm notice === Tarball Details ===
npm notice name:          @cci-techblog/point
npm notice version:       1.0.0
npm notice filename:      @cci-techblog/point-1.0.0.tgz
<省略>
npm notice total files:   5
npm notice
npm notice Publishing to https://test-domain-111122223333.d.codeartifact.ap-northeast-1.amazonaws.com/npm/test-repo/
+ @cci-techblog/point@1.0.0

CodeArtifact リポジトリ管理画面からパッケージが確認できればアップロード完了です!

実践:CodeArtifactのパッケージをインストール

それではアップロードしたパッケージを新規プロジェクトから利用してみます

新規ディレクトリ「sample」に移動し $ npm init -y $ tsc --init と実行します

CodeArtifact の認証を通します

$ aws codeartifact login --tool npm --repository test-repo --domain test-domain --domain-owner 111122223333

CodeArtifactリポジトリに存在するパッケージをインストールします

$ npm install @cci-techblog/point

ソースを記述します

ファイル名:index.ts

import { Point } from '@cci-techblog/point';

const tokyo = new Point("東京", 140, 36);
const osaka = new Point("大阪", 135, 34);

console.log(`${tokyo.getName()}は東経${tokyo.getX()}度、北緯${tokyo.getY()}度`);
console.log(`${osaka.getName()}は東経${osaka.getX()}度、北緯${osaka.getY()}度`);

コンパイルし実行します

$ tsc

$ node index.js
東京は東経140度、北緯36度
大阪は東経135度、北緯34度

自作パッケージのクラスが利用できることが確認できました!

~/.npmrc ファイルを削除すればnpmの接続先リポジトリもデフォルトに戻ります

最後に

今回お試しで1リポジトリしか使いませんでしたが、実際に使い始める際は利用側の接続エンドポイントとしてダウンストリームリポジトリを別に用意するなどリポジトリ構成を少し考えた方が便利かもしれません(下図のような)

ですが非常に簡単に使え コストも安く セキュアで便利なサービスだと感じました

作成したパッケージを共有すれば開発にかかる時間を大幅に短縮できると思います!