プライベートDockerレジストリとしてのGitLab Container Registry

# GitLab Registryという選択肢
Dockerイメージの管理(registry)に[DockerHub](https://hub.docker.com/)や[GCR](https://cloud.google.com/container-registry/)，[ECR](https://aws.amazon.com/jp/ecr/)など
のサービスを利用している人も多いかと思いますがやはりローカル環境(オンプレミス環境)で
Registryサービスを構築して利用したいという人も多いと思います．

そいういうときの選択肢としては[Docker Registry](https://docs.docker.com/registry/)が始めに挙がると思いますが，
残念ながらOSS版のRegistryにはユーザ認証機能などがなく，
便利な機能は有償のDocker EEで提供される[Docker Trusted Registry](https://docs.docker.com/datacenter/dtr/2.1/guides/)を利用する必要があります．

では代替として何があるかというと，CNCFプロジェクトの1つとなった[Harbor](https://github.com/goharbor/harbor)があります．
Harborにはユーザ認証機能はもちろん，脆弱性検査などの機能もあり非常に便利ですが
運用がそれなりに面倒という課題があります．
自分も自宅で構築・運用していますが，アップデート手順がバージョンによって違ったり，
単にDockerイメージを格納するだけでもそれなりの計算機リソースが必要になったりと
手軽に始めるにはすこし大変だと思います．

そういったときに簡単に利用できるのが[GitLab Contaienr Registry](https://docs.gitlab.com/ee/user/project/container_registry.html)です．

# GitLab Container Registryの特徴
GitLab Container Registryはその名の通り，GitLabで提供されるDocker レジストリです．
gitlab.comはもちろん，gitlab-ceなど自前で構築したgitlabでも簡単に利用することができます．

GitLabのプロジェクトと連動しており，GitLabのプロジェクト名でDockerイメージ名を付与でき，
プロジェクトの公開設定と同様にレジストリのアクセス権限が設定されます．
すなわち，GitLab上にグループ名: `sample` プロジェクト名: `my-app` を構築すると
Dockerレジストリとしても `gitlab.example.com/sample/my-app` のようなDockerイメージ名が利用できます．
このときプロジェクトがpublicであれば誰でもpullできて，権限あるメンバのみ `docker login` による認証後にpushできる，
プロジェクトがprivateならメンバのみして認証後にpush/pullできる，といった感じです．

また，他のレジストリにはない機能として最大3階層までのグループ名をサポートしています．
すなわち，以下のようなDockerイメージ名を設定可能です．

    registry.gitlab.com/thaim/sample-project:tag
    registry.gitlab.com/thaim/sample-project/optional-image-name:tag
    registry.gitlab.com/thaim/sample-project/optional-name/optional-image-name:tag

また，GitLabではプロジェクト自体にサブグループの機能を持っているので，
サブグループと合わせれば以下のようなDockerイメージ名も利用可能です．
さすがにやりすぎはアンチパターンだと思いますが．

    registry.gitlab.com/topgroup/subgroup/subsubgroup/sample-project:tag
    registry.gitlab.com/topgroup/subgroup/subsubgroup/sample-project/optional-image-name:tag
    registry.gitlab.com/topgroup/subgroup/subsubgroup/sample-project/optional-name/optional-image-name:tag

一方で，DTRやHarborなどで利用可能な脆弱性検査機能は組込まれていないので
基本的には単にイメージを格納するためのものです．
GitLab Contaienr Registryで脆弱性検査を実施したいのであれば
[公式ドキュメント](https://docs.gitlab.com/ee/ci/examples/container_scanning.html)を参考にGitLab CIでプロジェクト毎に設定する必要があります．

# GitLab Container Registryのセットアップ
gitlab.comではデフォルトで有効になっており，特に追加設定なしで利用できます．
ここでは，gitlab-ce (特にomnibus版)での利用方法を記載します．

基本的には[ドキュメント](https://docs.gitlab.com/ee/administration/container_registry.html)に従ってgitlab.rbにホスト名を設定すればよいです．

    registry_external_url 'http://registry.example.com:4567'

## 権限の修正
実は(omnibus版のみ？)GitLab Container Registryには不具合があり，
パーミッションの関係でイメージをpushできません．

    $ docker push registry.example.com:4567/thaim/sample-image
    The push refers to a repository [registry.example.com:4567/thaim/sample-image]
    cd7100a72410: Retrying in 1 second 
    received unexpected HTTP status: 500 Internal Server Error

これを修正するためにはregistry関連のディレクトリに対するオーナー権限を修正する必要があります．
`/var/opt/gitlab/gitlab-rails/shared/registry/docker/` 以下のオーナーが，
`registry:registry` でなければならないところが `git:git` となっているようです．

    $ chown -R registry:registry /var/opt/gitlab/gitlab-rails/shared/registry/docker/

この操作以降は意図した通りにDockerイメージをpushできるようになります．
既にこの[不具合に関するissue](https://gitlab.com/gitlab-org/gitlab-ce/issues/41080)は解決方法含めて共有されているので近いうちに解決するはず．