Docker Registry 2.0 を使ってみる

以前は、[docker-registry](https://github.com/docker/docker-registry)を利用してPrivate Docker Regisryを作っていましたが、[Registry 2.0](https://blog.docker.com/2015/04/faster-and-better-image-distribution-with-registry-2-0-and-engine-1-6/)の発表をもってdocker-registryがDeprecatedとなりました。

[Registry 2.0](https://github.com/docker/distribution)はGoで書きなおされ、以下のような新しい機能も追加されました。
## Webhook notifications
imageがpushされたら指定されたエンドポイントを呼び出すことが出来ます。
CIとの連携やチャットツールへの通知に利用可能です。

## Native TLS support
Registryの設定でTLSを有効にできるので、よりセキュアとなりました。

----

# セットアップ

[手順はこちらを参考にしてます](https://docs.docker.com/registry/deploying/)

## Docker Regisryの準備

事前準備として以下の作業を終わらせておきます。

- S3へのPutとGetの権限をもったACCESS KEY
- 上記の権限で利用できるS3のバケット

せっかくなので実際に導入しそうな、ストレージにS3を使った方法を試してみたいと思います。
サーバとして使うのはAmazon Linux
dockerのバージョンは

```
docker -v
Docker version 1.6.2, build 7c8fca2
```

適当なディレクトリにcloneしてきます

```
git clone https://github.com/docker/distribution.git
```

configファイルを編集してストレージにS3を利用するように設定します。

`vim cmd/registry/config.yml`

```
storage:
    filesystem:
        rootdirectory: /tmp/registry-dev
```
↑ `filesystem`の設定を消して、代わりにS3の設定を追加します。

```
storage:
    s3:
        accesskey: <発行したaccess key>
        secretkey: <発行したsecret key>
        region: ap-northeast-1
        bucket: <バケット名>
        encrypt: true
        secure: true
        v4auth: true
        chunksize: 5242880
        rootdirectory: /
```

|パラメータ  |必須  |説明  |
|---|---|---|
| accesskey  |yes  |AWS Access Key  |
| secretkey  |yes  |AWS Secret Key  |
| region | yes | リージョン|
| bucket | yes | バケット |
| encrypt | no | 暗号化形式でイメージを保存するか。デフォルトはfalse|
| secure | no | HTTPSアクセスを利用するか。デフォルトはfalse|
| v4auth | no | [AWS Signature Version 4](http://docs.aws.amazon.com/AmazonS3/latest/API/sig-v4-authenticating-requests.html)を使うか。デフォルトはfalse|
| chunksize | no | チャンクサイズ。S3のAPIでマルチアップロードする際のチャンクは少なくとも５Mである必要があります。|
| rootdirectory | no | S3に格納する際のキーのprefix。指定されたprefixに`/docker/registry/v2/repositories/イメージ名`というキーで保存されます|
[その他の設定はこちらに詳細があります](http://docs.docker.com/registry/configuration/)

イメージをビルド＆コンテナの起動

```
docker build -t registry .

docker run -d -p 5000:5000 registry
```

### pushしてみる

ローカルはMac上でboot2dockerを使ってます

```
boot2docker version

Boot2Docker-cli version: v1.6.2
Git commit: cb2c3bc
```

別の端末からdockerイメージを作ってpushしてみましょう

```
# パブリックリポジトリからサンプルを実行
docker run hello-world

# dockerイメージが登録されてます
docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world         latest              91c95931e552        7 weeks ago         910 B

# registryサーバの名称でtagを作成します
docker tag hello-world:latest my-registry.com:5000/hello-world:latest

docker images
REPOSITORY                                  TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
hello-world                                 latest              91c95931e552        7 weeks ago         910 B
my-registry.com:5000/hello-world   latest              91c95931e552        7 weeks ago         910 B

# push
docker push my-registry.com:5000/hello-world:latest
The push refers to a repository [my-registry.com:5000/hello-world] (len: 1)
91c95931e552: Image already exists
a8219747be10: Image successfully pushed
Digest: sha256:b9ab97b754952ff68d5db3cb1d44f2db38d7777e0d824a41c1193179b805b0de

# 確認
curl -X GET http://my-registry.com:5000/v2/hello-world/tags/list
{"name":"hello-world","tags":["latest"]}
```

以下のようなエラーが出る場合

```
FATA[0000] Error response from daemon: v1 ping attempt failed with error: Get https://my-registry.com:5000/v1/_ping: x509: certificate signed by unknown authority. If this private registry supports only HTTP or HTTPS with an unknown CA certificate, please add `--insecure-registry my-registry.com:5000` to the daemon's arguments. In the case of HTTPS, if you have access to the registry's CA certificate, no need for the flag; simply place the CA certificate at /etc/docker/certs.d/my-registry.com:5000/ca.crt
```

推奨されているhttpsでの通信ができなかったからエラーが出ているので、以下のコマンドでinsecure-registryのフラグを指定します。

```
boot2docker ssh "echo $'EXTRA_ARGS=\"--insecure-registry my-registry.com:5000\"' | sudo tee -a /var/lib/boot2docker/profile && sudo /etc/init.d/docker restart"
```

### 登録されているイメージからコンテナを実行してみる

```
# ローカルに登録されているイメージを一旦消す
docker rmi -f $(docker images -q -a )

# 実行
docker run my-registry.com:5000/hello-world
Unable to find image 'my-registry.com:5000/hello-world:latest' locally
latest: Pulling from my-registry.com:5000/hello-world
a8219747be10: Pull complete
91c95931e552: Already exists
Digest: sha256:b9ab97b754952ff68d5db3cb1d44f2db38d7777e0d824a41c1193179b805b0de
Status: Downloaded newer image for my-registry.com:5000/hello-world:latest
Hello from Docker.
This message shows that your installation appears to be working correctly.

To generate this message, Docker took the following steps:
 1. The Docker client contacted the Docker daemon.
 2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
    (Assuming it was not already locally available.)
 3. The Docker daemon created a new container from that image which runs the
    executable that produces the output you are currently reading.
 4. The Docker daemon streamed that output to the Docker client, which sent it
    to your terminal.

To try something more ambitious, you can run an Ubuntu container with:
 $ docker run -it ubuntu bash

For more examples and ideas, visit:
 http://docs.docker.com/userguide/
```

boot2dockerのバージョンが古いと、registryに対してv1のAPIを叩きに行こうとしてエラーになるので、バージョンに注意する必要があります。