GitLab Container Registry

# GitLab Container Registry
[GitLab Advent Calendar 2016](http://qiita.com/advent-calendar/2016/gitlab) の九日目は Docker Image のレジストリである [GitLab Container Registry](https://docs.gitlab.com/ce/user/project/container_registry.html) の紹介をしたいと思います。


## 概要
ビルドした Docker Image を [Docker Hub](https://hub.docker.com/) にプッシュされている方は多いのではないでしょうか?

GitLab CE/EE には [GitLab Container Registry](https://docs.gitlab.com/ce/user/project/container_registry.html) が統合されており、Docker Hub と同じように Docker Image を保管することができます。もちろんこの機能は GitLab.com でも使うことができます。

公式の Docker Hub を使ってもいいのですが、GitLab Container Registry を個人的におすすめする理由はいくつかあります。

まず第一に、社内にサーバーを立てて社内で使う Container Registry が構築できることです。(構築方法は[四日目の記事、GitLab をインストールしよう! (omnibus package)](http://qiita.com/masakura/items/0a0f00dfdddc8ce27f29) をご覧ください)

第二に、GitLab.com でプライベートでも無料で使えるからです。(価格については[八日目の hiroponz さんの記事、GitHub.com・BitBucket.org・GitLab.comの月額料金比較 + α](http://qiita.com/hiroponz/items/c1ed4d6c10484233bf88) をご覧ください)

第三に、GitLab に完全に統合されているからです。アカウントに GitLab のものが使えるのはもちろんですが、GitLab CI ともうまく統合されており、トークンやパスワードを設定することなしに CI から Docker Image をプッシュすることができます。面倒な操作の必要がないのももちろんですが、トークンを設定する必要がない分安心感があります。

## 使い方
パソコンに Docker Engine がインストールされていることとします。


### GitLab.com 編
まずは GitLab.com で使ってみましょう!

[GitLab.com](https://gitlab.com/users/sign_in) にログインして、プロジェクトを作成してください。デフォルトで Container Registry は有効化されていますので、すぐに使いはじめることができます。

`Registry` タブをクリックすると、まだひとつも Docker Image が登録されていないことが分かります。しかも、使い方まで書いてあるので非常に便利ですね! (この記事の意味って一体...)

![gitlab1.png](https://qiita-image-store.s3.amazonaws.com/0/103982/199ee00f-b638-b6f8-033e-7ba33f4e1b7a.png)

書かれている通り、まずはログインをします。GitLab.com のアカウント名とパスワードを入力してください。

```text
$ docker login registry.gitlab.com
```

次に Docker Image を作ってプッシュしてみます。`Dockerfile` を書くのは面倒ですので、今回は別の方法を使います。

```text
$ docker pull hello-world
$ docker tag hello-world registry.gitlab.com/masakura/docker-sample
$ docker push registry.gitlab.com/masakura/docker-sample
```

ページをリロードすると `latest` イメージが作成されました!

![gitlab2.png](https://qiita-image-store.s3.amazonaws.com/0/103982/a2a5d060-e63b-53db-e0e5-a231606d199b.png)

ちなみに Docker Image 名の右のコピーボタンをクリックすると、`docker pull` コマンドとセットで Docker Image 名がクリップボードにコピーされます。覚えておくと便利だと思います。

このような形で、GitLab はプロジェクトに一つだけ Docker Image を保管することができます。


### GitLab CE 編
GitLab CE で GitLab Container Registry を使う場合は、機能を有効化する必要があります。有効化の方法は[四日目の記事、GitLab をインストールしよう! (omnibus package)](http://qiita.com/masakura/items/0a0f00dfdddc8ce27f29) をご覧ください。

FQDN が GitLab.com と異なりますので、Docker Image 名やログインする Docker ホスト名が変わるくらいであとは GitLab.com と同じように使うことができます。

ところで、社内のサーバーに GitLab CE をインストールする場合、SSL を使わないことがよくあると思います。(個人的にはよくないと思うのですが...)

Docker Engine は SSL でない Container Registry には接続できません。以下のように接続に失敗します。証明書の購入をおすすめします。

```text
$ docker login registry.example.com
Username: root 
Password: 
Error response from daemon: Get https://registry.example.com/v1/users/: dial tcp 192.168.42.65:443: getsockopt: connection refused
```

ですが、どうしても SSL を有効に出来ない場合、Docker Engine の設定の `insecure-registry` に Container Registry の名前を設定するとアクセスできるようになります。

Linux で Docker Engine を動作させている場合は、`/etc/systemd/system/docker.service.d/local.conf` ファイルを作成し、`systemctl daemon-reload` のあとサービスを再起動してください。

```text
[Service]
ExecStart=
ExecStart=/usr/bin/dockerd -H fd:// --insecure-registry=registry.example.com
```

```text
$ sudo systemctl daemon-reload
$ sudo service docker restart
```

今度は無事ログインできました!

```text
$ docker login registry.example.com
Username: root
Password: 
Login Succeeded
```

設定の変更方法については [Control and configure Docker with systemd](https://docs.docker.com/engine/admin/systemd/) をご覧ください。

また、[Docker for Windows](https://docs.docker.com/docker-for-windows/#/docker-daemon) や [Docker for Mac](https://docs.docker.com/docker-for-mac/#/advanced) をお使いの方は設定画面から `insecure-registry` を追加してください。

でも、これらの設定を Container Registry の利用者全員にお願いするのはとても面倒ですよね! ですので、証明書を買ってきて設定したほうが楽だと思います!


### GitLab CI 編
続いて GitLab CI から Docker Image を Container Registry にプッシュする方法です。GitLab.com を使います。

GitLab CI は `.gitlab-ci.yml` ファイルにスクリプトを用意するだけで使うことができます。さらに、テンプレートも用意されていますので、簡単に使うことができます。

先ほど作ったプロジェクトのダッシュボードに `README` というリンクがありますので、それをクリックして `Commit Changes` で保存しましょう! (中身はなしで構いません)

続いて、`Repository` タブの `+` -> `New file` ボタンをクリックし `Dockerfile` ファイルを作成してください。ファイルの内容は以下の一行だけで構いません。

```text
FROM nginx
```

`Commit Changes` ボタンで保存します。

再度プロジェクトのダッシュボードに戻って、`Set Up CI` ボタンをクリックします。`Choose a GitLab CI Yaml Template` から `Docker` を選びます。

![gitlab3.png](https://qiita-image-store.s3.amazonaws.com/0/103982/6e0b2f1a-6377-3ee2-4476-bc0a5a956fc5.png)

こんな感じです。

```yaml
# This file is a template, and might need editing before it works on your project.
# Official docker image.
image: docker:latest

services:
  - docker:dind

build:
  stage: build
  script:
    - docker login -u "gitlab-ci-token" -p "$CI_BUILD_TOKEN" $CI_REGISTRY
    - docker build --pull -t "$CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_BUILD_REF_NAME"
```

`Commit Changes` ボタンをクリックしてしばらく待つと...

![gitlab4.png](https://qiita-image-store.s3.amazonaws.com/0/103982/cb5871da-c795-5298-a6eb-f41b7549cfa8.png)

できました!

`docker login` のスクリプトで、CI でのビルドごとに生成されるトークンを使ってログインしていることが分かります。つまり、GitLab CI + GitLab Container Registry の組み合わせでは、ユーザー名やパスワードを設定する必要がなく、安全で簡単に使えることが分かると思います。


## 注意点
### Docker Image 名は小文字のみ
Docker Image には大文字や多くの記号を使うことができません。このため、GitLab のプロジェクト名とグループ名 (もしくはユーザー名) を小文字に変換されたものが Docker Image 名に使われています。

大文字小文字だけが違うプロジェクトを作った場合、Container Registry は共有されてしまうようです。(流石に、大文字小文字だけが違うグループは作れないようですので、赤の他人に Docker Image を取られることはなさそうですが...)


### Docker Image を消すと同じ Image ID のが全て消える
GitLab Container Registry から Docker Image を消すと、同じ Image ID の Docker Image が全て消えます。


### パスワードを設定しておく必要がある
主に GitLab.com のお話ですが、GitHub などの外部認証を使ってログインされている方はパスワードが未設定な状態となります。パスワードを設定するまでは `docker login` ができないと思われます。


### Docker in Docker で overlayfs を使う
GitLab CI で Docker Image をビルドする方法を紹介しました。こちらは Docker in Docker という Docker 社公式の方法を使ったものです。

ですが、GitLab のドキュメント、[Using Docker Build](https://docs.gitlab.com/ce/ci/docker/using_docker_build.html) の中の [Using the OverlayFS driver](https://docs.gitlab.com/ce/ci/docker/using_docker_build.html#using-the-overlayfs-driver) でパフォーマンスの問題が言及されています。

> By default, when using docker:dind, Docker uses the vfs storage driver which copies the filesystem on every run. This is a very disk-intensive operation which can be avoided if a different driver is used, for example overlay.

デフォルトではストレージドライバーに vfs が使われるためディスクに厳しく、overlayfs を使ったほうがいいと書かれています。

GitLab.com では `.gitlab-ci.yml` ファイルに少し書き足すだけで、overlayfs が使われるようになります。

```
variables:
  DOCKER_DRIVER: overlay
```


## 終わり
ちょっと長くなりましたけど、GitLab Container Registry で Docker Image を活用する方法はいかがだったでしょうか? こういったものが GitLab で完結して利用できるのはとても便利で、気に入ってしまいました!


## 追記
GitLab 8.14 から [Support for private container registries in GitLab CI builds](https://about.gitlab.com/2016/11/22/gitlab-8-14-released/#support-for-private-container-registries-in-gitlab-ci-builds) にあるとおり、プライベートプロジェクトの Container Registry の Docker Image を指定してビルドできるようになったようです。

プライベートプロジェクトではビルド用のカスタム Docker Image も公開したくないと思います。そういう時に非常に有用だと思います。