Docker Compose を使って自分好みの Redmine 実行環境を作ってみた

タイトルのとおりです。

前半部にやりたかったことと結果をまとめます。
後半部に、結果にいたるまでの試行錯誤っぷりをダラダラと書き並べていきます。

# やりたかったこと

* 最新バージョンの Redmine を動かしてみたい（執筆時の最新バージョンは 4.1.0）
* 素の Linux 上に Ruby のインストールから始めるのは面倒なので Docker でサクッと済ませたい
* データベースは PostgreSQL が使いたい（これは単なる個人的な好み）
* プラグインやテーマもまとめて入れたい
   * 特に [redmine_full_text_search](https://github.com/clear-code/redmine_full_text_search) （[Groonga](https://groonga.org/ja/) が必要） と [redmine_dmsf](https://github.com/clear-code/redmine_full_text_search) （様々なパッケージが必要）をなんとかしたい
* あまり手数をかけて作りたくない（Docker 等の作法に多少反してても、そこは目をつぶりたい…）

# 結果

ファイル一式を [GitHub](https://github.com/juno-nishizaki/myfav-redmine) で公開しています。ディレクトリ構成や細かい内容はそちらで確認してください。

以下の環境で起動と簡単な操作までを確認しました。

* OS: Ubuntu 18.04
* Docker: 19.03.8
* Docker Compose: 1.25.4

これから使い込んで動作に問題ないか確認しようとしています。


## 全体のざっくりとした説明

* Redmine と PostgreSQL を Dcoker Compose でひとまとめに構築
* Redmine は公式の Passenger 版イメージを使用
    * configuration.yml やプラグイン、テーマは Dockerfile で追加
* PostgreSQL は公式イメージをベースに [PGroonga](https://pgroonga.github.io/ja/) を追加でインストール
* リバースプロキシサーバーやリマインダー通知は含めていない

## 個別ファイルの説明

### docker-compose.yml

```yml:docker-compose,yml
version: "3.7"

services:

  redmine:
    build: ./redmine
    container_name: myfav-redmine
    restart: always
    depends_on:
      - db
    ports:
      - "3000:3000"
    environment:
      TZ: Asia/Tokyo
      REDMINE_DB_POSTGRES: db
      REDMINE_DB_DATABASE: redminedb
      REDMINE_DB_USERNAME: redmineuser
      REDMINE_DB_PASSWORD: redminepassword
      REDMINE_PLUGINS_MIGRATE: "true"
    volumes:
      - "/srv/redmine/files:/usr/src/redmine/files:z"
      - "/var/log/redmine:/usr/src/redmine/log:z"

  db:
    build: ./db
    container_name: myfav-redmine-db
    restart: always
    environment:
      TZ: Asia/Tokyo
      POSTGRES_DB: redminedb
      POSTGRES_USER: redmineuser
      POSTGRES_PASSWORD: redminepassword
    volumes:
      - "dbdata:/var/lib/postgresql/data"

volumes:
  dbdata:
```

* 必要に応じて Listen するポート、データベース名／ユーザー／パスワードを書き換えてください
* 添付ファイルとログはホスト側にバインドマウントしています（パスは変更してもよいです）
* プラグインの追加や更新を考慮して、起動時に `redmine:plugins:migrate` を実行するようにしています
* Dockerfile を変更したときは、起動前に `docker-compose build` の実行が必要です

### Redmine の Dockerfile

```Dockerfile:redmine/Dockerfile
FROM redmine:4.1-passenger

COPY config/configuration.yml config

RUN set -eux; \
        \
        apt-get update && apt-get install -y --no-install-recommends \
                antiword \
                catdoc \
                catdvi \
                djview \
                djview3 \
                gcc \
                gzip \
                libemail-outlook-message-perl \
                libwpd-tools \
                libwps-tools \
                libxapian-dev \
                make \
                poppler-utils \
                ruby-xapian \
                uuid \
                uuid-dev \
                unrtf \
                unzip \
                xapian-omega \
                xpdf \
                xz-utils \
        ; \
        \
# install plugins
        gosu redmine git clone --depth 1 https://github.com/akiko-pusu/redmine_banner.git plugins/redmine_banner; \
        gosu redmine git clone --depth 1 https://github.com/akiko-pusu/redmine_issue_badge.git plugins/redmine_issue_badge; \
        gosu redmine git clone --depth 1 https://github.com/akiko-pusu/redmine_issue_templates.git  plugins/redmine_issue_templates; \ 
        gosu redmine git clone --depth 1 https://github.com/clear-code/redmine_full_text_search.git plugins/full_text_search; \        
        gosu redmine git clone --depth 1 https://github.com/danmunn/redmine_dmsf.git plugins/redmine_dmsf; \
        gosu redmine git clone --depth 1 https://github.com/jbbarth/redmine_base_deface.git plugins/redmine_base_deface; \
        gosu redmine git clone --depth 1 https://github.com/jbbarth/redmine_drafts.git plugins/redmine_drafts; \
        gosu redmine git clone --depth 1 https://github.com/onozaty/redmine-view-customize.git plugins/view_customize; \
        \
# install themes
        gosu redmine git clone -b redmine4.1 --depth 1 https://github.com/farend/redmine_theme_farend_bleuclair.git public/themes/bleuclair; \
        \
# install gems
        gosu redmine bundle install;
```

* ホスト側の `config/configuration.yml` に、メールサーバーなどの設定を記述します
* redmine_dmsf の実行に必要な OS 側のパッケージを apt-get でインストールしています
* プラグイン、テーマは必要に応じて追加、変更してください
    * `bundle install` で Gem のビルド等に失敗するときは、apt-get の行に必要なパッケージを追加してください

### PostgreSQL の Dockerfile

```Dockerfile:db/Dockerfile
FROM postgres:12

RUN set -eux; \
        \
        apt-get update && apt-get install -y --no-install-recommends \
                ca-certificates \
                wget \
        ; \
        \
        mkdir pgroonga-work; \
        cd pgroonga-work; \
        \
        wget https://packages.groonga.org/debian/groonga-archive-keyring-latest-buster.deb; \
        apt-get install -y ./groonga-archive-keyring-latest-buster.deb; \
        apt-get update && apt-get install -y --no-install-recommends \
                groonga-tokenizer-mecab \
                postgresql-12-pgroonga \
        ; \
        \
        cd ..; \
        rm -rf pgroonga-work;
```

* PostgreSQL 12 に PGroonga を追加インストールしています
* redmine_full_text_search の実行には [TokenMecab](https://groonga.org/ja/docs/reference/tokenizers/token_mecab.html) も必要なため追加でインストールしています

# 結果に至るまで

正直なところ、全然わからん…の連続でした。Docker で Redmine を動かすのは [前記事](https://qiita.com/juno-nishizaki/items/3a73cf3b6d8217bf707f) 以来のことで、その当時は素の Redmine を動かした程度の経験しかなかったです。

以下、心の声を含めて試行錯誤の過程をダラダラと書き並べていきます。

* Passenger 版の Redmine ってどういう構成なんや… つーか、Passenger って Apache とかに組み込んで動かすんとちゃうの？
   * [Passenger はスタンドアロンでも動く](https://www.phusionpassenger.com/docs/tutorials/what_is_passenger/) らしいです… そのことがわかってなかったので [Dockerfile](https://github.com/docker-library/redmine/blob/fe32a0b56f5eacae086030de5e0ca19ea026b51b/4.1/passenger/Dockerfile) 読んでても全然しっくりきませんでした
* configuration.yml ってどうやってコンテナ側に置けばええねん…
   * せや、手元に Dockerfile 作って COPY したれ！
   * それやったらついでにプラグインやテーマも Dockerfile に書けばええやんけ！ 
      * この気づきがあったので、その後が楽になったと思っています。最初はプラグインやテーマのディレクトリをホスト側にバインドマウントしてましたが、コンテナ内に閉じ込めておいた方が OS 側パッケージの追加インストールも含めて管理しやすいです。
* PGroonga ってどうやって入れたらええんや…
   * Groonga 公式の [Dockerfile](https://github.com/pgroonga/docker/blob/2.2.5-alpine-12-slim/alpine/12-slim/Dockerfile) があるやんけ！ これ使うたろ！
      * TokenMecab が入ってなくてダメでした…（ベースが Alpine やから入れ方わからん…）
   * おとなしく PostgreSQL 公式のイメージに追加インストールするか… でも、本体の Dockerfile 見てると apt-get で入れたパッケージをビルドが終わったら巻き戻したりしてるし、こういうこと必要なんかな…
      * わからんからそのままにしといたれ…
* これで Redmine 側の apt-get もどうにかなるな…でも、追加したファイルのオーナーってどうやって書き換えるんやろ
   * 本体に [gosu](https://github.com/tianon/gosu) ってのが入ってる… 詳細はわからんけど便利そうやからそのまま使うたれ！（Golang で書かれたユーティリティツールのようです）

まあ、なんというか…くぅ～疲れましたw 

# おわりに

Docker Compose を使って簡単に好みの Redmine 環境が作れるようになりました。これで色んな実験がしやすくなったかな、と感じています。

きっと、プラグイン開発なども捗るんじゃなかろうか…と。先生の次回作にご期待ください…（涙）