DockerプライベートレジストリをSystemdサービスとして動かす

プライベートレジストリをCentOS 7のサービスとして動かす方法のメモ。

https://docs.docker.com/registry/deploying/

公式ドキュメントの記載のある以下の起動方法でも`--restart=always`としているので、dockerを再起動すると勝手に起動する。なのであえてサービス化する必要もないかもしれないが、サービスに登録して管理する方法のメモ。

```
docker run -d \
  -p 5000:5000 \
  --restart=always \
  --name registry \
  registry:2.6.2
```

## サービスとしての登録

以下のファイルを作成する。

```
sudo vi /etc/systemd/system/registry.service
```

```registry.service
[Unit]
Description=Registry
Requires=docker.service
After=docker.service

[Service]
ExecStart=/usr/bin/docker run --rm \
  --name registry \
  -p 5000:5000 \
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \
  -v /data/registry:/var/lib/registry \
  registry:2.6.2

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

- ホストの`/data/registry`をマウントしてデータを永続化
- `--rm`で停止時にコンテナを削除
- `-e REGISTRY_STORAGE_DELETE_ENABLED=true`を指定しておくとイメージの削除が可能

サービスを有効にする（システム起動時に自動的に起動するようにする）。

```
sudo systemctl enable registry
```

サービスを起動する。

```
sudo systemctl start registry
```

Systemd管理下のデーモンとして起動しているので、標準出力がjournaldに収集されている。

```
[centos@minikube ~]$ sudo journalctl -u registry --no-pager
-- Logs begin at Fri 2018-10-19 04:05:05 UTC, end at Mon 2018-10-22 02:55:14 UTC. --
Oct 22 02:55:06 minikube systemd[1]: Started Registry.
Oct 22 02:55:06 minikube systemd[1]: Starting Registry...
Oct 22 02:55:06 minikube docker[2196]: Unable to find image 'registry:2.6.2' locally
Oct 22 02:55:08 minikube docker[2196]: 2.6.2: Pulling from library/registry
Oct 22 02:55:09 minikube docker[2196]: d6a5679aa3cf: Pulling fs layer
Oct 22 02:55:09 minikube docker[2196]: ad0eac849f8f: Pulling fs layer
Oct 22 02:55:09 minikube docker[2196]: 2261ba058a15: Pulling fs layer
Oct 22 02:55:09 minikube docker[2196]: f296fda86f10: Pulling fs layer
Oct 22 02:55:09 minikube docker[2196]: bcd4a541795b: Pulling fs layer
Oct 22 02:55:09 minikube docker[2196]: f296fda86f10: Waiting
Oct 22 02:55:09 minikube docker[2196]: bcd4a541795b: Waiting
Oct 22 02:55:10 minikube docker[2196]: ad0eac849f8f: Verifying Checksum
Oct 22 02:55:10 minikube docker[2196]: ad0eac849f8f: Download complete
Oct 22 02:55:10 minikube docker[2196]: 2261ba058a15: Verifying Checksum
Oct 22 02:55:10 minikube docker[2196]: 2261ba058a15: Download complete
Oct 22 02:55:10 minikube docker[2196]: d6a5679aa3cf: Verifying Checksum
Oct 22 02:55:10 minikube docker[2196]: d6a5679aa3cf: Download complete
Oct 22 02:55:10 minikube docker[2196]: d6a5679aa3cf: Pull complete
Oct 22 02:55:11 minikube docker[2196]: f296fda86f10: Verifying Checksum
Oct 22 02:55:11 minikube docker[2196]: f296fda86f10: Download complete
Oct 22 02:55:11 minikube docker[2196]: bcd4a541795b: Verifying Checksum
Oct 22 02:55:11 minikube docker[2196]: bcd4a541795b: Download complete
Oct 22 02:55:12 minikube docker[2196]: ad0eac849f8f: Pull complete
Oct 22 02:55:12 minikube docker[2196]: 2261ba058a15: Pull complete
Oct 22 02:55:12 minikube docker[2196]: f296fda86f10: Pull complete
Oct 22 02:55:12 minikube docker[2196]: bcd4a541795b: Pull complete
Oct 22 02:55:12 minikube docker[2196]: Digest: sha256:5a156ff125e5a12ac7fdec2b90b7e2ae5120fa249cf62248337b6d04abc574c8
Oct 22 02:55:12 minikube docker[2196]: Status: Downloaded newer image for registry:2.6.2
Oct 22 02:55:13 minikube docker[2196]: time="2018-10-22T02:55:13Z" level=warning msg="No HTTP secret provided - generated random secret. This may cause problems with uploads if multiple registries are behind a load-balancer. To provide a shared secret, fill in http.secret in the configuration file or set the REGISTRY_HTTP_SECRET environment variable." go.version=go1.7.6 instance.id=390ba456-9eca-4413-8f7f-04a61c7334ab version=v2.6.2
Oct 22 02:55:13 minikube docker[2196]: time="2018-10-22T02:55:13Z" level=info msg="redis not configured" go.version=go1.7.6 instance.id=390ba456-9eca-4413-8f7f-04a61c7334ab version=v2.6.2
Oct 22 02:55:13 minikube docker[2196]: time="2018-10-22T02:55:13Z" level=info msg="Starting upload purge in 30m0s" go.version=go1.7.6 instance.id=390ba456-9eca-4413-8f7f-04a61c7334ab version=v2.6.2
Oct 22 02:55:13 minikube docker[2196]: time="2018-10-22T02:55:13Z" level=info msg="using inmemory blob descriptor cache" go.version=go1.7.6 instance.id=390ba456-9eca-4413-8f7f-04a61c7334ab version=v2.6.2
Oct 22 02:55:13 minikube docker[2196]: time="2018-10-22T02:55:13Z" level=info msg="listening on [::]:5000" go.version=go1.7.6 instance.id=390ba456-9eca-4413-8f7f-04a61c7334ab version=v2.6.2
[centos@minikube ~]$
```

## Secure Registryにする場合

自己署名証明書を作成する。

```
sudo mkdir -p /data/certs
cd /data/certs
sudo openssl req -newkey rsa:2048 -nodes -keyout domain.key -x509 -days 365 -out domain.crt
```

証明書のCNはちゃんと指定すること。

証明書を作成したフォルダをマウントして、証明書と鍵の場所を環境変数で指定する。

```registry.service
[Unit]
Description=Registry
Requires=docker.service
After=docker.service

[Service]
ExecStart=/usr/bin/docker run --rm \
  --name registry \
  -p 8500:443 \
  -e REGISTRY_HTTP_ADDR=0.0.0.0:443 \
  -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/domain.crt \
  -e REGISTRY_HTTP_TLS_KEY=/certs/domain.key \
  -e REGISTRY_STORAGE_DELETE_ENABLED=true \
  -v /data/certs:/certs \
  -v /data/registry:/var/lib/registry \
  registry:2.6.2

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

- 443は他で使っていたので8500ポートで公開

## クライアント側の設定

### Insecure Registryの場合

クライアント側でInsecure Registryとして登録する。

https://docs.docker.com/registry/insecure/

クライアントの`/etc/docker/daemon.json`を編集する。

```
sudo vi /etc/docker/daemon.json
```

```json:daemon.json
{
  "insecure-registries" : ["minikube:5000"]
}
```

Dockerを再起動。

```
sudo systemctl restart docker
```

pushする。

```
[centos@minikube certs]$ docker push minikube:5000/websphere-liberty:kernel
The push refers to a repository [minikube:5000/websphere-liberty]
fe1d522e726a: Layer already exists
9e77ba9eaafc: Pushed
8446532ec938: Pushed
8eb886ee803c: Layer already exists
b37a584582f1: Pushed
23079eb1920d: Pushed
519f68f5a195: Layer already exists
a4a5449903ec: Pushed
f1dfa8049aa6: Pushed
79109c0f8a0b: Pushed
33db8ccd260b: Pushed
b8c891f0ffec: Layer already exists
kernel: digest: sha256:1d6521b1313f08292bcdacaeb5c9ae00159f0cc9f42b67da98d77698186a1590 size: 2832
[centos@minikube certs]$
```

### Secure Registryの場合

以下を実施する。

1. クライアントの`/etc/docker/certs.d`以下にRegistyサーバーのホスト名:ポートのディレクトリを作成する
1. 作成したディレクトリに証明書をコピーして`ca.crt`とする

```
sudo mkdir -p /etc/docker/certs.d/minikube:8500
sudo cp /data/certs/domain.crt /etc/docker/certs.d/minikube:8500/ca.crt
```

pushする。

```
[centos@minikube certs]$ docker push minikube:8500/websphere-liberty:kernel
The push refers to a repository [minikube:8500/websphere-liberty]
fe1d522e726a: Pushed
9e77ba9eaafc: Pushed
8446532ec938: Pushed
8eb886ee803c: Pushed
b37a584582f1: Pushed
23079eb1920d: Pushed
519f68f5a195: Pushed
a4a5449903ec: Pushed
f1dfa8049aa6: Pushed
79109c0f8a0b: Pushed
33db8ccd260b: Pushed
b8c891f0ffec: Pushed
kernel: digest: sha256:1d6521b1313f08292bcdacaeb5c9ae00159f0cc9f42b67da98d77698186a1590 size: 2832
[centos@minikube certs]$
```

## 参考

[Systemdを使ってさくっと自作コマンドをサービス化してみる](https://qiita.com/DQNEO/items/0b5d0bc5d3cf407cb7ff)

[privateなdockerレジストリを構築する](https://qiita.com/zknzfz/items/13d5d07ab5bb0feb1fd1)