GitLab Runnerでprivate repositoryにpushする準備～EHW2018「環境整備⑨」

# 概要

このエントリは、「Enterprise "hello, world" 2018 Advent Calendar 2018」の12/23向けのものです。このAdvent Calendarでは、複数個のエントリにまたがる話の流れも鑑みつつ、なるべく1エントリで1つのトピックをカバーできるようにする予定です。

このエントリで記載するトピックは、GitLab Runnerでprivate repositoryにpushすることです。
下図のような環境で、GitLabにpushしたコードからGitLab runnerが起動され、GitLab RunnerがDocker in Dockerのデーモンを使ってテストとビルドを実行し、結果として出来上がったコンテナをprivate registryにpushするまでを扱います。

![EHW2018DevEnv_day23.png](https://qiita-image-store.s3.amazonaws.com/0/65002/0694ac62-82d8-6005-1292-20cff541e86a.png)


# 前提

## おことわり

- このEnterpfise "hello, world"シリーズは、ネタのためのエントリです。実環境でそのまま利用ことを目的とはしていません。
- 動かしやすさを優先してセキュリティを意図的に低くする設定など入れてありますのでご注意ください。

## 想定読者

「Enterprise "hello, world" 2018」的なネタとしては、下記のような状況を想定しています。

> GitLab runnerでテスト実行まではできているので、次はコンテナ化が必要だ

## 関係するエントリ

以下が特に関係します。
- [CI/CDのためにGitLab RunnerをDockerで動かす準備～EHW2018「環境整備⑧」 ](https://qiita.com/hrkt/items/111bada83225a1864c9b)

## ぼやき

エントリ執筆時点で、EHW2018のシリーズで用意している環境においては、GitLab runnerの機能で「service」を利用してDocker-in-Dockerを実現する際、なかなかうまくいかない部分がありました(なんとなく、[こちら](https://gitlab.com/gitlab-org/gitlab-runner/issues/2302)と似たような状況。。などを含み、他との絡みもあり)。この部分はあきらめて、docker-composeでrunnerの外側にdindを用意しています。

# 動かすまで

## GitLab runnerの準備

GitLab runnerは、どのジョブを実行するかについて「タグ」を付与しておくことができます。[以前のエントリ](https://qiita.com/hrkt/items/111bada83225a1864c9b)では、タグとして「test」だけを使っていましたが、今回の目的のため「container」も増やしておきます（下図）。

![Screenshot_2019-01-15_04-33-28.png](https://qiita-image-store.s3.amazonaws.com/0/65002/6682e4b9-5172-e6ca-60b9-125c224bbe07.png)

（参考）
タグで適切なものが見つからないと、GitLab runnerのジョブがスタックします（下図)
![Screenshot_2019-01-15_04-27-29.png](https://qiita-image-store.s3.amazonaws.com/0/65002/edc8d458-f59d-a5a2-c9d9-32b07cd04600.png)
。

## Docker in Docker用のサービスを上げる

Docker in Docker(DinD)は、Docker内でDockerを動かすための仕組みです。[公式サイトの説明](https://hub.docker.com/_/docker/)
今回のシリーズでこの構成にした理由は、ホスト側の環境とCI用の環境を別にしたかったためです。GitLab RunnerのジョブからDockerを使用する際、ホスト側のDockerを使ってしまうとビルド時のゴミがホスト側にも見えてしまってわかりにくくなってしまうため、CIで使うものはすべてこのDinD環境で実行するようにしています。

docker-compose.ymlに以下を追加します。

補足：privileged: trueにすると、コンテナがホスト側の資源に触れるものが増えてしまっていろいろ危険である面があり悩ましいところですが、今回は目をつぶっています。

```yml
  dind:
    image: docker:dind
    networks:
      - extnet
    privileged: true
    links:
      - samba
      - registry
```

## CIのパイプラインにジョブを増やす

[以前のエントリ](https://qiita.com/hrkt/items/111bada83225a1864c9b)で作ったものに対して、下図のように、stagesにジョブを2つ追加します。

以下が、ちょっとしたポイントです。

- Dockerのプライベートレジストリは、[dockerのプライベートレジストリに作ったコンテナを格納する～EHW2018「MVPをコンテナ化③」](https://qiita.com/hrkt/items/5fbafbcfc9172c8a380e)で作ったものです。DockerホストのネットワークアダプタのIP上にポートを指定しています。Rancherで、別ホストのk8s環境に対してデプロイをするときにも使いたいためです。
- GitLab runnerのvariablesとして、「DOCKER_HOST」を指定しています。

```
image: node:8-alpine

variables:
    DOCKER_HOST: tcp://dind.ehw2018.local:2375/
    DOCKER_DRIVER: overlay2

before_script:
    - ifconfig -a
    - cat /etc/hosts
    - apk update
    - apk add docker
    - docker info

stages:
    - test
    - containerize
    - ship 

exec_test:
    stage: test
    tags:
        - test
    script:
        - npm install
        - npm run test

containerize:
    stage: containerize
    tags:
        - container
    script:
        - docker build -t front-test .

ship:
    stage: ship
    tags:
        - container
    script:
        - docker tag front-test 10.0.2.15:5443/front-test:latest
        - docker push 10.0.2.15:5443/front-test:latest
```


## Registryにpushする準備

これまでの手順だけでは、DinDからPrivate Registryにpushしようとしたときに証明書のエラーが出てしまいます。

お使いの環境（ホスト名やIPアドレス）に合わせ、Private Registryの証明書をDinDのコンテナにも格納しておきます。

パスは、下記です。
```
/etc/docker/certs.d/{Private Registryのアドレス}:{ポート}/ca.crt
```

## 実行

ここまでの手順を踏むことで、GitLabのmasterブランチにコードをプッシュすると、3つのジョブが実行されるようになります。

![Screenshot_2019-01-15_07-29-22.png](https://qiita-image-store.s3.amazonaws.com/0/65002/24308360-9789-878b-a7bf-4548d2c4d5d5.png)

1. testジョブは、以前のエントリの通りの動作です。
2. containerizeジョブは、以前のエントリのDockerfileを使ってビルドしています。
3. shipジョブは、出来上がったコンテナをPrivate Registryにpushしています。



# まとめ

このエントリでは、「Enterprise "hello, world" 2018 Advent Calendar 2018」(EHW2018)の23日目として、GitLab Runnerでprivate repositoryにpushすることをトピックとして取り上げました。

EHW2018のネタとしては、pushしたイメージを使って環境にデプロイすることを考えています。