DockerでGitlabを動かしてみるまで


# Dockerでgitlabを動かすに至った経緯

事の発端は、最新のgitlabを使いたいと言われた事ですが、弊社で現在利用しているバージョンは、9.2.5です。

毎回、バージョンアップ用のshell書いて、公式サイトからgit cloneして、ruby関連をgem updateかけたり、bundle installしたりとやる事てんこ盛りで年一回のイベント騒ぎになっていました。

今回も9.2.5からバージョンを上げようと思っているのですが、DBのマイグレーションとかutf8mb4対応とか面倒だなぁって正直思ってました。

そこで言われたのが、「dockerで動かしてみたら？」でした。
どっちが楽かはさておき、とりあえずやってみることになりましたので、内容をちょこっと書き残そうと思います。

## Dockerfileを書く上で困ったこと

DockerやるならDockerfileを書くのですが、最初に困ったのはgit cloneして公式レポジトリから持ってくるか、yum installでインストールしてしまうか、のどちらを選択するかでした。
正直、git cloneはしたくない、と思ったので、yum installを選択したわけですが、どっちもどっちでどっちとも面倒だったっていうのがぼくの感想です。

git cloneする場合は必要なrubygemを用意したり、EC2インスタンス内で稼働してるMySQLをRDSのPostgresqlに置き換える必要があります。
redisはまあいいとして、他にもworkhorseだのgitalyだのなんだの引っ張ってくるものがあって、「うっわ、絶対こっちの方がめんどくさそう」という気持ちでいっぱいでした。

yum installする側はあっさりしたもので、必要なライブラリをインストールし、公式レポジトリを読み込むようにし、yum install gitlab-ce(yum install gitlab-ee)で完了してしまうのでした。
「gitlab-ce(gitlab-ee) reconfigureだけで終わるとか超楽じゃん…」って思ったのはいいのですが、設定ファイルが1000行ごえで「これヤベーな…」となりました。
でも、よくよく眺めていると、gitlab-ce(gitlab-ee)の方が楽で、gitlab.rbを抽出し、gitlab.rbの要らないコメントは全部消してしまえば良いのです。
後々困るんじゃないかって一瞬思ったのですが、最新のgitlab.rbをdiffすれば簡単なので、それほど困らない、という結論に達しました。
しかも、reconfigureするだけでredis、postgresql、workhorseなど必要なものが全部起動してくれます。
何もしなくて良い。


## Dockerfileを実際に書いてみた結果

Dockerfileを実際に書いてみたのですが、動かない、どこでreconfigureするか、が悩みのタネでした。

結果的に以下のような感じで書けばうまく動きました。
他にいい方法があるかもしれませんが、将来的にECSで動かす予定なので、この程度でいいかなーと思ってます。

以下が作成したDockerfileです。

```Dockerfile
# AMI Base
#
# 20180306
#   Amazon Linux
FROM amazonlinux
MAINTAINER systech

ARG env_external_url="http://localhost"
ARG env_gitlab_ssh_host="localhost"
ARG env_pages_external_url="http://localhost"

RUN yum update -y && yum upgrade -y && yum install -y epel-release && \
    yum clean all

RUN yum install -y vi vim wget git which curl gettext && \
    curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.rpm.sh | bash && \
    yum clean all

RUN yum install -y gitlab-ce && \
    yum clean all

COPY ./gitlab.rb /etc/gitlab/gitlab.rb
RUN sed -i -e "s|env_external_url|$env_external_url|g" /etc/gitlab/gitlab.rb && \
    sed -i -e "s|env_gitlab_ssh_host|$env_gitlab_ssh_host|g" /etc/gitlab/gitlab.rb && \
    sed -i -e "s|env_pages_external_url|$env_pages_external_url|g" /etc/gitlab/gitlab.rb

RUN echo '/opt/gitlab/embedded/bin/runsvdir-start &' >> /etc/rc.local && \
    echo '/opt/gitlab/bin/gitlab-ctl reconfigure' >> /etc/rc.local

ENTRYPOINT /sbin/init
```

gitlab.rbを必要最低限抜き出した場合はこうなりました。

```ruby
external_url 'env_external_url'
gitlab_rails['gitlab_ssh_host'] = 'env_gitlab_ssh_host'
gitlab_rails['gitlab_email_from'] = 'gitlab@env_gitlab_ssh_host'
gitlab_rails['gitlab_email_reply_to'] = 'noreply@env_gitlab_ssh_host'
pages_external_url "env_pages_external_url"
```


いくつかポイントがあるので、以下で詳細に書いていきます。
あ、そうそう。
gitlab.rb内にrootのパスワードを書く場所があるので書いておくと毎回パスワードを求められずに済みます

```ruby
# gitlab_rails['initial_root_password'] = "5iveL!fe"
```

### まずreconfigureを起動時に実行させたかった

DockerはECSに持ってくる上で、未reconfigure状態ですので、どこかで実行する必要がありました。
一番良いのは起動時に実行してくれることだよなーと思ってはいたのですが、RUNにやらせるべきかENTRYPOINTにやらせるべきかは悩みました。
結果的に選んだのは、RUNでrc.localに任せるという方法です。

```Dockerfile
RUN echo '/opt/gitlab/embedded/bin/runsvdir-start &' >> /etc/rc.local && \
    echo '/opt/gitlab/bin/gitlab-ctl reconfigure' >> /etc/rc.local
```

runsvdir-startはredisを構築する時に実行している必要があるらしく、runsvdir-startが止まっているとreconfigureも途中で止まります。
（途中で止まったメッセージでググるとみんな苦労してるようでした。）

### 次にホスト名の問題が出てきた

ホスト名はARGでやるかENVでやるか悩んでました。
ENVで「envsubst(yum install gettextがあるのはそのため)を使えばテンプレートエンジン風に使えるよ！」ってみんなが書いてるので、その通り試したらそもそもテンプレートエンジンとして動作しないどころか、envsubstで吐き出した内容が空っぽでした。（ ~~ファッキュー~~ ）

結論は、ARGに任せる、でした。
「ホスト名が頻繁に変わるようなサービスがあったら困るのですが、ホスト名ってそもそもビルドしたら変えることってなくね？」っていう話だと思ってます。
なので、ローカルビルド用のshellとデプロイ用のshellとそもそも指定しなかった時の挙動を想定して作りました。

```Dockerfile
ARG env_external_url="http://localhost"
ARG env_gitlab_ssh_host="localhost"
ARG env_pages_external_url="http://localhost"
```

以下がローカル用のshell。

```shell
#!/bin/sh
docker build --build-arg env_external_url=http://0.0.0.0 --build-arg env_gitlab_ssh_host=0.0.0.0 --build-arg env_pages_external_url=http://0.0.0.0/  -t gitlab .
```

以下がデプロイ用のshell。

```shell
#!/bin/sh
docker build --build-arg env_external_url=http://git.example.com --build-arg env_gitlab_ssh_host=git.example.com --build-arg env_pages_external_url=http://pages.example.com/  -t gitlab .
```

### その他（記載されていない部分）

弊社では、gitlabからgit cloneするときは10022ポートを使ってます。
10022ポートが変わると色々なプロジェクトに支障が出てきますので、どうしたものかなーと悩んだのですが、そもそもsshdもインストールされるので、sshd_configだけ置いてやりました。
しかも、既存の設定をごっそりそのまま放り込む形で。
サーバ側で保持する鍵とかも変更があると、やはり支障が出るので、鍵もごっそり持ってきてきました。ぐへへ。

# 残タスクやまとめ

既存のEBSをマウントすることと、既存のMysqlデータを事前にPostgresqlに移行する作業が残ってます。
Postgresqlに移行するツールが提供されているようですが、正直これもまた悩みそうだなぁと思ってます。
Dockerfileとは別に作っておかないと、みんな業務で日々git pushやmerge、commentを書いていくと思います。
そうなると、Dockerfileに任せるのは無理くさいなって思ってますので、こいつだけは別になるわけです。

EBSをマウントする方法はECSに任せておけば良いので、多分意識する必要はないはずです。
ただし、事前にマウントしてから起動してくるように仕込む必要はありますが…。
マウントタイミングってどうなってんのかなぁ…。

まとめとしては、Dockerは簡単にLAMP環境が作れるだの、良いだの言われてますが、そこまで良いか？と若干思わなくもないです。
毎回、どう書くか悩まされますし、いろんな人の書き方を見てると、これで良いのか？って悩むときもありますし、この記事も来年になったら古くなり、使えない記事になっていることでしょう。（またそのときは記事化することをお約束したいと思います。）

とりあえず、これでgitlabを皆さんも動かせると思いますので、ぜひ試してフィードバックいただければと思います。

***お粗末！***

![gitlab.png](https://qiita-image-store.s3.amazonaws.com/0/13837/ae0a1b12-f5e9-3744-cb53-628f5d43efc6.png "gitlab.png")