Docker Registry構築：IDCFクラウドをストレージに使ってみる

# はじめに
Dockerイメージのレポジトリといえば[Dockerhub](https://hub.docker.com/)がありますが、[docker-registry](https://github.com/docker/docker-registry)を使ってPrivateなレポジトリを構築することもできます。

Docker Registryでは、イメージなどの保存先にローカルストレージだけでなく[S3](http://aws.amazon.com/jp/s3/)や[Azure](http://azure.microsoft.com/ja-jp/)、[Swift](http://docs.openstack.org/developer/swift/)を使うことができます。

今回、S3互換の[IDCFクラウドのオブジェクトストレージ](http://www.idcf.jp/cloud/storage/)をDocker Registryのストレージとして使用する方法を紹介します。

Docker RegistryもDockerイメージとして配布されています。
今回はVagrantでCoreOSを立ち上げ、そこにDocker Registryを構築します。
Dockerが動けばいいので、CentOSでもUbuntuでも構いません。

# IDCFクラウド オブジェクトストレージ
（オブジェクトストレージを既に利用中の方はスキップしてください）

IDCFのオブストはRiakCSというOSSを利用した、S3互換のオブジェクトストレージです。

オブストを使うには、IDCFクラウドのコンパネの上部メニューからオブジェクトストレージを選択します。

![スクリーンショット 2015-02-04 14.28.06.png](https://qiita-image-store.s3.amazonaws.com/1225/51416/3ac09ade-fe9f-9a55-c7d9-165528455243.png "スクリーンショット 2015-02-04 14.28.06.png")

初めて使うときはプラン選択画面が出てくるので、とりあえず50GBを無料で使える従量プランを選択します。

![スクリーンショット 2015-02-04 14.29.22.png](https://qiita-image-store.s3.amazonaws.com/1225/51416/65c73b50-8c15-b926-7930-a2b2d23195e7.png "スクリーンショット 2015-02-04 14.29.22.png")

確認画面が出てくるので、申し込みます。

![スクリーンショット 2015-02-04 14.30.50.png](https://qiita-image-store.s3.amazonaws.com/1225/51416/55df658e-7e84-16fb-a742-6f5c6fd698a2.png "スクリーンショット 2015-02-04 14.30.50.png")

管理画面に行きます。

![スクリーンショット 2015-02-04 14.34.32.png](https://qiita-image-store.s3.amazonaws.com/1225/51416/fd004c01-bfc9-a38c-1448-63e8b435ab2a.png "スクリーンショット 2015-02-04 14.34.32.png")

次に、【APIユーザー追加】をクリックしてユーザを作成します。
ユーザを作成したら、オブストを使うためのAPIキーが発行されます。

![スクリーンショット 2015-02-04 14.36.32.png](https://qiita-image-store.s3.amazonaws.com/1225/51416/d9035232-aaf6-1085-bf87-8818414590c8.png "スクリーンショット 2015-02-04 14.36.32.png")

一覧画面に戻ってユーザー名をクリックすると、このようにAPIの接続情報が表示されます。
これでオブストを使うための準備は完了です。

![スクリーンショット_2015-02-04_14_37_33.png](https://qiita-image-store.s3.amazonaws.com/1225/51416/a2cc6321-a9d5-7f68-57bd-aecebcff5715.png "スクリーンショット_2015-02-04_14_37_33.png")

# CoreOS起動
Vagrantを使ってCoreOSを起動します。

```bash
git clone https://github.com/coreos/coreos-vagrant/
cd coreos-vagrant
vagrant up
```

無事起動したら、SSHで接続しましょう。

```bash
vagrant ssh
```

# Docker Registry用設定ファイル作成
Docker Registryは、[設定をYAMLで書く](https://github.com/docker/docker-registry/blob/master/config/config_sample.yml)ようになってます。

CoreOSのローカルに設定ファイル作成して、コンテナからマウントするようにします。
CoreOSの用途を考えると直接CoreOSのローカルに設定ファイルを保存するのは好ましくないので、実運用では別の方法を考えたほうがいいかもしれません。

以下、CoreOS上での操作です。

```bash
sudo mkdir /etc/registry
sudo vi /etc/registry/config.yml
```

```yaml:/etc/registry/config.yml
prod:
  issue: '"Private Docker Registry"'
  loglevel: info
  debug: false
  standalone: true
  search_backend: sqlalchemy
  sqlalchemy_index_database: sqlite:////tmp/docker-registry.db

  storage: s3
  boto_bucket: my-docker-registry
  storage_path: /registry
```

重要なのは、`storage: s3`です。ここではS3と指定します。
`boto_bucket`で指定したバケット内に、`storage_path`というディレクトリが作成されてそこにイメージが保存されます。

それぞれの詳しい意味は、[docker-registryのREADME](https://github.com/docker/docker-registry/blob/master/README.md)を参照してください。

# boto用設定ファイル作成
次に、[boto](http://docs.pythonboto.org/en/latest/)用の設定ファイルを作成します。
botoはDocker Registryが使用しているAWSのSDKです。

S3を使う場合など、通常ここは触らなくてOKです。
IDCFクラウドを使うためにエンドポイントを書き換える必要があるので設定します。

これも同様に、CoreOSのローカルに作成して、コンテナからマウントします。

```:/etc/registry/boto.cfg
[Boto]
metadata_service_timeout = 2.0
metadata_service_num_attempts = 3

[Credentials]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY

[s3]
host = ds.jp-east.idcfcloud.com
```

Credentialsとエンドポイントを設定します。

# Unitファイル作成
Docker RegistryをSystemdのサービスとして起動するためユニットファイルを作成します。

```:/etc/systemd/system/registry.service
[Unit]
Description=Docker Registry
After=docker.service
Requires=docker.service

[Service]
TimeoutStartSec=0
ExecStartPre=-/usr/bin/docker kill registry
ExecStartPre=-/usr/bin/docker rm registry
ExecStartPre=/usr/bin/docker pull registry
ExecStart=/usr/bin/docker run --name registry -p 5000:5000 -v /etc/registry/config.yml:/docker-registry/config/config.yml -v /etc/registry/boto.cfg:/etc/boto.cfg -e SETTINGS_FLAVOR=prod -e DOCKER_REGISTRY_CONFIG=/docker-registry/config/config.yml -e GUNICORN_WORKERS=2 registry

[Install]
WantedBy=multi-user.target
```

`ExecStartPre`で、コンテナの掃除をしてます。`=-`はsystemdのエラーを無視するという構文です。

`ExecStart`で、docker-registryコンテナを起動してます。
`DOCKER_REGISTRY_CONFIG`で、docker-registryが使うコンフィグファイルを指定します。
`-v`オプションでマウントしたファイルになるので、実体はCoreOSローカルの`/etc/registry/config.yml`です。
`SETTINGS_FLAVOR`では、コンフィグファイル内のどの設定を使うかを指定してます。
`GUNICORN_WORKERS`はコンテナ内で動くWorkerの数です。

# Docker Registry起動
では、systemdで起動してみましょう。

```bash
sudo systemctl start registry
```

初回はDockerイメージのPullがあるので、時間がかかります。
うまく起動すれば、`systemctl status registry`でrunningになっています。

```bash
$ sudo systemctl status registry
● registry.service - Docker Registry
   Loaded: loaded (/etc/systemd/system/registry.service; disabled; vendor preset: disabled)
   Active: active (running) since Wed 2015-02-04 06:32:14 UTC; 9s ago
  Process: 1240 ExecStartPre=/usr/bin/docker pull registry (code=exited, status=0/SUCCESS)
  Process: 1225 ExecStartPre=/usr/bin/docker rm registry (code=exited, status=1/FAILURE)
  Process: 1157 ExecStartPre=/usr/bin/docker kill registry (code=exited, status=1/FAILURE)
 Main PID: 1395 (docker)
   CGroup: /system.slice/registry.service
           └─1395 /usr/bin/docker run --name registry -p 5000:5000 -v /etc/registry/config.yml:/docker-registry/...
```

また、Dockerコマンドでも確認することができます。

```bash
$ sudo docker ps
CONTAINER ID        IMAGE               COMMAND             CREATED              STATUS              PORTS                    NAMES
488ed7044e69        registry:latest     "docker-registry"   About a minute ago   Up About a minute   0.0.0.0:5000->5000/tcp   registry
```

curlでも確認してみましょう。

```bash
$ curl http://localhost:5000/
"\"Private Docker Registry\""
```

いい感じで動いてそうです。

# Docker Push/Pull
では、次はDocker Registryとして動作しているかを確認します。

registryイメージをPullしているので、それをそのままPushしてみます。

```bash
sudo docker tag registry localhost:5000/registry
sudo docker push localhost:5000/registry
sudo docker pull localhost:5000/registry
```

うまくいったでしょうか。

# オブスト確認
最後に、イメージがちゃんとオブストに保存されているかどうかを確認します。
確認にはs3cmdを使用します。

s3cmdのセットアップ方法は[IDCFのマニュアル](http://www.idcf.jp/cloud/storage/faq/scm_005.html)を参照してください。

```bash
$ s3cmd ls s3://my-docker-registry/
                       DIR   s3://my-docker-registry/registry/
```

指定したバケットの中に、`/registry`というディレクトリができています。
これは、`config.yml`で指定した`storage_path: /registry`です。

```bash
$ s3cmd ls s3://my-docker-registry/registry/
                       DIR   s3://my-docker-registry/registry/images/
                       DIR   s3://my-docker-registry/registry/repositories/
```

`/registry`のなかにはさらに`/images`と`/repositories`ができています。
中身はそれぞれこんな感じで、イメージなどが入っています。

```bash
$ s3cmd ls s3://my-docker-registry/registry/images/
                       DIR   s3://my-docker-registry/registry/images/0e7a483810f64e4d2f4fc679d8c10d3914a975d18a2a152d26bd6655feb0af8f/
                       DIR   s3://my-docker-registry/registry/images/214c09aed08bbf283bfb334b5a0526fa7e66ccaf667a5feee66d75af6a69bc6f/
                       DIR   s3://my-docker-registry/registry/images/27d47432a69bca5f2700e4dff7de0388ed65f9d3fb1ec645e2bc24c223dc1cc3/
                       DIR   s3://my-docker-registry/registry/images/2ce4ac388730ca6857050f3b55e0c660e82e51eb8d21c7224a4f38f06304f141/
...
$ s3cmd ls s3://my-docker-registry/registry/repositories/
                       DIR   s3://my-docker-registry/registry/repositories/library/
$ s3cmd ls s3://my-docker-registry/registry/repositories/library/
                       DIR   s3://my-docker-registry/registry/repositories/library/registry/
```

ばっちり保存できてます！

# おわりに
こんな感じでS3などのオブジェクトストレージをバックエンドにDocker Registryを運用するとデータの永続化が非常に楽になります。
CoreOSの各ホストでDocker Registryを動かしておけばSPOFにもならないし、シンプルに運用できそうです。