Private Docker Container Registryサービスを作った話

こんにちは、さくらインターネットのこたまごです。

今日は、今日リリースしたサービス「Sakura Container Registry」のお話をします。


# Private Container Registryとは

Dockerなどのコンテナランタイムでは、実行するコンテナのイメージをどこからか取得する必要があります。
このイメージを保管する機能がContainer Registryです。

最も利用されていると思われるのは [Docker Hub](https://hub.docker.com/) でしょうか。NginxやPHP、PostgreSQLなど、公式、非公式問わずたくさんのイメージが共有され公開されています。

基本的にこれらのイメージは誰でもダウンロードすることができます。

一方で、自分だけがアクセスできるContainer RegistryがPrivate Container Registryです。
Docker Hubでも、有料プランを利用することで自分だけのイメージを保管することができます。

昨今コンテナの利用が進む中、意外とめんどくさいのがこのリポジトリの用意と運用です。

# Sakura Container Registryの使い方

[さくらのクラウド ドキュメント](https://manual.sakura.ad.jp/cloud/appliance/container-registry/)もご参照ください。

## レジストリの作成

さくらのクラウドにログインし、メニューから「コンテナレジストリ」→「作成」ボタンをクリック。

![レジストリ一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73788/4110be4b-a981-6264-c473-65031fa7fc79.png)


コンテナレジストリ名と公開設定が重要なポイントです。

コンテナレジストリ名は一度設定すると変更できません。公開設定はログインしていないユーザーのアクセス権を設定することができます。

* 「Push & Pull」イメージの更新も誰でもできるレジストリになります
* 「Pullのみ」イメージの更新は認証が必要ですが、イメージを取得し利用するのは誰でもできるレジストリになります
* 「非公開」イメージの更新も取得も認証が必要なレジストリになります


現時点では独自ドメインは利用できませんが、近々対応したいと思っています。

![レジストリ作成画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73788/7c3d0e1e-16bc-546d-8012-53c1df15957f.png)

コンテナレジストリ名を決めて作成すると「example.sakuracr.jp」のようなドメインが割り当てられます。これは後から変更できません。


## ユーザーの作成

実際に使う前にユーザーの追加が必要です。「ユーザー」タブから追加と削除ができるので追加してください。

![詳細画面](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73788/e4d76d25-8476-dd1d-0768-90fb26cb0348.png)

![ユーザ一覧](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73788/7a346e3d-8967-cd46-ac27-505f2277d38b.png)

![ユーザ作成](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73788/096805d6-2d64-a37c-de79-84de843d87e6.png)


現時点では読み書き (Push & Pullどちらもできる) 権限のあるユーザーしか作成できませんが、今後読み込み (Pull) 専用ユーザーも用意しようと思います。

## Dockerから使う

まずログインをしておく必要があります。

```bash
$ docker login example.sakuracr.jp
Username: (作ったユーザーのユーザー名)
Password: (パスワード)
```

`Login Succeeded` と表示されればOKです。

次に、アップロード(push)したいイメージを作成します。イメージ名は必ず `example.sakruacr.jp/(好きな名前):(タグ)` としてください。

ex) `example.sakuracr.jp/nginx:latest`, `example.sakuracr.jp/awsomeproject/application:latest`

今回は例としてNginxのイメージをそのまま利用します。

```bash
$ docker pull nginx:latest
$ docker tag nginx:latest example.sakuracr.jp/nginx:latest
```

`Dockerfile` がある場合には

```bash
$ docker build -t example.sakuracr.jp/awsomeproject/application:latest
```

などとしましょう。

あとはpushするだけです。

```bash
$ docker push example.sakuracr.jp/nginx:latest
```

or

```bash
$ docker push example.sakuracr.jp/awsomeproject/application:latest
```


# サービスの仕組み

[Docker Distribution](https://github.com/docker/distribution)をベースに、マルチテナントなContainer Registryを開発しました。

* 認証管理システム
* Container Registry
* ストレージ
* キャッシュ

の4つのアプリケーションで構成されています。


![diagram.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/73788/acbe360a-4bf2-8342-3897-cf7129b95b73.png)


## 認証管理システム

どんなレジストリがあるか、どんなユーザーがあるかを管理しています。
また、実際の認証認可も行っており、 `docker login` コマンド等の要求に対してJWT (JSON Web Tokens) で署名された認証キーの発行をしています。

私の趣味によりPythonとDjangoで書かれています。

## Container Registry

`docker push` `docker pull` コマンドで実際に通信するサーバです。

HTTPSのみに対応しており、SNIによってホスト名を識別後、ホスト名に応じて挙動が変わるようになっています。
これ自身にはパスワード認証の機能はなく、全て上記の認証管理システムから発行されたJWTによって認証認可を行っています。

Goで書かれています。

## ストレージ

`docker push` されたイメージを全て保存しているストレージです。社内の分散ストレージを利用しています。

## キャッシュ

`docker pull` が実行されたとき、イメージによってはかなり大きなデータ量の読み出しと送信が発生します。
また、Container Registryの特性上、分散したRegistryサーバに対して同じイメージが並列でリクエストされることが想定されます。

そこで、Container Registryとストレージの間にキャッシュサーバを挟み、イメージのキャッシュを行っています。

ハッシュ値によってキャッシュするサーバを決定することで、多数あるContainer Registryからの同じデータへのアクセスが一箇所のキャッシュサーバに集中するような工夫をしています。

Goで書かれています。

# さいごに

本サービスは、さくらインターネット内に新たにできたチーム「エンジニアリングラボ」で開発されたサービスです。
エンジニアリングラボでは品質に固執せず、開発早期の段階でお客様にご提供し、使ってみていただけるような取組を行うことを目的としております。

これからもさくらのエンジニアリングラボでは様々なサービスをお届けしていきます。

うまくいけばそのまま本番サービスとして提供できるものもあれば、お試し提供中に終了となるサービスも生まれるかもしれません。
ワクワクするようなたくさんの体験を皆さんに提供できるように努力していきますので、どうぞよろしくお願いいたします。


# できるまで

「開発早期の段階でお客様にご提供する」精神で、開発開始から17日でリリース！

* 12/2 レジストリが欲しいと弊社社員が言う
* 12/6 調査開始
* 12/7 レジストリ実装
* 12/8 管理システム実装
* 12/9 コンパネ実装
* 12/19 本番環境APIリリース
* 12/23 本番環境コンパネリリース