CoreOS 上に Private Docker Registry を立てる


## はじめに
Private Docker Regisry を立てられる [docker-registry](https://github.com/docker/docker-registry) というイメージ（docker-registry は python の gunicorn アプリケーションとして実装されてる）が docker 公式で用意されている。docker-registry は local, S3 や GCS 等色んなストレージをイメージの保存先として使うことができる。

## docker-registry をどう使うか
docker-registry は 1 台でも冗長構成でも良いが、ある 1 つのエンドポイントを使おうとすると

* SPOF になる
* 利用元サーバが大量にある場合、負荷を気にする必要が出てくる
* ローカルからも本番サーバからも利用しようとすると認証機構が必要になる
 * 本番サーバだけであれば同じネットワーク内のみ許可、のような形で制限はできるがローカルから pull/push できなくなる

そこで、docker-registry を全 Docker サーバで起動しておき localhost の registry に問い合わせるようにすることで

* 認証機構を用意しないで済む
* SPOF を作らない
* 負荷もほとんど気にしなくて良い
* ローカルの OSX でも CoreOS でも docker-registry イメージを使って同じ仕組みが使える

というメリットがある。

## docker-registry 用の S3 bucket を用意する
docker-registry 用に新しく S3 bucket を用意する。作成後、特にディレクトリは作る必要はない。使い始めると

```
$ aws s3 ls s3://wantedly-docker-registry/
                           PRE images/
                           PRE repositories/
```

というディレクトリが自動で作られる。

### docker-registry で利用する IAM User の権限

```json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "s3:Get*",
        "s3:List*"
      ],
      "Resource": [
        "arn:aws:s3:::your-bucket-name",
        "arn:aws:s3:::your-bucket-name/*"
      ]
    }
  ]
}
```

## コマンドラインから registry を起動する

```bash
core@core-01 ~ $ docker run \
  -d \
  --name registry \
  -e SETTINGS_FLAVOR=prod \
  -e AWS_BUCKET=your-bucket-name \
  -e AWS_KEY=XXXXXXXXXXXXXXXXXXX \
  -e AWS_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx \
  -e AWS_SECURE=true \
  -e DOCKER_REGISTRY_CONFIG=/docker-registry/config/config_sample.yml \
  -e STORAGE_PATH=/ \
  -e SEARCH_BACKEND=sqlalchemy \
  -e GUNICORN_WORKERS=3 \
  -p 5000:5000 \
  registry:0.7.3 \
  docker-registry
```

これで以下のように registry を利用出来る

```bash
$ docker pull localhost:5000/<user>/<repo>/<tag>
$ docker push localhost:5000/<user>/<repo>/<tag>

# 例
$ docker pull localhost:5000/wantedly/ubuntu:latest
$ docker push localhost:5000/wantedly/ubuntu:latest
```

## Cloud-Config から registry を起動する
CoreOS クラスタの各マシンで起動しておく必要があるので以下のように書く。

```yaml
#cloud-config
# 一部抜粋

coreos:
  units:
    - name: registry.service
      command: start
      enable: true
      content: |
        [Unit]
        Description=Private 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:0.7.3
        ExecStart=/usr/bin/docker run -d --name registry -e SETTINGS_FLAVOR=prod -e AWS_BUCKET=your-bucker-name -e AWS_KEY=XXXXXXXXXXXXX -e AWS_SECRET=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx -e AWS_SECURE=true -e DOCKER_REGISTRY_CONFIG=/docker-registry/config/config_sample.yml -e STORAGE_PATH=/ -e SEARCH_BACKEND=sqlalchemy -e GUNICORN_WORKERS=3 -p 5000:5000 registry:0.7.3 docker-registry

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

## メモと感想
### キャッシュ機能が追加されてる
最近キャッシュ機能が追加され redis と組み合わせと速度が上がるとのことで、近いうちに試そう

### 本番では Nginx か Apache と組み合わせる
[What about a production environment](https://github.com/docker/docker-registry#what-about-a-production-environment) にあるように本番では Nginx か Apache を前に置いた方が良い。apache コンテナか nginx コンテナを用意する。

### 常時起動でなくて都度起動するやり方もあり
gunicorn の worker 数にもよるが常時起動しておくと、500 MB 強 くらいのメモリは取るので、都度起動して、pull/push 終わったらコンテナ終了とするとマシンリソース的にはより効率的になる。常に起動しておいた方がシンプルではある

### バージョンによってハマる
https://github.com/docker/docker-registry/issues/400 で色々と話されているが S3  をストレージにした際に docker-regisry がハングしたり、 region 指定しろと言われてエラーになったりとハマりどころがある... 0.8.x も使ってみたけどまた動かない...

### docker hub と quay.io と private registry どれがいいか
これが正解、みたいにはなくても状況によってどれがよい、というのはありそう。別ポストで整理してみよう。ちょっと quay.io に惹かれている...

## REF

* [docker/docker-registry](https://github.com/docker/docker-registry)
* [Amazon S3をDockerプライベートレポジトリにしてAWS ElasticBeanstalk環境にデプロイ](http://aws.typepad.com/sajp/2014/06/eb-docker-private-repo.html)