
GitLab Package Registryをローカル環境で試してみた
-
2021年9月22日
こんにちは。ウェブ開発室基盤開発チームの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
- version: “3”
- services:
- web:
- image: “gitlab/gitlab-ee:13.12.4-ee.0”
- restart: always
- hostname: “localhost”
- environment:
- GITLAB_OMNIBUS_CONFIG: |
- external_url ‘http:/localhost:9010’
- gitlab_rails[‘gitlab_shell_ssh_port’] = 2022
- gitlab_rails[‘time_zone’] = ‘Asia/Tokyo’
- ports:
- – “9010:9010”
- – “443:443”
- – “2022:22”
- volumes:
- – “./config:/etc/gitlab”
- – “./logs:/var/log/gitlab”
- – “./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の設定をします。
- {
- “name”: “@web-assets/common-a”,
- “version”: “1.0.0”,
- “description”: “”,
- “main”: “index.js”,
- “scripts”: {
- “test”: “echo \”Error: no test specified\” && exit 1″
- },
- “repository”: {
- “type”: “git”,
- “url”: “http://localhost:9010/web-assets/packages/common-a.git”
- },
- “author”: “”,
- “license”: “ISC”,
- “publishConfig”: {
- “@web-assets:registry”: “http://localhost:9010/api/v4/projects/2/packages/npm/”
- }
- }
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
- version: “3”
- services:
- gitlab-ee.example.com:
- image: “gitlab/gitlab-ee:13.12.4-ee.0”
- restart: always
- hostname: “gitlab-ee.example.com”
- environment:
- GITLAB_OMNIBUS_CONFIG: |
- external_url ‘http://gitlab-ee.example.com:9010’
- gitlab_rails[‘gitlab_shell_ssh_port’] = 2022
- gitlab_rails[‘time_zone’] = ‘Asia/Tokyo’
- ports:
- – “9010:9010”
- – “443:443”
- – “2022:22”
- volumes:
- – “./config:/etc/gitlab”
- – “./logs:/var/log/gitlab”
- – “./data:/var/opt/gitlab”
- networks:
- – gitlab-network
- runner:
- image: “gitlab/gitlab-runner:latest”
- restart: always
- depends_on:
- – gitlab-ee.example.com
- volumes:
- – ./runner/config:/etc/gitlab-runner
- – /var/run/docker.sock:/var/run/docker.sock
- networks:
- – gitlab-network
- networks:
- 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も参考になります。
- default:
- image: node:14-alpine
- stages:
- – deploy
- deploy:
- stage: deploy
- script:
- – 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}”
- – |
- {
- echo “@${CI_PROJECT_ROOT_NAMESPACE}:registry=${CI_API_V4_URL}/projects/2/packages/npm/”
- echo “${CI_API_V4_URL#http*:}/projects/2/packages/npm/:_authToken=${CI_JOB_TOKEN}”
- } >> .npmrc
- – echo “Created the following .npmrc:”; cat .npmrc
- – 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を入れたいと考えています。
また、ココネでは一緒に働く仲間を募集中です。
ご興味のある方は、以下のリンクからぜひご応募ください。