オンプレGitLabをdockerで動かすときの備忘録

オンプレGitLabの設定をいつもググりながら頑張っているのでさすがにメモっとこうということで記事に。

# 環境
```shell-session:環境
vagrant@server:~$ uname -a
Linux server 5.15.0-67-generic #74-Ubuntu SMP Wed Feb 22 14:14:39 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
vagrant@server:~$ cat /etc/lsb-release 
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=22.04
DISTRIB_CODENAME=jammy
DISTRIB_DESCRIPTION="Ubuntu 22.04.2 LTS"
```

# Dockerのインストール
ここがわかりやすい

https://zenn.dev/shimakaze_soft/articles/02aebaedeb43b6

# GitLabのコンテナ起動
dockerhubにあるのでそれを使う。

https://hub.docker.com/r/gitlab/gitlab-ee/

ちなみにGitLabには
+ CE(Community Edition)
+ EE(Enterprise Edition)

があるが、EEはCEをベースに作られており、ライセンスを購入せずにEEを使うと実質CEを使ってる状態と同じになる。
なので特別な理由が無ければGitLab EEを指定するのがベター。らしい。

https://www.gitlab.jp/install/ce-or-ee/

## docker-compose.yml
```yml:docker-compose.yml
 version: "3"
 services:
     gitlab:
         image: gitlab/gitlab-ee:latest
         volumes:
             - ./gitlab/config:/etc/gitlab
             - ./gitlab/logs:/var/log/gitlab
             - ./gitlab/data:/var/opt/gitlab
             - /mnt/docker/gitlab:/mnt/backup
             - /var/run/docker.sock:/var/run/docker.sock
         ports:
             - '443:443'
             - '22:22'
         shm_size: '2gb'
         restart: always
         privileged: true
         environment:
             - TZ=Asia/Tokyo
```
+ volumesに `- /var/run/docker.sock:/var/run/docker.sock` を指定することでdocker内部でもホストのdockerが使用できる。
これでdood(Docker outside of Docker)を使ってCI/CDを走らせることができる。

https://qiita.com/t_katsumura/items/d5be6afadd6ec6545a9d

+ dockerコマンドを使う都合上 `privileged: true` を指定しているが、本当はあんまりよろしくない……

https://www.trendmicro.com/ja_jp/research/20/a/why-it-is-dangerous-to-run-Docker-containers-in-privileged-mode.html

+ この例では `./gitlab` にボリュームを充ててるので、もしカレントディレクトリにこのディレクトリが無ければ `mkdir gitlab` しておく

そして、以下のコマンドで起動
```shell-session
vagrant@server:~$ docker compose up -d
```

# コンテナの調整
まずは中に入る
```shell-session
vagrant@server:~$ docker compose exec gitlab bash
```
## 初期設定
```shell-session
root@1234abcd:/$ apt update
root@1234abcd:/$ apt upgrade -y
root@1234abcd:/$ apt install -y vim

# 必要ならホストに戻り設定ファイルをコピーする
root@1234abcd:/$ exit
vagrant@server:~$ docker compose cp ~/.vimrc gitlab:/root/
```

## GitLabの設定
色々設定があるので全部説明するのは厳しい。が、一応自分が設定しているものだけ抜粋
```shell-session:場所
root@1234abcd:/$ vim /etc/gitlab/gitlab.rb
```
| 設定 | 解説 |
|:-----|:-----|
|external_url 'https://your.gitlab-url.com'|外から見えるURL|
|gitlab_rails['time_zone'] = 'Asia/Tokyo'|タイムゾーンの設定|
|gitlab_rails['backup_path'] = "/mnt/backup/data"|バックアップ先の設定。<br/>`gitlab:backup:create`実行時ここに保存される|
|nginx['enable'] = true<br/>nginx['redirect_http_to_https'] = true<br/>nginx['ssl_certificate'] = "/etc/letsencrypt/live/your.gitlab-url.com/fullchain.pem"<br/>nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/your.gitlab-url.com/privkey.pem"<br/>nginx['listen_addresses'] = ['0.0.0.0', '[::]']<br/>nginx['listen_port'] = 443<br/>nginx['custom_gitlab_server_config'] = "location ^~ /.well-known { alias /etc/letsencrypt; }"<br/>nginx['worker_processes'] = 2<br/>letsencrypt['enable'] = false|httpsの設定<br/>`redirect_http_to_https`をtrueにして強制https化している|

## サーバー証明書の取得（https化）
```shell-session
root@1234abcd:/$ apt install -y certbot
root@1234abcd:/$ certbot certonly --standalone -d your.gitlab-url.com
```
もし80番や443番ポートが開いていないなどの理由でエラーが出るなら、手動で設定する方法もある。
```shell
root@1234abcd:/$ certbot certonly --manual --server https://acme-v02.api.letsencrypt.org/directory --preferred-challenges dns -d your.gitlab-url.com

...
# ここで利用規約の同意やメールの登録などが聞かれるので適宜進める
...
Please deploy a DNS TXT record under the name:
_acme-challenge.your.gitlab-url.com.
with the following value:
dummypeR4_Tz9VUGmdwRBH3iEh_xgBc
# ここで使っているDNSのTXTレコードにvalueを設定
# 登録が終わったらEnter
... 
root@1234abcd:/$ 
```
使っているサービスがCloudflareの場合、DNS設定のレコードにTXTを追加し、
+ 名前：_acme-challenge.your.gitlab-url.com
+ コンテンツ（必須）：dummypeR4_Tz9VUGmdwRBH3iEh_xgBc

を追加。これで証明書が貰える。

## 設定の反映
```shell-session
root@1234abcd:/$ gitlab-ctl reconfigure
```

## CI/CD設定
### GitLab Runner
GitLab Runnerの入れ方は公式にあるのでその通りにやる

https://docs.gitlab.com/runner/install/linux-repository.html

```shell-session
root@1234abcd:/$ curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | bash
root@1234abcd:/$ apt install -y gitlab-runner
```
あとは `gitlab-runner register` を用いて適宜Runnerを登録する

### Docker
コンテナ内で以下のコマンドを実行するだけで使えるようになる。便利。
```shell-session
root@1234abcd:/$ curl -sSL https://get.docker.com/ | sh
```
実行中にエラーが出る場合は、上記のコマンドを何回か試してみると上手くいく。

## バックアップジョブ
これが一番分かりやすい

https://pig-log.com/gitlab-backup-restore/

<br/>
保存したいのは/etc/gitlabの中にあるコンフィグとGitLabが持つデータ。なので自分は以下のようにしている。

```shell
root@1234abcd:/$ vim gitlab_backupjobs.sh
---
#!/bin/sh

BKDIR=/mnt/backup

# Config
tar cfz ${BKDIR}/config/$(date "+%s_%Y_%m_%d_etc_gitlab.tar.gz") -C /etc gitlab

# Data
/opt/gitlab/bin/gitlab-rake gitlab:backup:create

# Delete backups older than a week ago
find ${BKDIR}/config -mtime +6 | xargs rm -rf
find ${BKDIR}/data -mtime +6 | xargs rm -rf
---:wq!

root@1234abcd:/$ chmod +x gitlab_backupjobs.sh
```

これをホストのcrontabで定期実行。
```shell
vagrant@server:~$ docker compose ps
NAME                IMAGE                     COMMAND             SERVICE             CREATED             STATUS                 PORTS
docker-gitlab-1     gitlab/gitlab-ee:latest   "/assets/wrapper"   gitlab              3 hours ago         Up 3 hours (healthy)   80/tcp, 443/tcp, 0.0.0.0:443->443/tcp, :::80->80/tcp, 0.0.0.0:22->22/tcp, :::22->22/tcp

vagrant@server:~$ sudo crontab -l
# Edit this file to introduce tasks to be run by cron.
# 
# Each task to run has to be defined through a single line
# indicating with different fields when the task will be run
# and what command to run for the task
# 
# To define the time you can provide concrete values for
# minute (m), hour (h), day of month (dom), month (mon),
# and day of week (dow) or use '*' in these fields (for 'any').
# 
# Notice that tasks will be started based on the cron's system
# daemon's notion of time and timezones.
# 
# Output of the crontab jobs (including errors) is sent through
# email to the user the crontab file belongs to (unless redirected).
# 
# For example, you can run a backup of all your user accounts
# at 5 a.m every week with:
# 0 5 * * 1 tar -zcf /var/backups/home.tgz /home/
# 
# For more information see the manual pages of crontab(5) and cron(8)
# 
# m h  dom mon dow   command
0 5 * * * /usr/bin/docker exec -t docker-gitlab-1 /root/gitlab_backupjobs.sh CRON=1
```
上記の設定では毎日午前5時にバックアップジョブが実行される。
~~再起動したばっかりだからまだ３時間しか起動してないね~~

# リストア
基本手順は、
+ DB停止
+ リストア
+ リスタート

```shell-session
# コンテナ内で行う
root@1234abcd:/$ gitlab-ctl stop puma
root@1234abcd:/$ gitlab-ctl stop sidekiq
root@1234abcd:/$ gitlab-rake gitlab:backup:restore BACKUP=<バックアップ番号_年_月_日>
root@1234abcd:/$ gitlab-ctl restart
```

# 最後に
手作業に慣れ過ぎていつの間にか1時間掛からないくらいで再構築出来る様になった。
でもこれ絶対いくつか自動化できる。いつかやる。