DockerレスでDocker Registryを動かす。Basic認証出来るまで

出来ることは出来るんだろうなと思いつつ、やったことがないのでチャレンジ。
結論から書くと、Dockerイメージを使うよりも簡単。

# モノ
DockerHubにあるのは以下。
https://hub.docker.com/_/registry

そのDockerfileから、使っているバイナリを確かめる。
https://github.com/docker/distribution-library-image/blob/master/Dockerfile

そのバイナリのGitHubプロジェクトは以下。
https://github.com/distribution/distribution/

releasesのページにビルド済みのバイナリが置いてある。
https://github.com/distribution/distribution/releases

# 環境
Amazon Lightsailで$3.5(メモリ512MB)のUbuntu 20.04マシンを用意。

# Docker registyをインストールする
Goプロダクトなのでシングルバイナリであり、tgzファイルを落として解凍すれば実行可。

```bash
$ wget https://github.com/distribution/distribution/releases/download/v2.8.1/registry_2.8.1_linux_amd64.tar.gz
$ tar xzf registry_2.8.1_linux_amd64.tar.gz
```

# とりあえず起動

レジストリの設定ファイル内容については以下。
https://docs.docker.com/registry/configuration/

必要最低限ぽい値だけ設定ファイルに記述し、とりあえず起動。

```bash
$ cat >> config.yml << EOF
version: 0.1
http:
  addr: :5000
EOF
$ mkdir data
$ export REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=./data
$ ./registry serve config.yml
```

# Docker CLIから接続確認
別の$3.5/Ubuntu 20.04のLightsailインスタンスを作成して、それにDockerをインストール。
https://docs.docker.com/engine/install/ubuntu/
てか、Dockerをインストールするのがメンドくて最近敬遠しがち。。

```bash
$ sudo apt-get remove docker docker-engine docker.io containerd runc
$ sudo apt-get update
$ sudo apt-get install \
    ca-certificates \
    curl \
    gnupg \
    lsb-release
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
$ echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
$ sudo apt-get update
$ sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
$ sudo docker run hello-world
```

hello-worldのイメージを、先に作ったレジストリにpushしてみる。

```bash
$ sudo docker images
$ REGISTRY=＜レジストリサーバーの「プライベート」IPアドレス＞
$ cat > daemon.json << EOF
{"insecure-registries":["${REGISTRY}:5000"]}
EOF
$ sudo cp daemon.json /etc/docker/
$ sudo systemctl restart docker
$ sudo docker tag hello-world ${REGISTRY}:5000/test/hello-world
$ sudo docker push ${REGISTRY}:5000/test/hello-world
（出力結果）
Using default tag: latest
The push refers to repository [172.26.6.23:5000/test/hello-world]
e07ee1baac5f: Pushed
latest: digest: sha256:f54a58bc1aac5ea1a25d796ae155dc228b3f0e11d046ae276b39c4bf2f13d8c4 size: 525
```

うんまあ、良さそう。

# Registryにbasic認証を付ける
htpasswdで認証を設定する。
以下のコマンドを実行する前に、実行中のregistryのsshセッションでCtrl+cでプロセスを止めておく。
htpasswdはbcryptでの暗号化が必要。

```bash
$ sudo apt install -y apache2-utils
$ htpasswd -B -c ./htpasswd user1
$ cat >> config.yml << EOF
version: 0.1
http:
  addr: :5000
auth:
  htpasswd:
    realm: basic-realm
    path: ./htpasswd
EOF
```

んで、もう一回起動。

```
$ ./registry serve config.yml
```

# Docker CLIでの動作確認（認証）
先のDocker CLIを導入したsshセッションに戻って、おもむろに再度docker pushする。
以下のように失敗する。

```bash
$ sudo docker push ${REGISTRY}:5000/test/hello-world
（出力結果）
Using default tag: latest
The push refers to repository [172.26.6.23:5000/test/hello-world]
e07ee1baac5f: Preparing
no basic auth credentials
```

docker loginしてから再度pushすれば成功する。
まあ、結果はalready existsだが。

```bash
$ sudo docker login -u user1 ${REGISTRY}:5000
$ sudo docker push ${REGISTRY}:5000/test/hello-world
```

# ついでに
Registryを自己署名証明書でTLS有効にして、systemdで起動するまでやるなら以下の通り。

```bash
$ openssl genrsa -out ./key 2048
$ openssl req -key ./key -new -out ./csr -batch
$ openssl x509 -signkey ./key -in ./csr -req -days 3650 -out ./crt
$ cat > config.yml << EOF
version: 0.1
storage:
  filesystem:
    rootdirectory: /registry/data
http:
  addr: :5000
  tls:
    certificate: /registry/crt
    key: /registry/key
  headers:
    X-Content-Type-Options: [nosniff]
auth:
  htpasswd:
    realm: basic-realm
    path: /registry/htpasswd
EOF
$ sudo mkdir /registry
$ sudo mkdir /registry/data
$ sudo cp registry config.yml htpasswd key crt /registry
$ cat > registry.service << EOF
[Unit]
Description=registry

[Service]
ExecStart=/registry/registry serve /registry/config.yml
Restart=always

[Install]
WantedBy=multi-user.target
EOF
$ sudo cp registry.service /etc/systemd/system/
$ sudo systemctl enable registry --now
```