GitLab Package Registryをローカル環境で試してみた

こんにちは。ウェブ開発室基盤開発チームのOです。

 

coconeでは、社内のnpmパッケージの管理に npm private registry を利用しています。

npm private registryの利用には、npmのアカウントまたはnpmのトークンが必要です。 npmアカウントを持っていない人がパッケージを利用する機会が増えてきたため、一部プロジェクトでは GitLabのプライベートリポジトリURLをpackage.jsonに指定し、対象パッケージが入っているグループの読み取り権限を利用者に付与する対応をしています。
Creating and viewing access tokens にあるように、Read-only access tokenを利用する方法もありますが使っていません。)

 

npmパッケージの今後の運用方法を模索していたところ、GitLab には GitLab Package Registry があり、 GitLab NPM Registry を使ってパッケージ管理できることがわかりました。 GitLabリポジトリとGitLab CI/CDとの連携でパッケージ管理ができそうなので、移行の前にGitLab Package Registryの動作をローカル環境で検証してみました。

 

検証環境

docker-composeを使ってGitLab及びGitLab Runnerローカル環境を作ります。
試したDockerとdocker-composeのバージョンは下記です。

$ docker --version
Docker version 20.10.8, build 3967b7d
$ docker-compose --version
docker-compose version 1.29.2, build 5becea4c

GitLabの導入

GitLab公式ドキュメント|GitLab Docker images を参考に、GitLab用のディレクトリ(config, logs, data)と docker-compose.yml を作成します。
使用するDockerイメージは、記事執筆時点での社内環境に合わせています。

docker-compose.yml

  1. version: “3”
  2. services:
  3.   web:
  4.     image: “gitlab/gitlab-ee:13.12.4-ee.0”
  5.     restart: always
  6.     hostname: “localhost”
  7.     environment:
  8.       GITLAB_OMNIBUS_CONFIG: |
  9.         external_url ‘http:/localhost:9010’
  10.         gitlab_rails[‘gitlab_shell_ssh_port’] = 2022
  11.         gitlab_rails[‘time_zone’] = ‘Asia/Tokyo’
  12.     ports:
  13.       – “9010:9010”
  14.       – “443:443”
  15.       – “2022:22”
  16.     volumes:
  17.       – “./config:/etc/gitlab”
  18.       – “./logs:/var/log/gitlab”
  19.       – “./data:/var/opt/gitlab”

 

コンテナを起動

docker-compose.ymlが置いてあるディレクトリでdocker-compose upを実行します。
起動まで時間がかかりますのでしばらく待ちます。docker-compose psでSTATUSがhealthyになっていれば起動成功です。

$ docker-compose up -d
$ docker-compose ps
NAME COMMAND SERVICE STATUS PORTS
gitlab-test_web_1 "/assets/wrapper" web running (healthy)
0.0.0.0:2022->22/tcp, :::2022->22/tcp, 80/tcp, 0.0.0.0:443->443/tcp,
:::443->443/tcp, :::9010->9010/tcp, 0.0.0.0:9010->9010/tcp

 

しばらく待っても起動しない場合は、メモリ不足かもしれませんので確認してみましょう。
起動ログを見ると起動しない原因がわかる場合もあります。

$ docker-compose logs -f web # docker-compose logs -f <SERVICE>

GitLabにアクセス

ブラウザからGitLabにアクセスします。ポート番号はdocker-compose.ymlファイルに設定したものです。
http://localhost:9010へアクセスして、画面が表示されればOKです。
初めてアクセスする場合はrootユーザーのパスワード変更画面に遷移しますので、新しいパスワードを設定します。

 

 

無事にGitLab環境を作ることができました。

 

GitLab Package Registryを使う

NPM Package Registry用グループとプロジェクトの作成

今回はパッケージ用のグループを作成し、そのグループの中にNPM Package Registry用のプロジェクトを作成します。
グループメニューやプロジェクトメニューにPackages & Registriesが表示されていればGitLab Package Registryを使用することができます。

 

 

 

GroupのDeploy Tokenを作成

パッケージのpublishを行う人向けのDeploy Token(read_package_registry / write_package_registry )とパッケージを使う人向けのDeploy Token(read_package_registry)を作成します。
今回は、Group Deploy Tokenを作成します。

 

 

作成したDeploy Tokenは後ほど使うので忘れないようにメモしておきましょう。

 

Tokenの例

read/write package deploy token

read-write-deploy-token / jqCjrNx2JCpGvzF75T9y

 

read package deploy token

read-deploy-token / NojZWxP4fNxgi7s5cojJ

 

npmパッケージをpublishする

GitLab公式ドキュメント|GitLab NPM Registryを参考にして進めます。

パッケージ用のプロジェクトを作成後、GitLab NPM Registryへpublishするための設定をします。

NPM configuration

先程作成したDeploy Token(read-write-deploy-token)を使用します。
npm config setで設定するか、.npmrcファイルに設定します。

今回は、.npmrcファイルにDeploy Tokenとscoped packageのURLを設定します。


//localhost:9010/api/v4/packages/npm/:_authToken=jqCjrNx2JCpGvzF75T9y
//localhost:9010/api/v4/projects/2/packages/npm/:_authToken=jqCjrNx2JCpGvzF75T9y
@web-assets:registry=http://localhost:9010/api/v4/packages/npm/

設定の意味は、上から順番に以下の通りです。

  • scoped packageのURLのトークン追加。ダウンロードできるようになる
  • registryにアップロードするためのトークン追加。アップロードするプロジェクトのプロジェクトIDを設定
  • scoped packageのURLを設定。このURLをダウンロードに使用する。

アップロードするプロジェクトのプロジェクトIDは、先程作成したNPM Package Registry用のプロジェクトのプロジェクトIDです。
今回の例では、Project ID:2になります。

scoped package命名規則はGitLab公式ドキュメント|Package naming conventionをご参照ください。

package.json

パッケージ名とpublishの設定をします。

  1. {
  2.   “name”: “@web-assets/common-a”,
  3.   “version”: “1.0.0”,
  4.   “description”: “”,
  5.   “main”: “index.js”,
  6.   “scripts”: {
  7.     “test”: “echo \”Error: no test specified\” && exit 1″
  8.   },
  9.   “repository”: {
  10.     “type”: “git”,
  11.     “url”: http://localhost:9010/web-assets/packages/common-a.git&#8221;
  12.   },
  13.   “author”: “”,
  14.   “license”: “ISC”,
  15.   “publishConfig”: {
  16.     “@web-assets:registry”: http://localhost:9010/api/v4/projects/2/packages/npm/&#8221;
  17.   }
  18. }

 

publishConfigの設定の追加が必要になります。

publish

パッケージをpublishする準備ができましたので、以下のコマンドを実行してpublishしてみましょう。


$ npm publish
npm notice
npm notice 📦  @web-assets/common-a@1.0.0
npm notice === Tarball Contents ===
npm notice 31B  index.js
npm notice 435B package.json
npm notice === Tarball Details ===
npm notice name:          @web-assets/common-a
npm notice version:       1.0.0
npm notice package size:  728 B
npm notice unpacked size: 1.2 kB
npm notice shasum:        3cd598fc20792f0ff29e34b39d5a93d2c5646ebc
npm notice integrity:     sha512-vAt3FP510UxUJ[...]I/Bo3TDt7BiZA==
npm notice total files:   3
npm notice
+ @web-assets/common-a@1.0.0

NPM Package Registry用のプロジェクトのPackage Registryを確認します。

 

 

 

手動でのpublishに成功しました!
パッケージの詳細を見ると、インストールの方法やRegistryのセットアップ方法が記述されています。

次は GitLab CI/CDを使ってのpublishを試してみます。

 

GitLab Runnerの導入

docker-composeにGitLab Runnerを追加してからGitLab Runnerを登録します。
GitLabのAuto DevOpsがデフォルトですべてのプロジェクトに対して有効になっているので、GitLab Runnerを導入する前に無効にすることをオススメします。

GitLab Runner用のconfigディレクトリ(runner/config)とconfigファイル(runner/config/config.toml)を作成し、docker-compose.ymlを全体的に見直します。
Runner用のconfigファイル(config.toml)の中身は空で大丈夫です。

docker-compose.yml

  1. version: “3”
  2. services:
  3.   gitlab-ee.example.com:
  4.     image: “gitlab/gitlab-ee:13.12.4-ee.0”
  5.     restart: always
  6.     hostname: “gitlab-ee.example.com”
  7.     environment:
  8.       GITLAB_OMNIBUS_CONFIG: |
  9.         external_url http://gitlab-ee.example.com:9010&#8217;
  10.         gitlab_rails[‘gitlab_shell_ssh_port’] = 2022
  11.         gitlab_rails[‘time_zone’] = ‘Asia/Tokyo’
  12.     ports:
  13.       – “9010:9010”
  14.       – “443:443”
  15.       – “2022:22”
  16.     volumes:
  17.       – “./config:/etc/gitlab”
  18.       – “./logs:/var/log/gitlab”
  19.       – “./data:/var/opt/gitlab”
  20.     networks:
  21.       – gitlab-network
  22.   runner:
  23.     image: “gitlab/gitlab-runner:latest”
  24.     restart: always
  25.     depends_on:
  26.       – gitlab-ee.example.com
  27.     volumes:
  28.       – ./runner/config:/etc/gitlab-runner
  29.       – /var/run/docker.sock:/var/run/docker.sock
  30.     networks:
  31.       – gitlab-network
  32. networks:
  33.   gitlab-network:

 

コンテナを起動

networkが重複している場合は、–remove-orphansをつけて起動します。

コンテナ起動前のdocker networkの状況は以下です。(一部抜粋)


$ docker network ls
NETWORK ID     NAME                                             DRIVER    SCOPE
1d6eead741e3   gitlab-ee-demo_default                           bridge    local

docker-compose.ymlが置いてあるディレクトリでdocker-compose up -d –remove-orphansを実行し、runnerが起動されていることを確認します。


$ docker-compose up -d --remove-orphans
Creating network "gitlab-ee-demo_gitlab-network" with the default driver
Removing orphan container "gitlab-ee-demo_web_1"
Creating gitlab-ee-demo_gitlab-ee.example.com_1 ... done
Creating gitlab-ee-demo_runner_1                ... done

$ docker-compose ps
                 Name                               Command                  State                                                                  Ports
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
gitlab-ee-demo_gitlab-ee.example.com_1   /assets/wrapper                  Up (healthy)   0.0.0.0:2022->22/tcp,:::2022->22/tcp, 0.0.0.0:443->443/tcp,:::443->443/tcp, 80/tcp, 0.0.0.0:9010->9010/tcp,:::9010->9010/tcp
gitlab-ee-demo_runner_1                  /usr/bin/dumb-init /entryp ...   Up
sandbox/docker/gitlab-ee-demo

docker-compose.ymlで設定したdocker networkが作成されています。


$ docker network ls
NETWORK ID     NAME                                             DRIVER    SCOPE
1d6eead741e3   gitlab-ee-demo_default                           bridge    local
30f080db9d69   gitlab-ee-demo_gitlab-network                    bridge    local

GitLab Runnerの登録

セットアップ情報の確認

GitLab Runnerを登録するために必要な情報をGitLabで確認します。
GitLabに管理者アカウント(root)でログインし、shared runnerのセットアップ情報を確認します。ここに表示されているregistration tokenを使用します。

 

 

gitlab-runner register

Optionを指定して登録したいので、non-interactive modeでGitLab Runnerを登録します。


$ docker-compose exec runner gitlab-runner register -n \
                  --url http://gitlab-ee.example.com:9010/ \
                  --registration-token h31qsq27A1csvVRVsus5 \
                  --name my-runner \
                  --executor docker \
                  --docker-image node:14-alpine \
                  --docker-network-mode gitlab-ee-demo_gitlab-network
Runtime platform                                    arch=amd64 os=linux pid=20 revision=58ba2b95 version=14.2.0
Running in system-mode.

Registering runner... succeeded                     runner=h31qsq27
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!

–urlの設定は、GitLab上で表示されていたhttp://localhost:9010/ではなくて、http://gitlab-ee.example.com:9010/を設定しています。
これは、docker-compose.ymlのservice名とportになります。
詳細はComposeのネットワーク機能を参照してください。

–docker-network-modeには、新しく作成されたdocker network(gitlab-ee-demo_gitlab-network)を設定します。

GitLab Runnerの登録が成功したら、GitLab Runnerのconfig.tomlの中身を確認してみます。登録した内容で更新されているのがわかります。

$ docker-compose exec runner cat /etc/gitlab-runner/config.toml
concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "my-runner"
  url = "http://gitlab-ee.example.com:9010/"
  token = "NdPRFD6xXbGQoR5ymEAa"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
    tls_verify = false
    image = "node:14-alpine"
    privileged = false
    disable_entrypoint_overwrite = false
    oom_kill_disable = false
    disable_cache = false
    volumes = ["/cache"]
    network_mode = "gitlab-ee-demo_gitlab-network"
    shm_size = 0

GitLabに管理者アカウント(root)でログインし、shared runnerが登録されていることを確認します。

 

 

npm packageをpublishする

GitLab公式ドキュメント|Publishing a package with CI/CDを参考にして進めます。

作成済みのパッケージ用のプロジェクトに、.gitlab-ci.ymlを追加します。

.gitlab-ci.yml

GitLab公式の.gitlab-ci.yml templateも参考になります。

  1. default:
  2.   image: node:14-alpine
  3. stages:
  4.   – deploy
  5. deploy:
  6.   stage: deploy
  7.   script:
  8.     – echo “CI_PROJECT_ROOT_NAMESPACE-> ${CI_PROJECT_ROOT_NAMESPACE}, CI_API_URL-> ${CI_API_V4_URL}, protocol remove -> ${CI_API_V4_URL#http*:}, CI_PROJECT_ID -> ${CI_PROJECT_ID} -> CI_SERVER_HOST -> ${CI_SERVER_HOST}, CI_JOB_TOKEN -> ${CI_JOB_TOKEN} -> CI_DEPLOY_USER ${CI_DEPLOY_USER}, CI_REPOSITORY_URL -> ${CI_REPOSITORY_URL}”
  9.     – |
  10.       {
  11.         echo “@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_API_V4_URL}/projects/2/packages/npm/”
  12.         echo “${CI_API_V4_URL#http*:}/projects/2/packages/npm/:_authToken=${CI_JOB_TOKEN}”
  13.       } >> .npmrc
  14.     – echo “Created the following .npmrc:”; cat .npmrc
  15.     – npm publish

 

テスト用に定義済みの変数出力も追加していますが、必要な部分は定義済み変数出力の後の記述です。
CI_PROJECT_ROOT_NAMESPACEを使っているため、パッケージ用のプロジェクトもパッケージ用のグループ以下に作成しています。
publish用のtokenはCI_JOB_TOKENを使います。

package.json

publishConfigのregistry URLをgitlab-runner registerで指定したURL(http://gitlab-ee.example.com:9010/)に変更します。
GitLab RunnerからGitLabへの接続は、gitlab-ee.example.comを使用するためです。


  "publishConfig": {
    "@web-assets:registry":"http://gitlab-ee.example.com:9010/api/v4/projects/2/packages/npm/"
  }

localhost:9010のままだと、以下のエラーでJobが失敗します。


$ npm publish
npm notice
npm notice package: @web-assets/common-a@1.0.1
npm notice === Tarball Contents ===
npm notice 45B  index.js     
npm notice 435B package.json 
npm notice 714B .gitlab-ci.yml
npm notice === Tarball Details ===
npm notice name:          @web-assets/common-a                   
npm notice version:       1.0.1                                  
npm notice package size:  734 B                                  
npm notice unpacked size: 1.2 kB                                 
npm notice shasum:        4994a6d35c15317ab7abbc118cc0c5258721d57b
npm notice integrity:     sha512-GPYibWCHAwEQY[...]ZOYZ7BeYoOyvA==
npm notice total files:   3                                      
npm notice
npm ERR! code ECONNREFUSED
npm ERR! errno ECONNREFUSED
npm ERR! FetchError: request to http://localhost:9010/api/v4/projects/2/packages/npm/@web-assets%2fcommon-a failed, reason: connect ECONNREFUSED 127.0.0.1:9010
npm ERR!     at ClientRequest.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/node-fetch-npm/src/index.js:68:14)
npm ERR!     at ClientRequest.emit (events.js:400:28)
npm ERR!     at Socket.socketErrorListener (_http_client.js:475:9)
npm ERR!     at Socket.emit (events.js:400:28)
npm ERR!     at emitErrorNT (internal/streams/destroy.js:106:8)
npm ERR!     at emitErrorCloseNT (internal/streams/destroy.js:74:3)
npm ERR!     at processTicksAndRejections (internal/process/task_queues.js:82:21)
npm ERR!  FetchError: request to http://localhost:9010/api/v4/projects/2/packages/npm/@web-assets%2fcommon-a failed, reason: connect ECONNREFUSED 127.0.0.1:9010
npm ERR!     at ClientRequest.<anonymous> (/usr/local/lib/node_modules/npm/node_modules/node-fetch-npm/src/index.js:68:14)
npm ERR!     at ClientRequest.emit (events.js:400:28)
npm ERR!     at Socket.socketErrorListener (_http_client.js:475:9)
npm ERR!     at Socket.emit (events.js:400:28)
npm ERR!     at emitErrorNT (internal/streams/destroy.js:106:8)
npm ERR!     at emitErrorCloseNT (internal/streams/destroy.js:74:3)
npm ERR!     at processTicksAndRejections (internal/process/task_queues.js:82:21) {
npm ERR!   type: 'system',
npm ERR!   errno: 'ECONNREFUSED',
npm ERR!   code: 'ECONNREFUSED'
npm ERR! }
npm ERR! 
npm ERR! If you are behind a proxy, please make sure that the
npm ERR! 'proxy' config is set properly.  See: 'npm help config'
npm ERR! A complete log of this run can be found in:
npm ERR!     /root/.npm/_logs/2021-09-20T15_44_58_648Z-debug.log
ERROR: Job failed: exit code 1

publish

パッケージをCIでpublishする準備ができましたので、GitLabにpushしてpublishしてみましょう。
GitLab repositoryへのpushはPersonal Access Token(read_repository/write_repository)を使用しました。
詳細はGitLab公式ドキュメント|Personal access tokensを参照してください。

 

 

 

Jobが成功しました!
詳細を確認してみましょう。

 

 

次に、NPM Package Registry用のプロジェクトのPackage Registryを確認します。

 

 

 

CIでのpublishに成功しました!

 

まとめ

GitLabのPackage Registryの利用検証をしてみて、npm private registryの代わりとして十分使えるということがわかりました。
GitLab公式が動画も用意してくれているので、合わせて参照すると理解しやすいと思います。

🎦GitLab NPM Registry Demo
🎦GitLab Single Project Package Registry Demo

移行後に社内パッケージを利用する際は、read package registry権限のGroup Deploy Tokenを使用してパッケージをインストールすることを想定しています。

CIを利用するとPackage Registryへのpublishが簡単にできるので、GitLab Package Registryへ移行する際には各パッケージにCIの設定を入れていきたいと思います。
実際に運用する際は、GitLab公式ドキュメント|Publish npm packages to the GitLab Package Registry using semantic-releaseを参考にして、semantic-releaseを入れたいと考えています。

 


 

また、ココネでは一緒に働く仲間を募集中です。

ご興味のある方は、以下のリンクからぜひご応募ください。

 

ココネ株式会社 採用情報

Category

Tag

%d