NGC Container Replicator で NGC のイメージを手元に複製

こんにちは、エヌビディアの佐々木です。

[NGC Container Replicator](https://github.com/NVIDIA/ngc-container-replicator) をご存じですか？これは、[NGC](https://ngc.nvidia.com) のコンテナーイメージをダウンロードし、下記の処理（の一部または全部）を行う Python スクリプトです。

- 別の Docker レジストリへ登録 (組織内のローカルレジストリなど)
- tar ファイルとしてディスクへ保存 (インターネットに接続されていない環境へ移送して docker load するような使い方を想定)
- Singularity のイメージファイルに変換

複数のユーザーが複数の計算機を共有してコンテナーを実行するような環境 (大規模な例としては [ABCI] (https://blogs.nvidia.co.jp/2019/06/19/abci-adopts-ngc/) のようなスパコンセンターとか) では、計算ノード毎にそれぞれ NGC からイメージをダウンロードするのは非効率ですよね。そんなときに NGC Container Replicator が便利です。

以下、 NGC Container Replicator (以降、Replicator と略記) の実行方法を簡単に説明します。

# 動作要件

Replicator の実行には以下の環境が必要です

- Docker が動作しインターネットにアクセスできるコンピューター
  - Replicator は NGC のイメージを pull しますので、当然 Docker が動作する必要があります。ただし、コンテナを実行するわけではありませんので、 GPU は不要です。
- NGC のアカウントと API キー
  - 現在、NGC の多くのイメージは認証無しで pull 可能になっていますが、 Replicator は実行時に必ず API キーを指定する必要があります。事前に NGC の管理画面で API キーを生成してください。方法はこちら → [NGC の API キーを生成](https://qiita.com/ksasaki/items/618b2f6c0cacbc7f9584#ngc-%E3%81%AE-api-%E3%82%AD%E3%83%BC%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B)

# 実行方法

Replicator は [GitHub](https://github.com/NVIDIA/ngc-container-replicator) でソースが公開されているほか、すぐに実行可能なコンテナーイメージが [Docker Hub](https://hub.docker.com/r/deepops/replicator) で利用可能になっています。手っ取り早く実行するにはこのイメージを使うのがオススメです。私が試しに自分の環境で実行してみたスクリプトを以下に載せておきます。これは、

- TensorFlow と PyTorch コンテナーイメージの 19.06 版以降を取得
- tar ファイルへの出力、別レジストリへの push、Singularity イメージ生成の 3 アクションを全て実施

という動作をします。tar ファイルと Singularity イメージはホストの `/shared/containers` ディレクトリに保存されます。別レジストリとしては、[Microsoft Azure の Container Registry](https://azure.microsoft.com/ja-jp/services/container-registry/) を使いました。

```
#! /bin/bash

docker run --rm -it \
-v /var/run/docker.sock:/var/run/docker.sock \
-v /shared/containers:/output \
deepops/replicator \
--project=nvidia --min-version=19.06 \
--image=tensorflow \
--image=pytorch \
--singularity \
--exporter \
--registry-url=ksasaki.azurecr.io \
--registry-username=USER \
--registry-password=PASSWORD \
--api-key=NGCAPIKEY
```

オプションが色々あるのでちょっと解説しますと、

- 最初の `-v /var/run/docker.sock:/var/run/docker.sock`
  - これは、コンテナー内からホストの Docker を操作するために必要です。
- 二番目の `-v /shared/containers:/output`
  - Replicator は Docker イメージの tar ファイルや Singularity のイメージファイル等を (デフォルトでは) /output へ保存します。Replicator をコンテナーで実行する際は、こういったファイルをコンテナー内に吐き出してもあまり意味がありませんので、ホストのディレクトリをマウントしてホストに保存するようにします。

そして、 `deepops/replicator` 以降は Docker ではなく Replicator に対するオプションになりますが、これはあまり詳しくドキュメント化されていないので、ここで少しく解説しておきます。

## Replicator のコマンドラインオプション

### 基本設定

- --api-key
  - NGC の API キーを指定します。デフォルト値は環境変数 NGC_REPLICATOR_API_KEY が設定されていればそちらから。
- --output-path
  - Docker イメージの tar ファイルや Singularity のイメージファイル、そしてどのイメージをダウンロードしたかという状態情報を保存する state.yml ファイルを保存する場所を指定します。デフォルト値は `/output`。
- --dry-run
  - 実際にコンテナーイメージをダウンロードはせずに、何がダウンロードされるかだけを表示します。
- --no-remove
  - Replicator は実行したホストにコンテナーイメージを一旦ダウンロード (docker pull) し、それを tar ファイルに出力したり、他のレジストリに push したり、 Singularity イメージに変換したあと、削除します。このオプションを指定した場合、一旦ダウンロードしたイメージを削除せずに残します。 

### 対象イメージの条件指定

- --project
    - project とは、コンテナーイメージの URL のなかで "nvcr.io" の次の部分 (例えば `nvcr.io/nvidia/caffe:19.08-py2` の `nvidia` 部分) で、デフォルトは `nvidia` です。今のところ、NGC のイメージには nvidia, hpc, nvidia-hpcvis, partners の 4 プロジェクトがあります。
- --min-version
  - 取得するイメージのバージョン番号の下限を指定します。例えば 19.03 を指定すると、 19.03 より古いイメージは対象外となります。
- --image
  - 取得するイメージの名前を指定します。このオプションは繰り返し複数指定できます。

### ダウンロードしたイメージに対するアクションの指定

下記の 3 オプションは、ダウンロードしたイメージを別のレジストリへ push するための指定です。組織内のローカルレジストリ等へ NGC のイメージを複製する際に使用します。

- --registry-url
 - 複製先レジストリの URL を指定します。
- --registry-username
  - 複製先レジストリへログインするためのユーザー名を指定します。
- --registry-password
  - 複製先レジストリへログインするためのパスワード名を指定します。

次のオプションで、ダウンロードしたイメージを docker save するか否かを指定します。

- --exporter/--no-exporter
  - このオプションのデフォルト値は True です。つまり、--no-exporter を指定しない限り、イメージの tar ファイルが作成されます。

次のオプションで、ダウンロードしたイメージを Singularity イメージに変換するか否かを指定します。

- --singularity/--no-singularity
  - このオプションのデフォルト値は False です。 --singularity を明示的に指定した場合のみ、Singularity イメージが作成されます。

# 定期的に実行するには？

NGC Container Replicator 自体はワンショット実行ツールです。定期的に実行するには cron ジョブなどを利用してください。Kubernetes で CronJob として実行する方法も [GitHub](https://github.com/NVIDIA/ngc-container-replicator#kubernetes-deployment) に記載があります。
 
# 関連情報

- [NGC Container Replicator](https://github.com/NVIDIA/ngc-container-replicator)
- [Automating Downloads with NGC Container Replicator, Ready-to-Run on Singularity](https://devblogs.nvidia.com/automating-downloads-ngc-container-replicator/)
- [日本最速のスーパーコンピュータが NGC を採用し、ディープラーニング フレームワークの利用をより簡単に](https://blogs.nvidia.co.jp/2019/06/19/abci-adopts-ngc/)
- [NGC の API キーを生成](https://qiita.com/ksasaki/items/618b2f6c0cacbc7f9584#ngc-%E3%81%AE-api-%E3%82%AD%E3%83%BC%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B)