自宅環境にコンテナレジストリ（Harbor）を構築してみた

# Harborとは
自宅環境に構築もできるGUI付きのコンテナレジストリである。GUI付きというところが良いところらしい。
DockerHubの自宅版と思えばよいかと。インターネット上に公開したくないイメージを扱うのに使える。

# マシンスペックの確認
以下のスペックのハードウェアを用意する。
| Resource | Minimum | Recommended |
|:-:   |:-:   |:-:    |
| CPU  | 2CPU | 4CPU  |
| Mem  | 4GB  | 8GB   |
| Disk | 40GB | 160GB |

今回は、おうちクラウドに最低スペックである2CPU、4GBメモリ、40GBのディスク領域のVMを立てて構築することにする。
Dockerさえ動けば、OSは特に指定がなさそうだったので、AlmaLinux8.6を使うことにする。

なお、必要スペックは公式ページから確認できる。

https://goharbor.io/docs/2.5.0/install-config/installation-prereqs/

## サーバーの事前準備
事前準備しておく。
```console:Harborを動かしたいサーバー
# echo "SELINUX=disabled" > /etc/selinux/config
# dnf upgrade
# dnf -y install wget
```

# 必要なソフトウェアを確認
こちらも公式ページに書いてあるものを参考にする。
| Software | Version |
|:-:|:-:|
| Docker engine | Version 17.06.0-ce+ or higher |
| Docker Compose | Version 1.18.0 or higher |
| Openssl | Latest is preferred |

すべて最新版をインストールしておけば良さそう。
DockerやDocker Composeのインストールは、以前書いた記事を参考にインストールする。
OpenSSLは最初から入ってたのでインストール不要だった。

https://qiita.com/Nats72/items/660798a9146baf68e376

# インストール手順
インストール方法は、オンラインインストーラとオフラインインストーラを使う２種類があるようである。
- オンラインインストーラは、DockerHub(GitHub?)からインストールしてくる小さいサイズでのインストーラ。
- オフラインインストーラは、ビルド済みイメージが含まれた大きいサイズのインストーラ。

容量の違いだけっぽいのでどっちでも良さそう。
今回は、オンラインインストーラを使ってインストールすることにする。

https://goharbor.io/docs/2.5.0/install-config/download-installer/

## バージョン確認
こちらのページからバージョンを確認できる。**latest**のものを選ぶと良い。

https://github.com/goharbor/harbor

2022/12/17時点ではv2.6.2が最新の安定版のようであった。
ダウンロードリンクはこちら。
ダウンロードしてSFTPでサーバーに持っていっても良いし、サーバーで`wget`してもよい。

https://github.com/goharbor/harbor/releases/download/v2.6.2/harbor-online-installer-v2.6.2.tgz

## ダウンロード＆インストール
`wget`でオンラインインストーラをダウンロード。
```console:Harborを動かしたいサーバー
# wget https://github.com/goharbor/harbor/releases/download/v2.6.2/harbor-online-installer-v2.6.2.tgz
```
インストーラを解凍。
```console:Harborを動かしたいサーバー
# tar xzvf harbor-online-installer-v2.6.2.tgz 
```

# SSL対応
自宅で使うだけだからhttpでも良いとは思うのだけど、せっかくなのでSSL対応させる。
ここで作成するSSL証明書は、HarborとDockerで利用する。

サーバーのホスト名を設定。名称はなんでもよい。
```console:Harborを動かしたいサーバー
# hostnamectl set-hostname ouchiharbor.com
```

SSL証明書を準備する。
公式を見る感じだと自己署名証明書（オレオレ証明書）でやってそうだった。

https://goharbor.io/docs/2.5.0/install-config/configure-https/

証明書保管用ディレクトリを作成。
作ったディレクトリで作成していく。
```console:Harborを動かしたいサーバー
# mkdir pki
# cd pki
```

CA証明書の秘密鍵を発行
```console:Harborを動かしたいサーバー
# openssl genrsa -out ca.key 4096
```

CA証明書を生成
```console:Harborを動かしたいサーバー
# openssl req -x509 -new -nodes -sha512 -days 3650 -subj "/C=JP/ST=Aichi/L=Toyota/O=example/OU=Personal/CN=ouchiharbor.com" -key ca.key -out ca.crt
```

サーバー証明書の秘密鍵を作成
```console:Harborを動かしたいサーバー
# openssl genrsa -out ouchiharbor.com.key 4096
```

証明書署名要求(CSR)を発行する
```console:Harborを動かしたいサーバー
# openssl req -sha512 -new -subj "/C=JP/ST=Aichi/L=Toyota/O=example/OU=Personal/CN=ouchiharbor.com" -key ouchiharbor.com.key -out ouchiharbor.com.csr
```

X509 v3設定ファイルを作成する
```console:Harborを動かしたいサーバー
# cat > v3.ext <<-EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = serverAuth
subjectAltName = @alt_names

[alt_names]
DNS.1=ouchiharbor.com
DNS.2=ouchiharbor
EOF
```
サーバー証明書を作成する
```console:Harborを動かしたいサーバー
# openssl x509 -req -sha512 -days 3650 -extfile v3.ext -CA ca.crt -CAkey ca.key -CAcreateserial -in ouchiharbor.com.csr -out ouchiharbor.com.crt
```

Dockerが解釈できるように、サーバー証明書を.certに変換する。
どうやら、Dockerは.crtをルート証明書、.certをサーバー証明書として解釈する仕様のようである。
```console:Harborを動かしたいサーバー
# openssl x509 -inform PEM -in ouchiharbor.com.crt -out ouchiharbor.com.cert
```

Docker証明書フォルダを作成して、証明書をコピーして配置
```console:Harborを動かしたいサーバー
# mkdir /etc/docker/certs.d
# mkdir /etc/docker/certs.d/ouchiharbor.com
# cp ouchiharbor.com.cert /etc/docker/certs.d/ouchiharbor.com/
# cp ouchiharbor.com.key /etc/docker/certs.d/ouchiharbor.com/
# cp ca.crt /etc/docker/certs.d/ouchiharbor.com/
```

Dockerを再起動する
```console:Harborを動かしたいサーバー
# systemctl restart docker
```

Harbor用の証明書をコピーして配置
```consoel:Harborを動かしたいサーバー
# mkdir /cert
# cp ouchiharbor.com.crt /cert
# cp ouchiharbor.com.key /cert
```

Harbor設定ファイルを編集する
`harbor.yml.tmpl`という名前のテンプレートがあるので、こちらを複製＆リネームして編集する
```console:Harborを動かしたいサーバー
# cd ../harbor
# cp harbor.yml.tmpl harbor.yml
# vi harbor.yml
```
```diff_yaml:harbor.yml
- hostname: reg.mydomain.com
+ hostname: ouchiharbor.com

...

https:
  port: 443
- certificate: /your/certificate/path
+ certificate: /cert/ouchiharbor.com.crt
- private_key: /your/private/key/path
+ private_key: /cert/ouchiharbor.com.key
```

# Harborデプロイ
prepareを実行すると、Docker Composeによってharborがデプロイされる。
```console:Harborを動かしたいサーバー
# chmod +x /root/harbor/prepare 
# /root/harbor/prepare 
```
install.shを実行
```console:Harborを動かしたいサーバー
# chmod +x /root/harbor/install.sh 
# /root/harbor/install.sh 
```
以下の表示が出れば成功
```console:Harborが動いてるサーバー
✔ ----Harbor has been installed and started successfully.----
```:Harborが動いてるサーバー
コンテナイメージやコンテナができていることが確認できる
```console
# docker images
REPOSITORY                    TAG       IMAGE ID       CREATED       SIZE
goharbor/redis-photon         v2.6.2    84fa3669bb10   5 weeks ago   154MB
goharbor/harbor-registryctl   v2.6.2    d403d4e0f990   5 weeks ago   137MB
goharbor/registry-photon      v2.6.2    596e445b18f0   5 weeks ago   77.5MB
goharbor/nginx-photon         v2.6.2    cbbdf28947a5   5 weeks ago   154MB
goharbor/harbor-log           v2.6.2    3ce902023f73   5 weeks ago   161MB
goharbor/harbor-jobservice    v2.6.2    05791a75c8b8   5 weeks ago   250MB
goharbor/harbor-core          v2.6.2    484e2a64616d   5 weeks ago   213MB
goharbor/harbor-portal        v2.6.2    932297030d4e   5 weeks ago   162MB
goharbor/harbor-db            v2.6.2    351b19e366cb   5 weeks ago   225MB
goharbor/prepare              v2.6.2    eecc993c7643   5 weeks ago   164MB
```
```console:Harborが動いてるサーバー
# docker ps
CONTAINER ID   IMAGE                                COMMAND                  CREATED          STATUS                             PORTS                                                                            NAMES
7aa4cc8b8379   goharbor/harbor-jobservice:v2.6.2    "/harbor/entrypoint.…"   21 seconds ago   Up 16 seconds (health: starting)                                                                                    harbor-jobservice
ff490819af84   goharbor/nginx-photon:v2.6.2         "nginx -g 'daemon of…"   21 seconds ago   Up 18 seconds (health: starting)   0.0.0.0:80->8080/tcp, :::80->8080/tcp, 0.0.0.0:443->8443/tcp, :::443->8443/tcp   nginx
0c4f3e0dd38d   goharbor/harbor-core:v2.6.2          "/harbor/entrypoint.…"   21 seconds ago   Up 19 seconds (health: starting)                                                                                    harbor-core
089380bfd35f   goharbor/harbor-registryctl:v2.6.2   "/home/harbor/start.…"   21 seconds ago   Up 19 seconds (health: starting)                                                                                    registryctl
3befb6e206a0   goharbor/harbor-db:v2.6.2            "/docker-entrypoint.…"   21 seconds ago   Up 20 seconds (health: starting)                                                                                    harbor-db
7882cc600b22   goharbor/harbor-portal:v2.6.2        "nginx -g 'daemon of…"   21 seconds ago   Up 19 seconds (health: starting)                                                                                    harbor-portal
482f0d9dac96   goharbor/redis-photon:v2.6.2         "redis-server /etc/r…"   21 seconds ago   Up 19 seconds (health: starting)                                                                                    redis
8e6949c4cf83   goharbor/registry-photon:v2.6.2      "/home/harbor/entryp…"   21 seconds ago   Up 19 seconds (health: starting)                                                                                    registry
114e00aff805   goharbor/harbor-log:v2.6.2           "/bin/sh -c /usr/loc…"   22 seconds ago   Up 20 seconds (health: starting)   127.0.0.1:1514->10514/tcp                                                        harbor-log
```

# ブラウザで確認
`https://{FQDN}`もしくは、`https://{IPアドレス}`で接続できる。
ログインユーザーのデフォルト値は、ユーザ名：admin、パスワード：Harbor12345になっているようである。

# イメージファイルをアップロードしたいクライアントサーバーの設定
まずは名前解決できるようにする。
今回はhostsに書いているが、おうちDNSサーバーがあるなら、そこで設定しても良いと思う。
```console:Harborに接続したいサーバー
# vi /etc/hosts 
```
```diff:hosts
+ 192.168.0.xxx ouchiharbor.com
```
ca.crtがないとlogin弾かれるようなので、scpでコピーしてくる。
```console:Harborに接続したいサーバー
# mkdir /etc/docker/certs.d
# mkdir /etc/docker/certs.d/ouchiharbor.com
# scp root@ouchiharbor.com:/etc/docker/certs.d/ouchiharbor.com/ca.crt /etc/docker/certs.d/ouchiharbor.com/ca.crt
root@ouchiharbor.com's password: 
ca.crt                                                                                                                      100% 2049     3.4MB/s   00:00 
```

# クライアントサーバーからログイン
```console:Harborに接続したいサーバー
[root@almalinux86 ~]# docker login ouchiharbor.com
Username: admin
Password: 
...
Login Succeeded
```
`Login Succeeded`が表示されればログイン成功

ログアウトは、`docker logout`でできそう。

# Harborコンテナを落とす
```console:Harborが動いてるサーバー
# ls
LICENSE  common  common.sh  docker-compose.yml  harbor.yml  harbor.yml.tmpl  install.sh  prepare
# docker-compose down
```

# 公式ページ以外に参考にさせていただいたサイト

https://www.si1230.com/?p=44422