GitLabとGitLab Runnerをdocker-composeで手軽に構築する

# はじめに
最近GitLabをコンテナで構築することがあったので、備忘がてら手順を書いてみます。

# 環境
- Amazon Linux2
- Windows10(SSH用)
- WSL

# 作業内容
## EC2構築
コンソールからEC2を起動します。OSはAmazon Linux2の最新を選択します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/79c79456-bf41-1722-0bdd-d1b5a429a203.png)

インスタンスタイプは少し大きめのt3a.largeを選択します。
これより小さいインスタンスタイプを設定するとインストールが止まったりしたのでこのタイプにしました。
それなりに金額がかかりますので、作成される方はご注意ください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/1d8538d8-0c9d-5b1b-c6b1-745d2c91f450.png)

ボリュームはデフォルトの8GBだと少し足りないので、30GBぐらいで設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/c69436e5-c865-5137-f30e-6fe7a9fbc137.png)

セキュリティグループはSSHとHTTPの2つを設定します。(接続場所の関係でHTTPが2つ入ってます)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/7970029d-0139-a212-5b76-4dde22eb0c46.png)

起動したらEC2の準備OKです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/083ab55e-697c-26f1-11da-02b33ea5f76c.png)

## Dockerインストール
コンソールから起動したEC2を選択し、接続を押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/985c7cc9-1834-1d65-0769-f8575235460c.png)

インスタンスに接続するためのコマンドがあるので、一番下のsshのコマンドをコピーしておきます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/1c40eee8-b424-7b17-77ce-0ae019214063.png)

ローカルPCでwslを起動して、keypairファイルの格納しているフォルダに移動して、sshコマンドを実行します。

```
$ sudo ssh -i "keypair.pem" ec2-user@ec2-XXX-XXX-XXX-XXX.ap-northeast-1.compute.amazonaws.com
[sudo] password for user:
The authenticity of host 'ec2-XXX-XXX-XXX-XXX.ap-northeast-1.compute.amazonaws.com (XXX.XXX.XXX.XXX)' can't be established.
ECDSA key fingerprint is SHA256:FRJ1YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY0CjM.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'ec2-XXX-XXX-XXX-XXX.ap-northeast-1.compute.amazonaws.com,XXX.XXX.XXX.XXX' (ECDSA) to the list of known hosts.

       __|  __|_  )
       _|  (     /   Amazon Linux 2 AMI
      ___|\___|___|

https://aws.amazon.com/amazon-linux-2/
6 package(s) needed for security, out of 14 available
Run "sudo yum update" to apply all updates.
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$
[ec2-user@ip-XXX-XXX-XXX-XXX ~]$ sudo su
[root@ip-XXX-XXX-XXX-XXX ec2-user]#
[root@ip-XXX-XXX-XXX-XXX ec2-user]#
```

[こちら](https://qiita.com/reoring/items/0d1f556064d363f0ccb8)を参考にdockerとdocker-composeをインストールします。
以下のコマンドを上から順に実行していきます。

```
$ sudo yum install -y docker
$ sudo systemctl start docker
$ sudo usermod -a -G docker ec2-user
$ sudo systemctl enable docker
$ sudo curl -L https://github.com/docker/compose/releases/download/1.28.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
$ sudo chmod +x /usr/local/bin/docker-compose
```

docker-composeはパスが通ってなかったので、.bash_profileの設定をしました。
/usr/local/bin/を追加しています。

```
$ cat ~/.bash_profile
# .bash_profile

# Get the aliases and functions
if [ -f ~/.bashrc ]; then
        . ~/.bashrc
fi

# User specific environment and startup programs

PATH=$PATH:$HOME/bin:/usr/local/bin/

export PATH
```

コマンドが実行できるようになりました。

```
$ docker-compose
Define and run multi-container applications with Docker.

Usage:
  docker-compose [-f <arg>...] [--profile <name>...] [options] [--] [COMMAND] [ARGS...]
  docker-compose -h|--help

Options:
  -f, --file FILE             Specify an alternate compose file
                              (default: docker-compose.yml)
  -p, --project-name NAME     Specify an alternate project name
                              (default: directory name)
  --profile NAME              Specify a profile to enable
  -c, --context NAME          Specify a context name
  --verbose                   Show more output
  --log-level LEVEL           Set log level (DEBUG, INFO, WARNING, ERROR, CRITICAL)
  --ansi (never|always|auto)  Control when to print ANSI control characters
  --no-ansi                   Do not print ANSI control characters (DEPRECATED)
  -v, --version               Print version and exit
  -H, --host HOST             Daemon socket to connect to
~略~
```

## docker-compose実行
ec2-userディレクトリの直下にdocker-compose.ymlファイルを作成します。

```
$ cat docker-compose.yml
version: '3'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    restart: always
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - /home/ec2-user/gitlab/config:/etc/gitlab
      - /home/ec2-user/gitlab/logs:/var/log/gitlab
      - /home/ec2-user/gitlab/data:/var/opt/gitlab
```

以下のコマンドを実行してgitlab用のフォルダを作成しておきます。

```
$ mkdir -p /home/ec2-user/gitlab/config
$ mkdir -p /home/ec2-user/gitlab/logs
$ mkdir -p /home/ec2-user/gitlab/data
```

あとはdocker-compose.ymlファイルがあるディレクトリで以下のコマンドを実行します。
Pullに少し時間がかかりますが、これでGitLabがコンテナで起動しました。

```
$ docker-compose up -d
Creating network "ec2-user_default" with the default driver
Pulling gitlab (gitlab/gitlab-ce:latest)...
latest: Pulling from gitlab/gitlab-ce
7b1a6ab2e44d: Pull complete
c7b5535218a5: Pull complete
79f508cd75d4: Pull complete
9e411f19e622: Pull complete
4f9a74402cd4: Pull complete
b97274644821: Pull complete
270a6f9ec466: Pull complete
b3e10c449911: Pull complete
Digest: sha256:0f30e7000956cf3fe15ceefbdb8e57d6cd01e397028771244f4ddc77a1372c80
Status: Downloaded newer image for gitlab/gitlab-ce:latest
Creating ec2-user_gitlab_1 ... done
```

以下のコマンドでコンテナが起動していることを確認します。ここでCONTAINER IDをメモしておきます。

```
$ docker ps
CONTAINER ID   IMAGE                     COMMAND             CREATED          STATUS                             PORTS                                                                              NAMES
ead287afcc8f   gitlab/gitlab-ce:latest   "/assets/wrapper"   44 seconds ago   Up 37 seconds (health: starting)   0.0.0.0:80->80/tcp, :::80->80/tcp, 22/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   ec2-user_gitlab_1
```

## GitLabログイン
ここまでできたらEC2のグローバルIPでGitLabに接続できるので、早速確認...といきたいところですが、その前にrootユーザの初期パスワードを確認しておく必要があります。
rootユーザの初期パスワードはGitLabコンテナの「/etc/gitlab/initial_root_password」に記載されているので、以下のコマンドでファイルの中身を確認してみます。

```
$ docker exec -it ead287afcc8f cat /etc/gitlab/initial_root_password
# WARNING: This value is valid only in the following conditions
#          1. If provided manually (either via `GITLAB_ROOT_PASSWORD` environment variable or via `gitlab_rails['initial_root_password']` setting in `gitlab.rb`, it was provided before database was seeded for the first time (usually, the first reconfigure run).
#          2. Password hasn't been changed manually, either via UI or via command line.
#
#          If the password shown here doesn't work, you must reset the admin password following https://docs.gitlab.com/ee/security/reset_user_password.html#reset-your-root-password.

Password: UaPgof9ToHCIFTc9aym6JjGQGB6qqyQFQVcJ2Ao6ftI=

# NOTE: This file will be automatically deleted in the first reconfigure run after 24 hours.
```

今回の例だと「Password: UaPgof9ToHCIFTc9aym6JjGQGB6qqyQFQVcJ2Ao6ftI=」の部分がパスワードにあたります。

パスワードがわかったところでブラウザから「 http://<EC2のパブリックIP>/ 」にアクセスして、ログイン画面を開きます。
ログイン画面ではrootと先ほどのパスワードを入力して、Sign inを押下します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/d8b79efb-c43f-6318-fa8a-c7e294120817.png)

問題なくGitLabにログインすることができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/42e457c7-51f5-3438-c40a-8d0ca7ccb7bd.png)

## GitLab Runner構築
ここまでできたら、次はGitLabのCICDで利用されるGitLab Runnerのコンテナ作ってみます。
最初に作成したdocker-compose.ymlファイルに以下の内容でgitlab-runnerを追加します。

```
$ cat docker-compose.yml
version: '3'

services:
  gitlab:
    image: gitlab/gitlab-ce:latest
    restart: always
    ports:
      - "443:443"
      - "80:80"
    volumes:
      - /home/ec2-user/gitlab/config:/etc/gitlab
      - /home/ec2-user/gitlab/logs:/var/log/gitlab
      - /home/ec2-user/gitlab/data:/var/opt/gitlab
  gitlab-runner:
    image: gitlab/gitlab-runner:latest
    restart: always
    volumes:
      - /home/ec2-user/gitlab-runner/config:/etc/gitlab-runner
      - /var/run/docker.sock:/var/run/docker.sock
```

例のごとく必要なフォルダを事前に作成しておきます。

```
$ mkdir -p /home/ec2-user/gitlab-runner/config
```

docker-composeコマンドを実行して、Runnerを起動します。

```
$ docker-compose up -d
Pulling gitlab-runner (gitlab/gitlab-runner:latest)...
latest: Pulling from gitlab/gitlab-runner
7b1a6ab2e44d: Already exists
25e144866312: Pull complete
01efcda22c81: Pull complete
079259b86897: Pull complete
9c1c93bb1b17: Pull complete
d9463bd8b03f: Pull complete
Digest: sha256:09b86155c323660f27a1c7ceb3899df4cfe60860d5a9a191057363292ce2d1af
Status: Downloaded newer image for gitlab/gitlab-runner:latest
ec2-user_gitlab_1 is up-to-date
Creating ec2-user_gitlab-runner_1 ... done
```

docker psでRunnerが起動されていることを確認します。

```
$ docker ps
CONTAINER ID   IMAGE                         COMMAND                  CREATED          STATUS                    PORTS                                                                              NAMES
7cec5fc6a81c   gitlab/gitlab-runner:latest   "/usr/bin/dumb-init …"   34 seconds ago   Up 31 seconds
                                                                      ec2-user_gitlab-runner_1
ead287afcc8f   gitlab/gitlab-ce:latest       "/assets/wrapper"        19 minutes ago   Up 19 minutes (healthy)   0.0.0.0:80->80/tcp, :::80->80/tcp, 22/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   ec2-user_gitlab_1
```

Runnerが起動したら以下のコマンドを実行してGitLabのリポジトリにRunnerを登録します。
※GitLabに事前にリポジトリを作成しておく必要があります
※「Enter the registration token」については後述

```
$ docker run --rm -t -i -v /home/ec2-user/gitlab-runner/config:/etc/gitlab-runner \
> --name gitlab-runner-tmp gitlab/gitlab-runner register
Runtime platform                                    arch=amd64 os=linux pid=7 revision=e91107dd version=14.5.2
Running in system-mode.

Enter the GitLab instance URL (for example, https://gitlab.com/):
http://10.10.149.44
Enter the registration token:
XXXXXXXXXXXXXXXXXXX
Enter a description for the runner:
[0d7a963169c9]: "GitLab Runner"
Enter tags for the runner (comma-separated):
test-runner
Registering runner... succeeded                     runner=cgdeSzvu
Enter an executor: custom, docker-ssh, ssh, docker+machine, docker, parallels, shell, virtualbox, docker-ssh+machine, kubernetes:
docker
Enter the default Docker image (for example, ruby:2.6):
docker:18.09.7
Runner registered successfully. Feel free to start it, but if it's running already the config should be automatically reloaded!
```

Runner登録時に「Enter the registration token」を入力する必要がありますが、これはGitLabのSettingsから確認することができます。
GitLabの以下の場所に記載されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/bfe4c310-990b-85ee-acf7-79a3dec15a7e.png)

登録されるとTokenと同じ場所に以下のように表示されます。
あとは.gitlab-ci.ymlファイルにtagsでタグ名(この例だと"test-runner")を指定してあげれば、CICDを動かすことができるようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/440403/1b966cd4-a12e-c126-9347-e01bacbdb18d.png)

最後にRunner環境でdocker in dockerを動かすために以下のように設定を変更しておきます。
- clone_url = "http://10.10.1.167" ※追加
- privileged = true　※trueに変更

```
$ docker ps 
CONTAINER ID   IMAGE                         COMMAND                  CREATED          STATUS                    PORTS                                                                              NAMES
c15a8dacc603   gitlab/gitlab-runner:latest   "/usr/bin/dumb-init …"   16 minutes ago   Up 16 minutes
                                                                      ec2-user_gitlab-runner_1
1d323c008851   gitlab/gitlab-ce:latest       "/assets/wrapper"        22 minutes ago   Up 14 minutes (healthy)   0.0.0.0:80->80/tcp, :::80->80/tcp, 22/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp   ec2-user_gitlab_1

$ docker cp c15a8dacc603:/etc/gitlab-runner/config.toml ./config.toml
$ vi config.toml
$ docker cp ./config.toml c15a8dacc603:/etc/gitlab-runner/config.toml
$ docker exec -it c15a8dacc603 cat /etc/gitlab-runner/config.toml
concurrent = 1
check_interval = 0

[session_server]
  session_timeout = 1800

[[runners]]
  name = "\"GitLab Runner\""
  url = "http://10.10.1.167"
  clone_url = "http://10.10.1.167"
  token = "JowTaMwJSyQkjexz7kG8"
  executor = "docker"
  [runners.custom_build_dir]
  [runners.cache]
    [runners.cache.s3]
    [runners.cache.gcs]
    [runners.cache.azure]
  [runners.docker]
$ docker restart c15a8dacc603
c15a8dacc603
```

これでRunnerでdocker in dockerが使えるようになりました。

# おわりに
GitLabをyum installするところからスタートしたので、ここまで来るのにだいぶ時間がかかりました。
情報はあるけど意外にまとまっていないので、毎回ハマって大変でした。

これからGitLabを構築される方の参考になれば幸いです。