JenkinsJobをDockerで処理する（1. DockerRegistry構築編）


Jenkinsを使って色々なプロダクトのビルドをするようになってくると、プロダクト間でのライブラリやツールのバージョン競合が増えてきます。また、ビルド用のツールをJenkinsに設定するため、Jenkins設定の管理も必要になるのでこれも手間です。そこで、できるだけビルド設定は各プロダクト内で管理したい、Jenkinsへの依存は減らしたいと思ったのでビルド環境をDockerで作成し、JenkinsJobはJenkinsfileで設定するようにしました。

## やること

1. Dockerイメージを管理するPrivateRegistryの構築
2. [ビルド用Dockerイメージの作成](http://qiita.com/ogasada0/items/6ad8e4d263c34a19c3ca)
3. [ビルド処理をJenkinsfileで設定](http://qiita.com/ogasada0/private/bf548f2b08a231c1e4d1)

これから3回に分けて書いていきたいと思います。

## 1. Dockerイメージを管理するPrivateRegistryの構築

JenkinsJobを処理する環境に手動でビルド用のDockerイメージを作成するのは手間なので、docker pullできるようにするためPrivateDockerRepogistryを作成します。

社内ではGitLabを使っていて、GitLabにはDockerRegistryも入っているので、今回はこれを利用します。

社内のGitLabはDockerで動いており、そのイメージは[sameersbn/docker-gitlab](https://github.com/sameersbn/docker-gitlab)を使わせてもらっています。READMEに従って[GitLab Container Registry](https://github.com/sameersbn/docker-gitlab/blob/master/docs/container_registry.md)の設定を行います。

### サーバー証明書の準備

DockerRegistryを使うためにはHTTPSによる通信が必要になります。そこでサーバー証明書が必要になりますが、今回は自己証明書で対応します。（自己証明書だと利用する側への設定（後述）も必要になるので管理面でもセキュリティ面でもちゃんとした証明書を利用したほうがいいです）

DockerRegistryを構築するホスト名を`gitlab.example.com`とした場合、以下のコマンドで証明書を作成します。

```bash
$ openssl req -nodes -newkey rsa:4096 -keyout gitlab.exapmle.com-auth.key -out gitlab.exapmle.com-auth.csr -subj "/CN=gitlab.example.com"
$ openssl x509 -in gitlab.example.com-auth.csr -out gitlab.example.com-auth.crt -req -signkey gitlab.example.com-auth.key -days 3650
```

これで、`gitlab.example.com-auth.key`, `gitlab.example.com-auth.csr`, `gitlab.example.com-auth.crt`の3つが作成されます。このうち`.key`,`.crt`の2つを利用します。

次に、DockerRegistryに接続する側に先ほど作成したサーバー証明書を登録します。信頼された証明機関から発行された証明書を利用する場合は、この作業は不要です。

接続する側がLinuxの場合、先ほど作成した`gitlab.example.com-auth.crt`ファイルを`/etc/docker/certs.d/gitlab.example.com:5000/ca.crt`として配置します。配置先のディレクトリ名の`gitlab.example.com:5000`はDockerRegistryが稼働しているサーバーのホスト名、ポート番号になります。

Linux以外の場合など詳しくは、[docker docs(DockerRegistry)](https://docs.docker.com/registry/insecure/#using-self-signed-certificates)を参照してください。

### DockerRegistryコンテナの設定

GitLabからDockerRegistryを利用できるようにするため、GitLabのdocker-compose.ymlの設定を変更します。

まずは、GitLabコンテナの設定変更です。

```docker-compose.yml（一部抜粋）
gitlab:
  ・・・
  volumes:
  - /opt/docker/gitlab/certs:/certs
  ・・・
  external_links:
  - "registry:gitlab.example.com"
  environment:
  - GITLAB_REGISTRY_ENABLED=true
  - GITLAB_REGISTRY_HOST=gitlab.example.com
  - GITLAB_REGISTRY_PORT=5000
  - GITLAB_REGISTRY_API_URL=https://gitlab.example.com:5000
  - GITLAB_REGISTRY_CERT_PATH=/certs/gitlab.example.com-auth.crt
  - GITLAB_REGISTRY_KEY_PATH=/certs/gitlab.example.com-auth.key
  ・・・
```

サーバー証明書はGitLabコンテナとDockerRegistryコンテナの両方で参照するので、ホスト上（/opt/docker/gitlab/certs）に配置して共有するようにしています(volumesの設定）。また、gitlabコンテナ内からregistryコンテナへ`gitlab.example.com`という名前でアクセスできるようにするため、external_linksを設定しています。公式ドキュメントにはexternal_linksの設定はなく、`GITLAB_REGISTRY_API_URL`の設定は`http://registry:5000`とコンテナ名でアクセスするようになっていましたが、この通りやるとサーバー証明書のチェックに失敗して接続ができなかったのでexternal_linksを使うようにしています。別の原因で接続できなかっただけかもしれないので、何か知っている人がいたら教えて欲しいです。

次は、DockerRegistryコンテナの設定追加です。

```docker-compose.yml（一部抜粋）
registry:
  image: registry:2.4.1
  ports:
  - "5000:5000"
  volumes:
  - registry-data:/var/lib/registry
  - /opt/docker/gitlab/certs:/certs
  environment:
  - REGISTRY_LOG_LEVEL=info
  - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry
  - REGISTRY_AUTH_TOKEN_REALM=http://gitlab.example.com/jwt/auth
  - REGISTRY_AUTH_TOKEN_SERVICE=container_registry
  - REGISTRY_AUTH_TOKEN_ISSUER=gitlab-issuer
  - REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/certs/gitlab.example.com-auth.crt
  - REGISTRY_STORAGE_DELETE_ENABLED=true
  - REGISTRY_HTTP_TLS_CERTIFICATE=/certs/gitlab.example.com-auth.crt
  - REGISTRY_HTTP_TLS_KEY=/certs/gitlab.example.com-auth.key
  - REGISTRY_HTTP_SECRET=secret
```

こちらもgitlabコンテナと同様にホスト上のサーバー証明書を参照するためvolumes設定しています。

これで、GitLabからDockerRegistryが利用できるようになります。GitLabのプロジェクトごとにRegistryを利用するかどうか設定ができますので、プロジェクトの`Settings`ページより`Container Registry`機能を有効にしてください。

Dockerイメージを登録できるようになったので、[次回](http://qiita.com/ogasada0/items/6ad8e4d263c34a19c3ca)はJenkinsJobで利用するコンテナの作成をします。

参考までにGitLabを動かすためのdocker-compose.ymlの全体も書いておきます（ホスト名やセキュリティに関するところはマスクしてます）。

```docker-compose.yml（全体）
version: '2'

services:
  gitlab-redis:
    image: sameersbn/redis:latest
    volumes:
    - /etc/localtime:/etc/localtime:ro
    networks:
      - proxy_network

  gitlab-postgresql:
    image: sameersbn/postgresql:9.5-1
    ports:
    - "15432:5432"
    environment:
    - DB_NAME=gitlabhq_production
    - DB_USER=xxxxxx
    - DB_PASS=xxxxxx
    - DB_EXTENSION=pg_trgm
    volumes:
    - /opt/docker/gitlab/postgresql/data:/var/lib/postgresql
    - /etc/localtime:/etc/localtime:ro
    networks:
      - proxy_network

  gitlab:
    image: sameersbn/gitlab:9.3.5
    depends_on:
    - gitlab-redis
    - gitlab-postgresql
    ports:
    - "10080:80"
    - "10022:22"
    volumes:
    - /opt/docker/gitlab/git:/home/git/data
    - /opt/docker/gitlab/logs:/var/log/gitlab
    - /opt/docker/gitlab/certs:/certs
    - /etc/localtime:/etc/localtime:ro
    external_links:
    - "registry:gitlab.example.com"
    environment:
    - DB_ADAPTER=postgresql
    - DB_HOST=gitlab-postgresql
    - DB_PORT=5432
    - DB_USER=xxxxxx
    - DB_PASS=xxxxxx
    - DB_NAME=gitlabhq_production
    - REDIS_HOST=gitlab-redis
    - REDIS_PORT=6379
    - GITLAB_TIMEZONE=Tokyo
    - GITLAB_PORT=10080
    - GITLAB_HOST=gitlab.example.com
    - GITLAB_RELATIVE_URL_ROOT=/gitlab
    - GITLAB_SHELL_SSH_PORT=10022
    - GITLAB_EMAIL=xxxx@xxxxxxx.com
    - GITLAB_EMAIL_DISPLAY_NAME=GitLab
    - GITLAB_BACKUP_SCHEDULE=daily
    - GITLAB_BACKUP_TIME=01:00
    - GITLAB_BACKUP_EXPIRY=86400
    - GITLAB_SECRETS_DB_KEY_BASE=xxxxxxxxxxxxxxxxxxxxxx
    - GITLAB_SECRETS_SECRET_KEY_BASE=xxxxxxxxxxxxxxxxxxxxxx
    - GITLAB_SECRETS_OTP_KEY_BASE=xxxxxxxxxxxxxxxxxxxxxx
    - GITLAB_REGISTRY_ENABLED=true
    - GITLAB_REGISTRY_HOST=gitlab.example.com
    - GITLAB_REGISTRY_PORT=5000
    - GITLAB_REGISTRY_API_URL=https://gitlab.example.com:5000
    - GITLAB_REGISTRY_CERT_PATH=/certs/gitlab.example.com-auth.crt
    - GITLAB_REGISTRY_KEY_PATH=/certs/gitlab.example.com-auth.key
    - SMTP_DOMAIN=xxxxxxxxxx
    - SMTP_HOST=xxxxxxxxxx
    - SMTP_PORT=25
    - SMTP_USER=xxxxxxxx
    - SMTP_PASS=xxxxxxxx
    - UNICORN_TIMEOUT=300
    networks:
      - proxy_network

  registry:
    image: registry:2.4.1
    ports:
    - "5000:5000"
    volumes:
    - registry-data:/var/lib/registry
    - /etc/localtime:/etc/localtime:ro
    - /opt/docker/gitlab/certs:/certs
    environment:
    - REGISTRY_LOG_LEVEL=info
    - REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY=/var/lib/registry
    - REGISTRY_AUTH_TOKEN_REALM=http://gitlab.example.com:10080/gitlab/jwt/auth
    - REGISTRY_AUTH_TOKEN_SERVICE=container_registry
    - REGISTRY_AUTH_TOKEN_ISSUER=gitlab-issuer
    - REGISTRY_AUTH_TOKEN_ROOTCERTBUNDLE=/certs/gitlab.example.com-auth.crt
    - REGISTRY_STORAGE_DELETE_ENABLED=true
    - REGISTRY_HTTP_TLS_CERTIFICATE=/certs/gitlab.example.com-auth.crt
    - REGISTRY_HTTP_TLS_KEY=/certs/gitlab.example.com-auth.key
    - REGISTRY_HTTP_SECRET=secret
    networks:
      - proxy_network

volumes:
  registry-data:

networks:
  proxy_network:
    external: true
```