Gitlab on Docker  をlocalのMacに構築して Gitlab pagesを見る方法

## はじめに

gitlabをいじいじして、CI環境を整えることになったので、そのときにはまったことを一通りメモっておく。
本当は、本番で稼働しているgitlabを飛ばすと大変なことになってしまうので、localにgitlabを立てて予行演習をしようと思っただけだったんですが、長い戦いだった。

誰か同じことでハマる人がいたら、参考にしてもらえると :muscle:

## 方針

最近流行りのInfra as a Codeということで、Gitlab on Docker on Macする。

## 使う物

- Macbook Pro
- Docker Toolbox
- http://www.damagehead.com/docker-gitlab/

## 手順

### 1. MacにDocker Toolboxを入れる

公式に従って入れてください

* `docker-machine start default`
* `docker run hello-world`

上記2つのコマンドが通って、「dockerの世界にこんにちは」できたら次へ

※最近だと、docker for Macが推奨されてるっぽい

### 2. Virtual VMのメモリを上げておく

Docker Toolboxで立ち上げたdefaultのdocker-machineは1GBのメモリしかなく、このままgitlabを立ち上げると頻繁に500が返ってくる不安定なサーバーになるので、以下を参考にVMのメモリを上げておく。（体験済み） [^1]
[^1]: https://github.com/sameersbn/docker-gitlab/issues/1595

[この記事を参照](https://qiita.com/niisan-tokyo/items/2d7d21aeb4e25f7a7bbe)
or
`docker-machine create -d virtualbox --virtualbox-memory 8192 default`

### 3. docker-composeする

有志がGitlab CEベースでdocker imageを作ってくれているので[これ](http://www.damagehead.com/docker-gitlab/)を利用する。 [^2]
[^2]: 「0から5秒以内に構築できるGitlab」という名前、最高

wgetしてきて、docker-composeして立ち上がったら次へ

### 4. アクセスする

Docker ToolboxだとDocker Container on VM by VirtualBox on Macになります
これでHostのVMにアクセスするには`localhost`ではなく、VMのアドレスである`192.168.99.100`にアクセスする必要があります。

デフォルトだと`http://192.168.99.100:10080`にアクセスすると見慣れたGitlabの画面に辿り着けます。以下で入れるので、入りましょう。

- username: root
- password: 5iveL!fe

### 5. Gitlabのデータを永続化する

4でせっかく立ち上がったGitlabのlocalサーバーですが、defaultのdocker-machineを落とすとデータが消えます。
https://serverfault.com/questions/722085/why-does-docker-machine-clear-data-on-restart

なので、[この記事を参考にして](https://qiita.com/damele0n/items/ac20e93749eb060fddfa)data-volumeをcreateして、そこに永続化したいデータをマウントするようにします。

`docker-machine restart default` して、Gitlabを再起動してもデータが残っていれば次へ

### 6. Gitlab CI runnerを立ち上げる

CI環境を作るぞということで、以下を参考に作る。

- https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#use-docker-in-docker-executor
- https://medium.com/@tonywooster/docker-in-docker-in-gitlab-runners-220caeb708ca

ただ、docker-compose.ymlの中にregister-runnerのサービスを記述すると、`docker-compose up`するたびにrunnerが登録されることになってしまいます。
そこで、以下のような手順でやることにしました。

1. あらかじめdata-volumeを作成
2. volumeにgitlab-runnerのデータを永続化
3. 初回だけ手作業でgitlab-runnerをregister

volumeの作成

```
docker volume create --name gitlab-runner-db
```

gitlab-runnerにdata-volumeにをマウントする形で立ち上げ

```
docker run -v gitlab-runner-db:/etc/gitlab-runner:Z --name gitlab-runner --restart always gitlab/gitlab-runner:alpine
```

gitlab-runnerに入る

```
docker exec -it gitlab-runner bash
```

registerする
```
gitlab-runner register
```

interactiveモードで立ち上がって、色々聞かれるので、wizardに従って、いい感じに答えていくとgitlab側に登録されて表示されます。

adminエリアでこんな感じに表示されたら次へ。

<img width="1245" alt="01.png" src="https://qiita-image-store.s3.amazonaws.com/0/125675/050226aa-e1d8-9ce4-6ce8-931a2c2c2a71.png">

### Gitlab pagesを作る

Gitlab CIでテストカバレッジレポートなんかを作成して、ウェブページとして公開できる夢の機能です。
pagesに生成物を置く過程は省略します。

docker-gitlabでgitlab pagesを使うには環境変数に以下を追加します。

```yml
...
  envrironment:
    - GITLAB_PAGES_ENABLED=true
    - GITLAB_PAGES_PORT=18080
    - GITLAB_PAGES_EXTERNAL_HTTP=:18080
...
```

これで、containerを再起動するとgitlab pagesが`192.168.99.100:18080`にてホストされているようになります。
ただ、gitlab pagesはデフォルトでこんな感じのvirtual hostを想定しています。[^3]

[^3]: https://gitlab.com/gitlab-org/gitlab-pages/tree/master

```
http://<group or username>.<GITLAB_PAGES_DOMAIN>/<project-name>
Ex. http://test.example.com/test-project
```

なので、`/etc/hosts/`に生成されるURLとIPの対応を直書きしておいて、見たいプロジェクトのURLへアクセスしましょう。

```
...
# gitlab test
192.168.99.100 test.example.com
...
```

`http://test.example.com:18080/test-project`にアクセスして、見たいものが見れたら完成です！


### 置物
不必要な設定が入りっぱなしなので、無駄に長いですが、ここまでの設定をすべて書いたやつです。

<details><summary>docker-compose.yml</summary><div>

```yml
version: '3'

volumes:
  redis-db:
    driver: local
  postgresql-db:
    driver: local
  gitlab-db:
    driver: local
  gitlab-runner-db:
    driver: local

services:
  redis:
    restart: always
    image: sameersbn/redis:latest
    container_name: redis
    command:
    - --loglevel warning
    volumes:
    - redis-db:/var/lib/redis:Z

  postgresql:
    restart: always
    image: sameersbn/postgresql:latest
    container_name: postgresql
    volumes:
    - postgresql-db:/var/lib/postgresql:Z
    environment:
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production
    - DB_EXTENSION=pg_trgm

  gitlab:
    restart: always
    image: sameersbn/gitlab:latest
    container_name: gitlab
    depends_on:
    - redis
    - postgresql
    ports:
      # gitlab http host port
    - "10080:80"
      # gitlab ssh host port
    - "10022:22"
      # gitlab pages port
    - "18080:18080"
    volumes:
    - gitlab-db:/home/git/data:Z
    environment:
    - DEBUG=false

    - DB_ADAPTER=postgresql
    - DB_HOST=postgresql
    - DB_PORT=5432
    - DB_USER=gitlab
    - DB_PASS=password
    - DB_NAME=gitlabhq_production

    - REDIS_HOST=redis
    - REDIS_PORT=6379

    - TZ=Asia/Kolkata
    - GITLAB_TIMEZONE=Kolkata

    - GITLAB_HTTPS=false
    - SSL_SELF_SIGNED=false

      # for gitlab pages settings
    - GITLAB_PAGES_ENABLED=true
    - GITLAB_PAGES_PORT=18080
    - GITLAB_PAGES_EXTERNAL_HTTP=:18080

      # for Mac OSX, docker container host is VM on virtualBox, so localhost has no effect
    - GITLAB_HOST=192.168.99.100
    - GITLAB_PORT=10080
    - GITLAB_SSH_PORT=10022
    - GITLAB_RELATIVE_URL_ROOT=
    - GITLAB_SECRETS_DB_KEY_BASE=long-and-random-alphanumeric-string
    - GITLAB_SECRETS_SECRET_KEY_BASE=long-and-random-alphanumeric-string
    - GITLAB_SECRETS_OTP_KEY_BASE=long-and-random-alphanumeric-string

    - GITLAB_ROOT_PASSWORD=
    - GITLAB_ROOT_EMAIL=

    - GITLAB_NOTIFY_ON_BROKEN_BUILDS=true
    - GITLAB_NOTIFY_PUSHER=false

    - GITLAB_EMAIL=notifications@example.com
    - GITLAB_EMAIL_REPLY_TO=noreply@example.com
    - GITLAB_INCOMING_EMAIL_ADDRESS=reply@example.com

    - GITLAB_BACKUP_SCHEDULE=daily
    - GITLAB_BACKUP_TIME=01:00

    - SMTP_ENABLED=false
    - SMTP_DOMAIN=www.example.com
    - SMTP_HOST=smtp.gmail.com
    - SMTP_PORT=587
    - SMTP_USER=mailer@example.com
    - SMTP_PASS=password
    - SMTP_STARTTLS=true
    - SMTP_AUTHENTICATION=login

    - IMAP_ENABLED=false
    - IMAP_HOST=imap.gmail.com
    - IMAP_PORT=993
    - IMAP_USER=mailer@example.com
    - IMAP_PASS=password
    - IMAP_SSL=true
    - IMAP_STARTTLS=false

    - OAUTH_ENABLED=false
    - OAUTH_AUTO_SIGN_IN_WITH_PROVIDER=
    - OAUTH_ALLOW_SSO=
    - OAUTH_BLOCK_AUTO_CREATED_USERS=true
    - OAUTH_AUTO_LINK_LDAP_USER=false
    - OAUTH_AUTO_LINK_SAML_USER=false
    - OAUTH_EXTERNAL_PROVIDERS=

    - OAUTH_CAS3_LABEL=cas3
    - OAUTH_CAS3_SERVER=
    - OAUTH_CAS3_DISABLE_SSL_VERIFICATION=false
    - OAUTH_CAS3_LOGIN_URL=/cas/login
    - OAUTH_CAS3_VALIDATE_URL=/cas/p3/serviceValidate
    - OAUTH_CAS3_LOGOUT_URL=/cas/logout

    - OAUTH_GOOGLE_API_KEY=
    - OAUTH_GOOGLE_APP_SECRET=
    - OAUTH_GOOGLE_RESTRICT_DOMAIN=

    - OAUTH_FACEBOOK_API_KEY=
    - OAUTH_FACEBOOK_APP_SECRET=

    - OAUTH_TWITTER_API_KEY=
    - OAUTH_TWITTER_APP_SECRET=

    - OAUTH_GITHUB_API_KEY=
    - OAUTH_GITHUB_APP_SECRET=
    - OAUTH_GITHUB_URL=
    - OAUTH_GITHUB_VERIFY_SSL=

    - OAUTH_GITLAB_API_KEY=
    - OAUTH_GITLAB_APP_SECRET=

    - OAUTH_BITBUCKET_API_KEY=
    - OAUTH_BITBUCKET_APP_SECRET=

    - OAUTH_SAML_ASSERTION_CONSUMER_SERVICE_URL=
    - OAUTH_SAML_IDP_CERT_FINGERPRINT=
    - OAUTH_SAML_IDP_SSO_TARGET_URL=
    - OAUTH_SAML_ISSUER=
    - OAUTH_SAML_LABEL="Our SAML Provider"
    - OAUTH_SAML_NAME_IDENTIFIER_FORMAT=urn:oasis:names:tc:SAML:2.0:nameid-format:transient
    - OAUTH_SAML_GROUPS_ATTRIBUTE=
    - OAUTH_SAML_EXTERNAL_GROUPS=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_EMAIL=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_NAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_FIRST_NAME=
    - OAUTH_SAML_ATTRIBUTE_STATEMENTS_LAST_NAME=

    - OAUTH_CROWD_SERVER_URL=
    - OAUTH_CROWD_APP_NAME=
    - OAUTH_CROWD_APP_PASSWORD=

    - OAUTH_AUTH0_CLIENT_ID=
    - OAUTH_AUTH0_CLIENT_SECRET=
    - OAUTH_AUTH0_DOMAIN=

    - OAUTH_AZURE_API_KEY=
    - OAUTH_AZURE_API_SECRET=
    - OAUTH_AZURE_TENANT_ID=

  dind:
    restart: always
    container_name: dind
    privileged: true
    volumes:
    - /var/lib/docker
    image: docker:stable-dind
    command:
    - --storage-driver=overlay2
  
  gitlab-runner:
    restart: always
    image: gitlab/gitlab-runner:alpine
    container_name: gitlab-runner
    volumes:
    - gitlab-runner-db:/etc/gitlab-runner:Z
    environment:
    - DOCKER_HOST=tcp://dind:2375
```
</div></details>


## 雑感
めっちゃハマったんですが、調べてみると実はDocker for Macではなく、Docker Toolboxを使っていたせいなのでは？という気持ちになりました。
あとDockerはいいぞ。