【Dockerで開発環境構築】Verdaccio on DockerでコンテナのローカルIPを調べる方法


2020/04/27
2021/05/10
蛸壺の技術ブログ|Verdaccio on DockerでコンテナのローカルIPを調べる方法

Verdaccioは、社内のみで運用したいプライベートなnpmパッケージをとりためておけるパッケージレジストリです。

Verdaccio - A lightweight private npm proxy registry

Verdaccioはnpmインストールからパッケージ版を利用して、ローカルネットワーク上に常駐させるレジストリサーバとしてサービスを提供することが可能ですが、Dockerが使える環境であれば、dockerイメージをpullするだけで、お手元のdockerネットワーク上でお手軽にパッケージレジストリが構築出来ておすすめです。

とはいえ、著者のよう独りでPC上にVerdaccioを立ち上げて、dockerコンテナで自分専用パッケージを出し入れするという珍妙な使い方をする方が他にいるか分からんですが、verdaccioのレジストリコンテナにアクセスする際に必要なIPの調べ方をメモします。


はじめに〜バージョンアップデートで躓く話(※2021年5月更新)

先日、社内用のVerdaccioレジストリとして利用していたDockerコンテナを久々(実に一年ぶり)にメンテナンスしてみようと思い立ちまして、どうせなのでコンテナのイメージがバージョン3から5にリニューアルしたところ、上手くnpmパッケージがVerdaccio側にパブリッシュ出来なくなってしましました。

            
            $ npm adduser --registry http://192.168.32.1:4873
npm notice Log in on http://192.168.32.1:4873/
Username: *****
Password:
Email: (this IS public) ****
Logged in as **** on http://192.168.32.1:4873/.
npm notice
npm notice package: @my/**********
npm notice === Tarball Contents ===
#...中略
npm notice
npm ERR! code E500
npm ERR! 500 Internal Server Error - PUT http://192.168.32.1:4873/@my%2f*********** - internal server error

npm ERR! A complete log of this run can be found in:
npm ERR!     /home/******/.npm/_logs/2021-05-10T06_01_39_320Z-debug.log
error Command failed with exit code 1.
info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.
        
どうやら暫くの間にVerdaccioの中身も色々と様変わりしたようで、直すところをしっかり対応しないとダメそうです...

ということで、この記事の内容も古いままでしたので、Verdaccio5で動作確認できたないように以降の内容もアップデートしておきます。


基本的な立ち上げ方〜直接Shell画面でみる

とりあえずverdaccioの公式からdockerイメージをプルしてきます。公式には、以下のコマンドで立ち上がると記載されております。

            
            $ docker run -it --rm \
    --name verdaccio \
    -p 4873:4873 \
    verdaccio/verdaccio
        
個人差もあるのですが、毎回長々しいdockerコマンドのオプションを覚えてはいない為、docker-composeを使いましょう。

以下、docker-compose.ymlを作成します。

            
            version: '3'
services:
  verdaccio:
    image: verdaccio/verdaccio:5
    container_name: verdaccio-local
    ports:
      - "4873:4873"
    volumes:
        - "./storage:/verdaccio/storage"
        - "./conf:/verdaccio/conf"
    restart: always
volumes:
  verdaccio:
    driver: local
        
それではコンテナを立ち上げます。

            
            $ docker-compose up

Creating network "verdaccio_docker_default" with the default driver
Creating verdaccio-local ... done
Attaching to verdaccio-local
verdaccio-local |
...
        
立ち上がりました。そしてまずはブラウザでhttp://localhost:4873を確認しましょう。

合同会社タコスキングダム|蛸壺の技術ブログ

写真のように、プライベートに開発したパッケージが表示されます。この画面にアクセスすると、起動していたシェル画面に、

            
            verdaccio-local |  info <-- 192.168.32.1 requested 'GET /'
verdaccio-local |  http <-- 304, user: null(192.168.32.1), req: 'GET /', bytes: 0/0
verdaccio-local |  http <-- 304, user: null(192.168.32.1), req: 'GET /', bytes: 0/0
#...
#以下略
        
と何やら、ブラウザで叩いた際のアクセス履歴を大量に吐き出します。そしてこの際にタナボタ的に見えているIPがVerdaccioのコンテナへアクセスする際のIP(今回は"192.168.32.1")です。このIPはコンテナを起動・停止させるたびに変わる為、毎回確認が必要です。

立ちあがったコンテナーを停止する際には、

            
            $ docker-compose down
        
で停止します。

基本的にはVerdaccioのセットアップ・操作はこれで終わりです。


Verdaccio Docker コンテナのIPを調べる

Dockerイメージでもnpmパッケージ版をインストールしてそれをnodeでサーバー化して使うにしても、ブラウザからはhttp://localhost:4873でverdaccioレジストリにアクセス可能ですが、Dockerネットワーク上で構築された複数のコンテナ間でverdaccioを組み込んで運用する場合に、Container-to-Containerでやり取りする際には、dockerネットワーク上のIPを確認する必要があります。

先程のやり方ですと、毎回ブラウザでverdaccioの画面を見に行かなきゃいけないので、なんだかスマートではありません…。

できることなら、立ち上げからIP確認まで同一のシェル上で出せたらよりスマートです。

そこで今回は、docker-compose を デタッチ・モード(-d)で起動し、 バックグラウンドでコンテナを実行します。

            
            $ docker-compose up -d
        
立ち上がったコンテナをリスト表示させて見まして、

            
            $ docker ps | grep verd
CONTAINER ID        IMAGE                          COMMAND                  CREATED             STATUS                     PORTS                    NAMES
8665cf056ad7        verdaccio/verdaccio:5   "uid_entrypoint /bin…"   19 minutes ago      Up 3 minutes               0.0.0.0:4873->4873/tcp   verdaccio-local
        
ここで、Container IDかContainer名が判明しました。

ちなみにimage名ならdocker-compose.ymlで記述した通りになっているので、控えることもありません。

dockerコマンドの正規な作法でIP確認

以下のコマンドで、Container ID値かContainer名を用いて、IPを表示することが出来ます。今回のケースでは、

            
            #With Container ID (ID値に重複がなければ短縮OK)
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' 866
192.168.32.2

#Or, With Image Name
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' verdaccio-local
192.168.32.2
        
ということで、無事にコンテナーのIPアドレス('192.168.32.2')が引っ張って来れました。

さっきはIPが
'192.168.32.1'だったじゃない、とお気づきになった方もいると思います。実際にはコンテナのIP呼んでいるものは、コンテナのネットワークインターフェース(eth0)に割り当てられているIPアドレス(ここでは'192.168.32.2')であって、コンテナのデフォルトゲートウェイと機能してるdockerの仮想ブリッジ(docker0)に割り当てられている(ここでは'192.168.32.1')にアクセスすることで外部との通信を可能としているようです。

詳細は以下参考の方で説明させている方のページの方をご覧ください。

ということで、実際にはdocker0に割り当てられていたIPでアクセスしていたんだということを踏まえまして、先程のコマンドを修正します。

            
            #With Container ID (ID値に重複がなければ短縮OK)
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' 866
192.168.32.1

#Or, With Image Name
$ docker inspect --format='{{range .NetworkSettings.Networks}}{{.Gateway}}{{end}}' verdaccio-local
192.168.32.1
        
とお目当てのIPを得ることができました。

ちょっと荒っぽいけど簡単なIP確認

…でもちょっとdocker inspect--formatオプションの作法がやたらと面倒臭い。普通だと中々覚えられないです。

            
            #With Container ID (コンテナID値に重複がなければ短縮OK)
$ docker inspect 866 | grep Gate
    "Gateway": "",
    "IPv6Gateway": "",
            "Gateway": "192.168.32.1",
            "IPv6Gateway": "",

#Or, With Image Name
$ docker inspect verdaccio-local | grep Gate
    "Gateway": "",
    "IPv6Gateway": "",
            "Gateway": "192.168.32.1",
            "IPv6Gateway": "",
        
ということでgrepを使えば少し余計なものも引っ張ってくるものの、サッとIPが発見できます。


npmパッケージをVerdaccioレジストリへパブリッシュ

Verdaccioのコンテナが立ちあがったら、だいたい以下のコマンドでnpmパッケージの公開手順と同じように利用できます。

            
            #👇ユーザーの登録(ユーザ名・パスワード・emailアドレス)
$ npm adduser --registry http://{コンテナIP}:4873

#👇npmパッケージをVerdaccio側へアップロード
$ npm publish --registry http://{コンテナIP}:4873
        
一年以上前の記憶で、古いVerdaccioならエラーも出ずにすんなりといけたように思いますが、結果は冒頭でも述べたように、何かの内部エラーでパブリッシュを拒否されてしまいます。

...なんだこの挙動は、と思いつつVerdaccioコンテナの反応をバックグラウンド起動を一旦止めて、
docker-compose upでモニタリングしておきます。

            
            $ docker-compose up
Creating network "verdacciodocker_default" with the default driver
Creating verdaccio-local ... 
Creating verdaccio-local ... done
Attaching to verdaccio-local
verdaccio-local |  warn --- config file  - /verdaccio/conf/config.yaml
verdaccio-local | (node:8) Warning: deprecate: multiple logger configuration is deprecated, please check the migration guide.
verdaccio-local | (Use `node --trace-warnings ...` to show where the warning was created)
verdaccio-local |  warn --- Plugin successfully loaded: verdaccio-htpasswd
verdaccio-local |  warn --- Plugin successfully loaded: verdaccio-audit
verdaccio-local |  warn --- http address - http://0.0.0.0:4873/ - verdaccio/5.0.4
        
ぱっと見て取れるのは、警告とcheck the migration guide.config.yamlのマイグレーションガイダンスを読むように書いてあります。

サイトの方をよく確認すると、
@hoge/piyoみたいなパッケージ形式をscoped packageと呼んでいるようですが、このスコープ付きパッケージは/verdaccio/conf/config.yamlに定義して使うように書かれています。

例えば
@my/なんとかというnpmパッケージをとりあえず不特定多数からダウンロード・アップロードさせておきたいときには以下のようにpackagesフィールドへ追加します。

            
            packages:
  '@jota/*':
      access: $all
      publish: $all

  #👇スコープ付きパッケージの追加
  "@my/*":
    access: $all
    publish: $all

  '@*/*':
    # scoped packages
    access: $all
    publish: $all
    proxy: npmjs
        
定義をconfig.yamlに設定し、再度パッケージをパブリッシュしてもこれだけだと駄目のようで、Verdaccio内のログを確認すると、

            
            #...中略
verdaccio-local |  info --- ********** is allowed publish for @my/hoge
verdaccio-local |  error--- unexpected error: EACCES: permission denied, open '/verdaccio/storage/@my/hoge/hoge.tgz.tmp-189143654945658'
verdaccio-local | Error: EACCES: permission denied, open '/verdaccio/storage/@my/hoge/hoge.tgz.tmp-189143654945658'
verdaccio-local |  http --- 500, user: **********(192.168.32.1), req: 'PUT /@my%2fhoge', error: internal server error
verdaccio-local |  http --- 192.168.32.1 requested 'PUT /@my%2fhoge'
verdaccio-local |  info --- auth/allow_action: access granted to: undefined
verdaccio-local |  info --- ********** is allowed publish for @my/hoge
verdaccio-local |  error--- unexpected error: EACCES: permission denied, open '/verdaccio/storage/@my/hoge/hoge.tgz.tmp-017407823939065148'
verdaccio-local | Error: EACCES: permission denied, open '/verdaccio/storage/@my/hoge/hoge.tgz.tmp-017407823939065148'
verdaccio-local |  http --- 500, user: **********(192.168.32.1), req: 'PUT /@my%2fhoge', error: internal server error
        
というエラーが起こっていることが分かります。...どうやらEACCES: permission deniedで、Verdaccioコンテナがローカルフォルダへ書き込む権限が無いエラーのようです。


Verdaccioコンテナにファイル書き込み権限を与える

以下のコマンドで起動中のVerdaccioコンテナ内部にルート権限で入り、インタラクティブモードで設定を操作していきます。

            
            $ docker exec -it --user=root verdaccio-local /bin/sh
/opt/verdaccio#
        
まずは現在のファイルのアクセス権限を確認します。

            
            /opt/verdaccio# ls -la /verdaccio/
total 20
drwxr-xr-x    1 root     root          4096 Apr 28 05:21 .
drwxr-xr-x    1 root     root          4096 May 10 06:55 ..
drwxr-xr-x    2 node     node          4096 May 10 00:45 conf
drwxr-xr-x    2 root     root          4096 Apr 28 05:21 plugins
drwxr-xr-x   10 node     node          4096 May 10 01:12 storage
        
ということで、パッケージの書き込みに関係ありそうなconfstorageがユーザー名とグループ名もnodeに属しています。

Verdaccioの通常起動ではユーザ名
verdaccioとグループ名nogroupがデフォルトですので、権限的に上位のnodeのフォルダにはアクセス出来ないことになります。

そこで、以下のように個別の設定も面倒ですので
/verdaccioごとゴッソリユーザーとグループを書き換えます。

            
            /opt/verdaccio# chown -R verdaccio:nogroup /verdaccio/
/opt/verdaccio# ls -la /verdaccio/
total 24
drwxr-xr-x    1 verdacci nogroup       4096 Apr 28 05:21 .
drwxr-xr-x    1 root     root          4096 May 10 06:55 ..
drwxr-xr-x    2 verdacci nogroup       4096 May 10 00:45 conf
drwxr-xr-x    1 verdacci nogroup       4096 Apr 28 05:21 plugins
drwxr-xr-x   10 verdacci nogroup       4096 May 10 01:12 storage
        
これでnodeからverdaccioに権限が移譲されて、再度npmパッケージをアップロードしてみると、

            
            $ npm adduser --registry http://192.168.32.1:4873
npm notice Log in on http://192.168.32.1:4873/
Username: ***********
Password:
Email: (this IS public) dave@osakavacuum.com
Logged in as *********** on http://192.168.32.1:4873/.
npm notice
npm notice package: @my/hoge
npm notice === Tarball Contents ===
#...中略
npm notice total files:   66
npm notice 
+ @my/hoge
Done in 5.59s.
        
でアップロードが成功しました。


参考

Docker の bridge と host ネットワークについて勉強する

Verdaccio+Docker+EC2 その1