プライベートなdockerレジストリを構築

モチベーション

以前の投稿でユーザモードでdockerコンテナを起動する方法をまとめた。

複数のPC(WorkStation、以下WS)を使う場合、複数WS間でコンテナを共有する仕組みをどう実現するかを考える必要がある。singularityの場合には、sifファイルをNFSサーバに格納し、それを他のWSから使えば良かった。

dockerの場合には、自宅のネットワーク内にプライベートなレジストリを立てて、運用すれば良いと考え、レジストリ・サーバを構築することにした。

情報源

その他の情報源(ページ)を見てると、次のような内容をdeamon.jsonに記述すればよさそうで、rootless環境では、どこにdemon.jsonを格納場所さえ分かれば、簡単に構築できると思っていた。(xxxx.xxx.xxx.xxxはprivate registryのローカルネットワーク環境でのIPアドレス)

{
  "insecure-registries':[xxx.xxx.xxx.xxx:5000]"
}

しかしながら、実際には解決までには結構時間が掛かった。解決に役に立ったのが、上記の2つのページ。

rootless環境で、private registryを構築し、他のWSからpush/pullするまでの手順を以下にまとめる。説明する上で、private registryとなるWSをサーバと呼び、他のWSはクライアントとして説明する。

設定

private registryサーバ設定

秘密鍵と証明書を作成

自分の$HOMEディレクトリ配下にcertsというディレクトリを作成し、certs配下に鍵と証明書を作成する。

$ cd
$ mkdir certs
$ openssl req -newkey rsa:2048 -nodes -sha256 -keyout certs/ca.key -x509 -days 3650 -out certs/ca.crt -addext "subjectAltName = IP:192.168.xxx.yyy"

上記でのポイントは、-addext “subjectAltName = IP:192.168.xxx.yyy"である。ここで、192.168.xxx.yyyはprivate registryサーバのIPアドレス。

上記コマンド(openssl)を実行すると、Country Name等の入力を求められるが、Common Name以外は改行(未入力)で構わない。Common Nameのところは適当な文字列を入力。自分は、サーバ名.comとした。

/usr/share/ca-certificates/dockerに鍵と証明書を格納

/usr/share/ca-certificates配下にdockerディレクトリを作成し、上記で作成した鍵(ca.key)と証明書(ca.crt)をコピーする。

$ cd
$ sudo mkdir /usr/share/ca-certificates/docker
$ sudo cp certs/ca.* /usr/share/ca-certificates/docker
$ sudo update-ca-certificates
$ sudo vi /etc/ca-certificates.conf

上記最後の部分で、/etc/ca-certificates.confをviで開き、最終行にdocker/ca.crtを追加する。

dockerデーモンを再起動

$ systemctl --user restart docker

registryイメージを起動

$ docker run -d -p 5000:5000 -v $PWD/certs:/certs \
-v /ext/registry:/var/lib/registry \
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/ca.crt \
-e REGISTRY_HTTP_TLS_KEY=/certs/ca.key \
--restart=always registry:2

レジストリに登録した内容をコンテナ外からも確かめられるように、"-v /ext/registry:/var/lib/registry"を指定した。上記のように、マウントした項目毎に”-v"オプションを追加すれば良い。

クライアント側の設定

鍵と証明書の格納

クライアントの設定する際に、サーバ側で作成した鍵と証明書が必要となる。ここでは、/mnt/nfs/tmp/ca.*がそれであると仮定している。

# cd /usr/share/ca-certificate
# mkdir docker
# cp /mnt/nfs/tmp/ca.* docker
# vi /etc/ca-certificates.conf

サーバの時と同じく、/etc/ca-certificates.confの最終行にdocker/ca.crtを追加する。

# sudo update-ca-certificates

dockerデーモンを再起動

$ systemctl --user restart docker

クライアント側からイメージをpush

pushするイメージ

クライアント側には、次のようなjupyterlabのイメージがある。

$ docker images
REPOSITORY                  TAG                       IMAGE ID       CREATED         SIZE
pytorch-lab                 latest                    bac68bf54efe   21 hours ago    9.37GB

タグ付け

レジストリにpushする場合には、レジストリのIPアドレスを含めて以下のようにタグ付けする。

$ docker tag pytorch-lab:latest 192.168.xxx.yyy:5000/pytorch:lab
$ docker images
REPOSITORY                   TAG                      IMAGE ID       CREATED         SIZE
192.168.xxx.yyy:5000/pytorch lab                      bac68bf54efe   21 hours ago    9.37GB
pytorch-lab                  latest                   bac68bf54efe   21 hours ago    9.37GB

イメージをpush

$ docker push 192.168.xxx.yyy:5000/pytorch:lab
The push refers to repository [192.168.xxx.yyy:5000/pytorch]
(以下略)

別のクライアントからイメージをpull

イメージをpull

$ docker pull 192.168.xxx.yyy:5000/pytorch:lab
lab: Pulling from pytorch
Digest: sha256:807b0cd1b8754072940730a02a1d00933b1c6caedbb162de2b98cbeae642838c
Status: Image is up to date for 192.168.xxx.yyy:5000/pytorch:lab
192.168.xxx.yyy:5000/pytorch:lab

起動

以下の通り、pullしたjupyterlabイメージを起動する。以下の例では、カレントディレクトリにjupyterlabという、notebookを入れるディレクトリがを仮定している。

$ docker run -d --rm --gpus all -v ${PWD}/jupyterlab:/workdir -p 8888:8888 192.168.xxx.yyy:5000/pytorch:lab

まとめ

以上の手順によって、複数のWSでdockerイメージを共有することができるようになった。

今回のdocker private registry構築には、時間がかかり、結構苦労したが、この構築を通して、鍵、証明書など認証に関することを色々学んだ。

この分野は経験も少なく、誤った情報が含まれているかもしれない。誤り等に気づかれたら、指摘してほしい。よろしくお願いします。