Docker でオフィシャルな GitLab イメージと Redmine イメージのコンテナを連携させる

## はじめに

### 2017.5.1 追記: Deprecated

よりよい方法を見つけたので当記事の内容を非推奨にします。改定箇所が多かったので、[(改訂版) Docker でオフィシャルな GitLab イメージと Redmine イメージのコンテナを連携させる](http://qiita.com/nkenbou/items/e512b4aea9de40da606a) として新しく記事を書きました。参考にされる場合はそちらをご覧ください。

### 対象となる読者

* [オフィシャルな GitLab イメージ](https://hub.docker.com/r/gitlab/gitlab-ce/) を使いたい人
* [オフィシャルな Redmine イメージ](https://hub.docker.com/_/redmine/) を使いたい人
* 上記のイメージから作成したコンテナを連携させたい人

### この記事を読んだ後できるようになること

* GitLab の Issues タブが Redmine のプロジェクトにリンクされます。
* GitLab のコミットメッセージ内の issue 番号が Redmine チケットにリンクされます。
* Redmine のチケット連携機能がそのまま使えます。

### この記事を書いたときのバージョン

* GitLab イメージ: gitlab/gitlab-ce: 8.15.4-ce.1
* Redmine イメージ: redmine:3.3.2
* PostgreSQL イメージ: postgres:9.6.1 ※Redmine 用

### ソースコード (docker-compose.yml、Dockerfile など)

今回作った GitLab & Redmine 連携の Docker コンテナ用ソースコードは GitHub に置いてあります。

https://github.com/nkenbou/gitlab-redmine

## 連携可能なコンテナを作成するためのハック & 設定

docker、docker-compose のコマンドの使い方や、Dockerfile、docker-compose.yml の書き方などの説明は省略します。

### GitLab コンテナ上の git リポジトリを Redmine コンテナから参照できるようにする

Redmine のリポジトリ設定で GitLab コンテナ上のリポジトリのパスを指定する必要があります。そのために、GitLab のデータボリュームを Redmine でマウントしますが、オリジナルの GitLab イメージだとそのディレクトリはオーナーしかアクセスできない権限になっています。

また、コンテナにログインして手動でオーナー変更&権限変更しても、コンテナの再起動時などに Chef が実行されて設定が元に戻ってしまいます。

```sh
$ cd /var/opt/gitlab
$ ls -l
...
drwx------ 3 git          root        4096 Jan 17 23:13 git-data
...
$ ls -al git-data/
...
drwxrws---  5 git  root  4096 Jan 20 21:18 repositories
...
```

```sh
$ cat /opt/gitlab/embedded/cookbooks/gitlab/attributes/default.rb
...
default['gitlab']['user']['username'] = "git"
default['gitlab']['user']['group'] = "git"
default['gitlab']['user']['uid'] = nil
default['gitlab']['user']['gid'] = nil
...
default['gitlab']['gitlab-shell']['git_data_directories'] = {
  "default" => "/var/opt/gitlab/git-data"
}
default['gitlab']['gitlab-rails']['repositories_storages'] = {
  "default" => "/var/opt/gitlab/git-data/repositories"
}
...
```

```sh
$ cat /opt/gitlab/embedded/cookbooks/gitlab/recipes/gitlab-shell.rb
...
git_data_directories = node['gitlab']['gitlab-shell']['git_data_directories']
repositories_storages = node['gitlab']['gitlab-rails']['repositories_storages']
...
git_data_directories.each do |_name, git_data_directory|
  storage_directory git_data_directory do
    owner git_user
    mode "0700"
  end
end

repositories_storages.each do |_name, repositories_storage|
  storage_directory repositories_storage do
    owner git_user
    mode "2770"
  end
end
...
```

そこで、オリジナルの GitLab イメージを継承して、オーナーと権限を設定している処理を上書きして `git` グループに権限を付与します。

**gitlab-ce/Dockerfile** (抜粋)

```Dockerfile
RUN sed -i -e '/storage_directory git_data_directory do/,/end/ s/mode "[0-9]\+"/mode "0750"/ ' /opt/gitlab/embedded/cookbooks/gitlab/recipes/gitlab-shell.rb

RUN sed -i -e '/storage_directory git_data_directory do$/a \ \ \ \ group git_group' /opt/gitlab/embedded/cookbooks/gitlab/recipes/gitlab-shell.rb

RUN sed -i -e '/storage_directory repositories_storage do$/a \ \ \ \ group git_group' /opt/gitlab/embedded/cookbooks/gitlab/recipes/gitlab-shell.rb
```

さらに、ディレクトリオーナー (`git`) の uid と gid を明示的に指定します。

**docker-compose\.yml** (抜粋)

```yaml
...
services:
  gitlab:
    ...
    environment:
      GITLAB_OMNIBUS_CONFIG: |
        external_url 'http://localhost'
        user['uid'] = 998
        user['gid'] = 998
...
```

そして、Redmine のほうもイメージを継承して、`git` ユーザー、`git` グループを作成し、`redmine` ユーザーを `git` グループに追加します。

**redmine/Dockerfile**

```dockerfile
RUN groupadd -g 998 git && useradd -u 998 -g git git && gpasswd -a redmine git
```

これで、GitLab コンテナ上の git リポジトリを Redmine コンテナから参照できるようになりました。

## GitLab と Redmine を連携させてできるようになること

当記事で取り扱っているのは私自身が実際に試した機能だけです。ここに書いたこと以外にも便利な機能があるかもしれません。

* GitLab の **Issues** タブが Redmine のプロジェクトにリンクされます。
* GitLab の **New issue** メニューが Redmine の新規チケット作成ページにリンクされます。
* Git のコミットメッセージに `refs #123` など (チケット番号だと判定させるためのキーワード (`refs` など) は変更できます。後述。) と書くと、GitLab のコミットログから Redmine の `#123` チケットへのリンクが作成されるようになります。
* Git のコミットメッセージから、Redmine チケットの各種ステータス (作業時間など) を操作することができるようになります。

当記事では GitLab、Redmine とも `test` をプロジェクト名として説明します。

## Redmine 側の設定

Redmine のプロジェクトと連携させるために Redmine 側にも準備が必要です。

### Redmine ユーザーの設定

Redmine の **ログインID** と各ユーザーの開発マシンの git 設定 `user.name` は合わせておくとよいです。

開発マシンの `user.name` を設定する方法です。

```sh
$ git config --global user.name "nkenbou"
```

もし、別々にしたい場合は次のページで、ログから検出された git ユーザーと Redmine ユーザーを関連付けることができます。

![redmine-repository-user.png](https://qiita-image-store.s3.amazonaws.com/0/85728/e5db39d7-a565-f664-2476-dab26eeaf407.png)



### リポジトリ (管理) の設定

![redmine-admin-repository.png](https://qiita-image-store.s3.amazonaws.com/0/85728/8cb6e120-b80b-c79b-3ae8-5193ea43286b.png)

**設定のポイント:**

* **コミットを自動取得する**: on
* **リポジトリ管理用のWebサービスを有効にする**: on
* **APIキー**: **キーの生成** リンクから設定
* **参照用キーワード**: チケット番号だと判定させるためのキーワードの設定です。`*` を追加するとキーワードが不要になります (例. `#123`)。
* **異なるプロジェクトのチケットの参照/修正を許可**: on
* **コミット時に作業時間を記録する**: on
* **作業時間の作業分類**: 適宜

### リポジトリ (プロジェクト) の設定

![redmine-project-repository.png](https://qiita-image-store.s3.amazonaws.com/0/85728/b2ec626f-dbb9-29c9-b5bf-fe506e31d288.png)

**設定のポイント:**

* **バージョン管理システム**: Git
* **リポジトリのパス**: /var/opt/gitlab/git-data/repositories/*XXX*/*YYY*.git
    * *XXX*: GitLab でのプロジェクトネームスペース
    * *YYY*: GitLab でのプロジェクト名
* その他の設定は適宜

### その他、Redmine で最低限必要な設定項目

* チケットのステータス
* トラッカー
* ワークフロー
* 列挙項目
    * チケットの優先度
    * 作業分類 (時間管理)

## GitLab 側の設定

### Redmine サービス (テンプレート) の設定

Admin 権限でログインし、**Service Templates** > **Redmine** と選択していき Redmine サービスのテンプレートを設定するページを開きます。

![gitlab-service-template-redmine.png](https://qiita-image-store.s3.amazonaws.com/0/85728/e68b3dd5-69e9-0074-dee1-261e230fd35b.png)

**設定のポイント:**

* **Active**: on
* **Trigger**: on
* URL の`localhost:10081` の部分は環境に合わせて適切に置き換えてください。
* **Project url** 、 **New issue url** の `:project_id` の部分は (自動的に置き換えられそうですが) 個々のプロジェクトで Redmine サービスの設定をする際に手動で置き換えることになります。
* **Issues url** の `:id` は連携時に自動的に置き換わります。

### Redmine サービス (プロジェクト) を設定

Redmine と連携したいプロジェクトで **Services** > **Redmine** と選択していき Redmine サービスを設定するページを開きます。

![gitlab-service-redmine.png](https://qiita-image-store.s3.amazonaws.com/0/85728/968e623d-2e11-63ae-7e69-5190523c6ac7.png)


**設定のポイント:**

* **Project url** 、 **New issue url** の `:project_id` 部分を Redmine 側のプロジェクト名 (例. `test`) に置き換えます。

### Webhooks の設定

Redmine と連携したいプロジェクトの **Webhooks** メニューから Webhooks の設定ページを開きます。

![gitlab-webhooks.png](https://qiita-image-store.s3.amazonaws.com/0/85728/879d3b4f-0580-5ebb-340c-1361db99510b.png)

**設定のポイント:**

* **URL**:
    * ホスト名 (例. `redmine`) はコンテナ同士を参照するために Docker 内で自動生成されるものを使用してください。docker-compose.yml を使用している場合はサービス名です。
    * ポート: redmine コンテナ側のポート (例. `3000`) を指定してください。
    * key=: Redmine のリポジトリ設定の **APIキー** (例. `bP6pRCyiDsjPIHMNQAQf`) を指定してください。

## 動作確認

これで、設定は完了です。

Redmine のチケット連携機能だけ動作確認を載せておきます。

### コミット (作業時間の記録)

例. `#1` チケットに作業時間 2h30m で登録するようにコミット。

```sh
$ cd /path/to/test
$ echo "#GitLab & Redmine" > README.md
$ git add README.md
$ git commit -m "#1 @2h30m add title"
$ git push
```

![redmine-set-worktime.png](https://qiita-image-store.s3.amazonaws.com/0/85728/92a3a5c2-0ca3-79f5-f46b-ce60e85740cd.png)

コミットメッセージによる作業時間の記録については次のサイトが詳しいです。

http://blog.redmine.jp/articles/new-feature-1_1/automatic-spent-time-logging/

## まとめ

この記事の方法だとバージョンアップ時に動作しなくなる可能性がありますが、たいしたハックはしていないのでその都度対応もできそうです。
だけど、現時点では [sameersbn/docker-gitlab](https://github.com/sameersbn/docker-gitlab) と [sameersbn/docker-redmine](https://github.com/sameersbn/docker-redmine) を使ったほうが楽かな。

そこそこ調べたのですが、オフィシャルな GitLab と Redmine の Docker コンテナを連携させる正当なやり方は見つけられませんでした。ご存じの方がいらっしゃいましたらコメントなどいただけるとうれしいです。

### 参考文献

* [Redmine Service - GitLab Documentation](https://docs.gitlab.com/ce/project_services/redmine.html)
* [Redmine 1.1 新機能紹介: コミットメッセージによる作業時間の記録 | Redmine.JP Blog](http://blog.redmine.jp/articles/new-feature-1_1/automatic-spent-time-logging/)
* [SE奮闘記: RedmineとGitLabの連携。PushでチケットのStatusを変更](http://blog.dksg.jp/2015/05/redminegitlabpushstatus.html)