AWS(EC2 linux)でprivate docker registryを立てる

AWS(EC2 linux)でprivate docker registryを立ててみた
※シンプルな方法

##1.EC2にdockerをinstall


`sudo yum update -y`

`sudo yum install -y docker`

dockerサービスを起動する

`sudo service docker start`

sudoでなくてもdockerコマンドを利用できるようにする設定

`sudo usermod -a -G docker ec2-user`

実行後は一旦ログオフして再接続すると反映される

起動しているか確認

`docker info`

参考
http://docs.aws.amazon.com/AmazonECS/latest/developerguide/docker-basics.html



##2.docker-registryを起動

docker-registryはコンテナイメージとして提供されているので、docker runコマンドで起動することで容易にdocker-registryを立てられる
dockerにはバージョンが２種類あり、v1、v2がある。v2が推奨されているため今回はv2(2.1)を起動


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

-d オプション: バックグラウンド実行（デーモン化）を指定
-p オプション: ホストの TCP 5001 番ポートとコンテナの TCP 5000 番ポートをバインディング

registryデータはデフォルトではホストサーバのファイルシステムに格納されるが、オプション指定でS3バケットに格納することもできる


docker psコマンドで起動できたことを確認

```
$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
eff5cfac777b        registry:2.1        "registry cmd/registr"   2 minutes ago       Up 2 minutes        0.0.0.0:5000->5000/tcp   determined_visvesvaraya
```

参考
https://docs.docker.com/registry/deploying/#configure-tls-on-a-registry-server
http://dev.classmethod.jp/cloud/docker-registry-recipes/


##3.作成したprivate repogitryにdockerイメージをpush/pull

(1) private registryを立てた同じサーバ上から

まずはdocker hubから任意のイメージをpull(Download)する

`docker pull ubuntu:latest`

pullできたことを確認

```
$ docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                  latest              6cc0fc2a5ee3        3 weeks ago         187.9 MB
```

pullしたイメージをローカルのprivate registryへpushする用にtag付けする

`docker tag ubuntu localhost:5000/ubuntu`

確認

```
$ docker images
REPOSITORY              TAG                 IMAGE ID            CREATED             VIRTUAL SIZE
ubuntu                  latest              6cc0fc2a5ee3        3 weeks ago         187.9 MB
localhost:5000/ubuntu   latest              6cc0fc2a5ee3        3 weeks ago         187.9 MB
```

次にprivate registryへpush

`docker push localhost:5000/ubuntu`

pushしたイメージを今度はpullしてみる。
その前にlocalのイメージを削除する（同じイメージのため）

`docker rmi localhost:5000/ubuntu`

private registryから先ほどpushしたイメージをpullする

`docker pull localhost:5000/ubuntu`

private registryのimage一覧表示方法は、v2.1以降は以下。(v2ではAPIがない模様)

`curl -k https://localhost:5000/v2/_catalog`

※事前に4項のSSL証明書設定を行う必要あり
※オレオレ証明書なため、-kをつけない場合拒否される

参考
https://academy.gmocloud.com/advance/20151005/256
http://tanksuzuki.com/post/private-docker-registry/

(2) 他のクライアント（dockerホスト）から

※前提として、private registryを立てたEC2と同じVPC内にホスト用EC2をたてて、1項の手順でdockerをインストールする。
また、private registryを立てたサーバ側のセキュリティポリシーで、クライアントホストからのTCP通信を許可する設定にしておく。

今回はpull/pushをSSLを使わずに行う
以下がHTTPSではなくHTTPでpull/pushできるようにするためのクライアント側のオプション設定

`sudo vi /etc/sysconfig/docker`

以下を追記
`OPTIONS="--insecure-registry <サーバ側のローカルIP>:5000"`

dockerを再起動して反映

`sudo service docker restart`

同一VPC内のprivate registryからイメージをpull

`docker pull <サーバ側のローカルIP>:5000/ubuntu`

※(1)でpushしたイメージ



##4.HTTPSでpull/push （SSLオレオレ証明書の設定）

DockerホストとRegistry間の通信は基本HTTPSで行う。
公式な証明書設定が理想だが、ここではオレオレ証明書を設定する。

docker registryを立てるサーバのホストで、opensslでSSL証明書を作成。

```
$ cd
$ mkdir certs
$ openssl req -newkey rsa:2048 -nodes -keyout certs/domain.key -x509 -days 3650 -out certs/domain.crt

Generating a 2048 bit RSA private key
.........................................+++
..........................................................+++
writing new private key to 'certs/domain.key'
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:test
Organization Name (eg, company) [Default Company Ltd]:company
Organizational Unit Name (eg, section) []:test
Common Name (eg, your name or your server's hostname) []:mydocker
Email Address []:test@mydocker.com
```

Common Name以外は適当で良い。

作成した証明書ファイルを指定してdocker registry起動。

```
docker run -d -p 5000:5000   -e
 REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt   -e
 REGISTRY_HTTP_TLS_KEY=/certs/domain.key   -v $(pwd)/certs:/certs 
 registry:2.1
```

※~/certs/配下に証明書を格納した場合の例

###クライアントホスト側設定

docker pull/pushを行うクライアント側のホストに、さっき作成したcrtファイルを配布する。

dockerの証明書格納用フォルダを作成。
今回はCommon Nameをmydocker、5000ポートでLISTENするので、以下の通り。

`sudo mkdir -p /etc/docker/certs.d/mydocker:5000`

作成したdomain.crtを`/etc/docker/certs.d/mydocker:5000/ca.crt`として格納する。
また、/etc/hostsに、mydockerドメインのIPアドレスを記載しておく必要あり。
クライアントから 'docker pull mydocker:5000/[コンテナ名]' でpullできる。


###エラー

docker pullして下記エラーに遭遇したら、registryかclient側のcertのパスなどが正しいか確認。

```
x509: certificate is valid for xxx not for yyy
```