ソリューション技術部の斎藤です。
弊社では、社内でNPMパッケージを管理するライブラリとしてVerdaccio
を利用しています。
Verdaccioは、無料でプライベートなNPMレジストリを作成できるNPMパッケージです。
ローカルのNPMレジストリ参照先を、公式のNPMレジストリからVerdaccioで作成したプライベートレジストリに変更することで既存のNPMコマンドを利用できます。
プライベートレジストリに存在しないNPMパッケージをインストールしようとした場合にも、自動で公式のNPMレジストリに問い合わせを行います。
また、publishしたNPMパッケージをWeb画面上で確認することができ、画面上でダウンロードなども行えます。
リポジトリ管理されているパッケージの歴代バージョンも確認できます。
弊社では数年前からVerdaccioにお世話になっていましたが、時間経過とともにNPMパッケージが増え、徐々にEC2のディスクが圧迫されるようになってきました。
調べたところ、現在のVerdaccioバージョンではストレージ先をローカルからS3に変更できるとのことだったので、
ストレージ変更をおこなうとともに、Verdaccioのバージョンアップも行いましたのでその手順についてまとめました。
作業の流れ
今回の作業は、AWSで別サーバを用意して行います。
- 現行サーバのEC2ローカルからS3へのNPMパッケージ移行
- 新規サーバへのVerdaccioインストール
- Verdaccioの設定ファイル更新
- 新旧サーバ切替(Route 53)
NPMパッケージの移行
まずは、EC2のローカル上にあるNPMパッケージをS3に移行します。
バージョンアップ時に利用できるmigrationツールをVerdaccio公式が用意していましたが、
今回はストレージがS3への変更になるので、こちらは使わず、下記スクリプトを流してデータ移行しました。
S3に移行先となるバケットを作成して、作成したバケット名を下記スクリプトに指定します。
dirpath
は、現行サーバのVerdaccioのローカルストレージディレクトリの場所です。
下記は、ec2-user
のホームディレクトリにVerdaccioディレクトリが置かれている場合の例です。
#!/bin/sh dirpath="/home/ec2-user/verdaccio/storage/*" for package in $dirpath; do if [[ ! $filepath =~ ^@.* ]] && [ -d $filepath ] ; then package_name=$(basename ${package}) echo $package_name aws s3 cp /home/ec2-user/verdaccio/storage/"$package_name" s3://【S3バケット名】/"$package_name" --recursive fi done
新サーバへのインストール
NPMパッケージをS3にコピーしている間に、Verdaccioの設定ファイルを更新します。
サーバ設定の反映については、ansible
を使用します。
※今回の記事では、EC2構築手順については省略します。
nodejsのバージョン
今回はnode v16系にします。
# roles/nodejs/tasks/main.yml - name: node source shell: curl --silent --location https://rpm.nodesource.com/setup_16.x | bash - - name: install nodejs yum: name: nodejs
Verdaccio最新バージョンを入れる → バージョン固定に
Verdaccioのバージョンはlatest
を指定して作業していましたが、頻繁にアップデートされているプロジェクトのようで
作業時の最新バージョンではバグがあったようで起動しなくなってしまいましたのでバージョンは固定することにしました。
また、pm2で起動しますので最新バージョンを入れておきます。
# roles/nodejs/tasks/main.yml - name: install global npm packages npm: name={{ item.name }} version={{ item.version }} global=yes with_items: - { name: verdaccio, version: 'v5.19.1' } - { name: verdaccio-aws-s3-storage, version: latest } - { name: pm2, version: latest }
設定ファイルを置く場所を指定します。
下記は、ec2-user
で起動、ec2-userのホームディレクトリにVerdaccioディレクトリが置かれる場合の例です。
# roles/nodejs/tasks/main.yml - name: VERDACCIO | Put config.yaml copy: src: roles/nodejs/files/config.yaml dest: /home/ec2-user/verdaccio/config.yaml owner: ec2-user group: ec2-user - name: Put ecosystem.config.js copy: src: roles/nodejs/files/ecosystem.config.js dest: /home/ec2-user/verdaccio/ecosystem.config.js owner: ec2-user group: ec2-user
ここまでできたら一度ansible-playbook
コマンドで新サーバへ反映して、インストールを確認します。
Verdaccio設定ファイルの更新
こちらもansible-playbook
で反映します。
先程までの作業で、サーバ上にVerdaccioがインストールされていればconfig.yml
が指定ディレクトリに置かれていると思いますので
インストールされたYAMLファイルを更新していきます。
Verdaccioのストレージ変更
verdaccio S3 plugin
を利用します。
verdaccio S3 plugin github.com
設定ファイルのstorage
をコメントアウトして、store
以下を記載して設定します。
# roles/nodejs/files/config.yaml # path to a directory with all packages # storage: ./storage store: aws-s3-storage: bucket: 【S3バケット名】 region: 【リージョン】 accessKeyId: 【アクセスキーID】 secretAccessKey: 【シークレット】
ついでに日本語化
日本語化されていませんでしたので、localeを設定します。
# roles/nodejs/files/config.yaml i18n: web: ja-JP
pm2の設定
# roles/nodejs/tasks/main.yml - name: create pm2 startup script shell: sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u ec2-user --hp /home/ec2-user - name: pm2 startup script save shell: pm2 save - name: start app shell: pm2 startOrRestart /home/ec2-user/verdaccio/ecosystem.config.js become: false
その他設定は状況に応じて適宜変更して(ログファイルやローテートの設定など)、再度ansible-playbook
コマンドを実行します。
コマンド実行が成功すると、pm2がVerdaccioを起動して、ブラウザでVerdaccioが見れるようになる!…はずだったのですが
VerdaccioのjsのhostがローカルIPになってしまう
ブラウザで確認しようとしたところ、真っ白な画面が…。
Webコンソールで確認したところ、どうやら、Verdaccioのjsファイルのhost名にローカルIPが指定されているようです。
下記を参考に、環境変数でVERDACCIO_PUBLIC_URL
を設定することにします。
この設定はVerdaccioのconfigファイルでは設定できないようなので、こちらもansible-playbook
に追記します。
この時点ではまだ現行サーバで利用しているドメインに切り替えていませんので、一旦ALBのURLを指定します。
# roles/nodejs/files/environment VERDACCIO_PUBLIC_URL='【ALBのURL】'
環境変数を記載したenvironmentファイルを設置する設定も追記します。
# roles/nodejs/tasks/main.yml - name: VERDACCIO | Put /etc/environment copy: src: roles/nodejs/files/environment dest: /etc/environment
これをansible-playbook
コマンドで再反映すると、ブラウザで画面が見れるようになりました。
最初に実行していたS3へのパッケージ移行スクリプトが完了していたら、npm
コマンドをいくつか実行して動作確認してみます。
npm publish/unpublish
実行時には、S3バケット内も確認します。
$ npm config set registry 【ALBのURL】 $ npm adduser $ npm login $ npm publish $ npm unpublish [package name@xx.xx.xx]
サーバ切り替え
一通りの動作が確認できましたら、Route 53でドメインを切り替えます。
ansible-playbook
でALBのURLが設定されている箇所を切り替え後のドメインを設定し直し、再度ansible-playbook
コマンドを実行します。
作業後、切り替え後のドメインで先程のVerdaccioの画面が見れること、npm
コマンドが実行できることを確認できたら完了です。
※旧サーバのEC2インスタンスを停止させるのを忘れずに…
サーバ切り替え後に問題が…
これで作業は完了したと思っていたのですが、サーバ移行後しばらくしてからブラウザからVerdaccioにアクセスすると、
NPMパッケージが空っぽの状態(Verdaccio初期設定ページが表示されている)になっていました。
これは私がうっかりしていたのですが、セッションマネージャーからサーバに入った際にも、pm2を起動してしまっていたようで
ssm-user
とec2-user
の両方でpm2が二重起動されている状態でした。
ssm-user
のpm2ではALBのURLが参照されていたため、なにかのタイミングでこちらのpm2が参照されたとき、
クロスドメインによるエラーでNPMパッケージ一覧が取得できなくなっていました。
ssm-user
のpm2をkillして解決。
Verdaccio自体は200が返りますのでヘルスチェックも通ってしまっていたので、ブラウザにアクセスするまで気付けませんでした。
NPMパッケージが1件も取れなくなった場合にはアラートを飛ばすようにしたほうがいいかもしれません。(今後の課題)
まとめ
細々ハマった箇所はありましたが、設定自体はとてもシンプルで分かりやすい構造になっていると思います。
プライベートNPMレジストリを気軽に構築したい方は、ぜひお試しください。