Redmine を Docker 公式イメージで運用する

【追記】Redmine 4.x は別記事「[最新の Redmine 4 を Docker 公式イメージで運用する - Qiita](https://qiita.com/bezeklik/items/b9d75ee74e0ae4c6d42c)」で再検証したのでそちらを参照のこと。

## Redmine on Docker
Docker で Redmine を[とりあえず動かす](https://qiita.com/bezeklik/items/d3c82926da104ef0c5a3)ことは以前に試したが、運用上の考慮ができていなかったので、改めて諸々検討、検証してみた。

Redmine の Docker イメージは [Sameer Naik (sameersbn)](https://hub.docker.com/u/sameersbn/) による [sameersbn/redmine](https://hub.docker.com/r/sameersbn/redmine/) が著名でこのイメージを使った紹介記事が多いが、何をやっているか把握できていないのも困るので、この記事では全て公式イメージを使ってセットアップを行う。

既存の Redmine を Docker に移設した記事「[bitnami でインストールした Redmine を Docker に移設した - Qiita](https://qiita.com/bezeklik/items/1840fdd7aef84cd979c7)」も参考にどうぞ。

### 本稿の特徴
本稿によるセットアップの主な特徴は以下の通り。

- Docker 公式イメージのみを使用
- ホストOSから全て操作
- データベースは MySQL 5.7 を採用
- 文字コードは `utf8mb4` （照合順序は `utf8mb4_bin`）
- themes, plugins, files はホストOSにマウント
- Memcached の導入
- コマンドラインから一括設定
- テーマ、プラグインを一括インストール
- systemd の Timer による自動バックアップ
- バージョンアップ手順
- SSL 対応 (TODO)

## Docker のインストール
```bash
yum -y install epel-release && yum -y update && yum -y install yum-{axelget,plugin-rpm-warm-cache,utils} && \
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \
yum -y install docker-ce && systemctl start docker && systemctl enable $_ && \
curl -L $(curl -s https://api.github.com/repos/docker/compose/releases/latest | grep 'Linux-x86_64"' | grep url | cut -d'"' -f4) -o /usr/local/bin/docker-compose && chmod +x $_
```
CentOS 7.4.1708 上に Docker と Docker Compose をインストールする。

標準の Extras リポジトリの `docker` パッケージでは 1.12 が、 `docker-latest` パッケージでは 1.13 がインストールされる。
また EPEL リポジトリの `docker-compose` パッケージでは 1.9.0 がインストールされる。

## 格納ディレクトリの作成
```bash
mkdir -p /var/www/redmine && cd $_ && \
semanage fcontext -a -t container_file_t "$_(/.*)?" && \
restorecon -Rv /var/www/redmine
```
### 格納ディレクトリ
添付ファイル、テーマ、プラグイン、ログの保存ディレクトリのマウント先として `/var/www/redmine` を作成。

[FHS](http://refspecs.linuxfoundation.org/fhs.shtml) を考慮すると`/srv/redmine` や `/srv/docker/redmine` の方がいいのか迷い中。意見求む。

https://bugzilla.redhat.com/show_bug.cgi?id=1525921

7.5 から `svirt_sandbox_file_t` を指定すると `ValueError: 形式 svirt_sandbox_file_t が無効です。ファイルまたはデバイス形式である必要があります` と怒られるので `container_file_t` を使う。

### semanage, restorecon
SELinux が有効なままコンテナ側からアクセスできるようコンテキストを変更。

`semanage` コマンドが含まれる `policycoreutils-python` パッケージは `docker-ce` パッケージの依存関係でインストールされる。

## Docker Compose
```yaml
cat << "_EOF_" > docker-compose.yml && \
time docker-compose up -d && \
firewall-cmd --permanent --add-service=http{,s} && \
firewall-cmd --reload && \
sleep 20 && \
docker container logs --follow redmine
version: '3.5'
services:
  redmine:
    image: redmine:3-passenger
    container_name: redmine
    restart: always
    ports:
      - 80:3000
    environment:
      TZ: Asia/Tokyo
      REDMINE_DB_MYSQL: mysql
      REDMINE_DB_DATABASE: redmine
      REDMINE_DB_USERNAME: redmine
      REDMINE_DB_PASSWORD: redmine
      REDMINE_DB_ENCODING: utf8mb4
    depends_on:
      - mysql
      - memcached
    volumes:
      - /var/www/redmine/files:/usr/src/redmine/files
      - /var/www/redmine/log:/usr/src/redmine/log
      - /var/www/redmine/plugins:/usr/src/redmine/plugins
      - /var/www/redmine/public/themes:/usr/src/redmine/public/themes
  mysql:
    image: mysql:5.7
    container_name: mysql
    restart: always
    environment:
      TZ: Asia/Tokyo
      MYSQL_ROOT_PASSWORD: P@ssw0rd
      MYSQL_DATABASE: redmine
      MYSQL_USER: redmine
      MYSQL_PASSWORD: redmine
#    ports:
#      - 3306:3306
    volumes:
      - mysql-data:/var/lib/mysql
    command: mysqld --character-set-server=utf8mb4 --collation-server=utf8mb4_bin
  memcached:
    image: memcached
    container_name: memcached
    restart: always
#    ports:
#      - 11211:11211
volumes:
  mysql-data:
    name: mysql-redmine
_EOF_
```

### 解説

#### docker-compose
`docker-compose.yml` は Docker Compose で利用する設定ファイル。
`docker-compose up` は `docker-compose.yml` に基づいて各コンテナを起動するコマンド。`-d` オプションはデタッチモードの指定。

#### firewalld
ホスト OS 側からアクセスできるように、ホスト OS 側の 80, 443 ポートを `firewall-cmd` コマンドで開ける。

#### docker container logs
`docker container logs` はコンテナのログを出力するコマンド。旧コマンド体系の `docker logs` でも動作する。`--follow` または `-f` オプションはログファイルを追って更新（追記）されるたびに出力してくれる。

`depends_on:` で MySQL の起動を先にしても MySQL のセットアップが完了するまで待ってくれる訳ではないので、 Redmine 側は起動に失敗して何度も再起動を繰り返す。
そのため20秒程待った後に redmine コンテナのログ出力をフォローする。

`Completed 200 OK` が表示されたら完了なので <kbd>Ctrl</kbd> + <kbd>c</kbd> でログを抜ける。

`admin` `admin` でログイン。

#### Redmine 公式イメージ

Docker 公式イメージの redmine はタグに `passenger` を指定すると [Phusion Passenger](https://www.phusionpassenger.com/) を使用できる。指定しないと WEBrick が使用される。

#### container_name:

`container_name:` は任意にコンテナ名を指定できる。 `docker` コマンドで操作するときに楽になるので覚えやすく識別しやすい名称を付けると良い。 

#### environment:
`environment:` で環境変数 `TZ` に値を指定するとタイムゾーンを指定できる。

`REDMINE_DB_MYSQL` は紛らわしいがホスト名かIPアドレスを指定する。

#### depends_on:
`depends_on:` はコンテナの起動順序を指定できる。`links:` は `version: '2'` 以降は不要。 [^depends_on]

[^depends_on]: [docker-compose depends_onとlinksの違い - Qiita](https://qiita.com/sivertigo/items/9baa73d922a68788402b)

#### volumes:
`volumes:` でホストOS側のディレクトリをコンテナ側にマウントする。ここでは添付ファイル、ログ、プラグイン、テーマをマウントしている。
ホストOS側の public/themes ディレクトリを直接マウントするため、[デフォルトのテーマファイル群](https://github.com/redmine/redmine/tree/master/public/themes)は消失するので注意。

[^compose-docker-compatibility]: https://docs.docker.com/compose/compose-file/#compose-and-docker-compatibility-matrix


## 初期設定

### デフォルトデータのロード [^default-data-set]
```bash
docker exec redmine bundle exec rake redmine:load_default_data RAILS_ENV=production REDMINE_LANG=ja
```
[^default-data-set]: http://www.redmine.org/projects/redmine/wiki/redmineinstall#Step-7-Database-default-data-set

### データベースの認証情報の登録
```bash
docker exec -it mysql mysql_config_editor set --host=localhost  --user=redmine  --password
```
`mysql` および `mysqldump` コマンドで `--user` および `--password` オプションを省略するために
 `mysql_config_editor` コマンドを使って認証情報を暗号化して格納する。 [^password-security-user]

[^password-security-user]: [MySQL :: MySQL 5.6 リファレンスマニュアル :: 6.1.2.1 パスワードセキュリティーのためのエンドユーザーガイドライン](https://dev.mysql.com/doc/refman/5.6/ja/password-security-user.html)

### 設定
```sql
cat << '_EOQ_' | docker exec -i mysql mysql redmine && \
docker exec redmine passenger-config restart-app /usr/src/redmine
INSERT INTO `settings` (`name`, `value`) VALUES
('search_results_per_page','30'), -- ページごとの検索結果表示件数 (10)
('host_name','redmine.example.com'), -- ホスト名とパス (localhost:3000)
('protocol','https'), -- プロトコル (http)
('text_formatting','markdown'), -- テキスト書式 (textile)
('default_language','ja'), -- デフォルトの言語 (en)
('force_default_language_for_anonymous','1'), -- 匿名ユーザーにデフォルトの言語を強制 (0)
('force_default_language_for_loggedin','1'), -- ログインユーザーにデフォルトの言語を強制 (0)
('user_format','lastname_firstname'), -- ユーザー名の表示形式 (firstname_lastname)
('thumbnails_enabled','1'), -- 添付ファイルのサムネイル画像を表示 (0)
('login_required','1'), -- 認証が必要 (0)
('autologin','7'), -- 自動ログイン (0)
('max_additional_emails','0'), -- 追加メールアドレス数の上限 (5)
('session_lifetime','43200'), -- 有効期間の最大値 (0)
('session_timeout','480'), -- 無操作タイムアウト (0)
('default_users_time_zone','Tokyo'), -- タイムゾーン ()
('rest_api_enabled','1'), -- RESTによるWebサービスを有効にする (0)
('jsonp_enabled','1'), -- JSONPを有効にする (0)
('default_projects_public','0'), -- デフォルトで新しいプロジェクトは公開にする (1)
('default_projects_modules','---
- issue_tracking
- time_tracking
- wiki
- repository
- calendar
- gantt
'), -- 新規プロジェクトにおいてデフォルトで有効になるモジュールチケットトラッキング
('default_projects_tracker_ids','---
- \'1\'
- \'2\'
- \'3\'
'), -- 新規プロジェクトにおいてデフォルトで有効になるトラッカー
('cross_project_issue_relations','1'), -- 異なるプロジェクトのチケット間で関連の設定を許可 (0)
('default_issue_start_date_to_creation_date','0'), -- 現在の日付を新しいチケットの開始日とする (1)
('issue_done_ratio','issue_status'), -- 進捗率の算出方法 (issue_field)
('issue_list_default_totals','---
- estimated_hours
- spent_hours
'), -- チケットの一覧で表示する項目（合計）
('attachment_max_size','51200'), -- 添付ファイルサイズの上限 (5120)
('repositories_encodings','utf-8,cp932,euc-jp'), -- 添付ファイルとリポジトリのエンコーディング ()
('mail_from','admin@example.com'), -- 送信元メールアドレス (redmine@example.net)
('enabled_scm','---
- Subversion
- Git
'), -- 使用するバージョン管理システム
('commit_ref_keywords','refs,references,IssueID,*'), -- 参照用キーワード (refs,references,IssueID)
('commit_cross_project_ref','1'); -- 異なるプロジェクトのチケットの参照/修正を許可 (0)
_EOQ_
```
デフォルトでプロジェクトが公開される設定だったりと必須で変更したい点が複数あるため、コマンドラインで一括設定変更する。

### ロールと権限
```sql
cat << '_EOQ_' | docker exec -i mysql mysql redmine
UPDATE `roles` SET `permissions` = NULL WHERE `id` = '1' OR `id` = '2';
_EOQ_
```
「非メンバー」と「匿名ユーザー」の権限を全て剥奪。

## メール設定

### ホスト OS の Postfix を利用する場合
```yaml
cat << '_EOF_' | docker exec -i redmine bash -c "cat > /usr/src/redmine/config/configuration.yml" && \
docker exec redmine passenger-config restart-app /usr/src/redmine && \
sed -i /etc/postfix/main.cf \
 -e '/mynetworks = hash/a mynetworks = 127.0.0.0/8, 172.18.0.0/16' \
 -e '/^inet_interfaces/ s/localhost/localhost, 127.0.0.1, 172.18.0.1/' && \
systemctl restart postfix && \
firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="172.18.0.0/16" service name="smtp" accept' && \
firewall-cmd --reload
default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      address: 172.18.0.1
      port: 25
      domain: redmine.example.com
_EOF_
```
[Piping a file into docker run | CODE Q&A](https://code.i-harness.com/en/q/2208fd7)

### Gmail を利用する場合
```yaml
cat << '_EOF_' | docker exec -i redmine bash -c "cat > /usr/src/redmine/config/configuration.yml" && \
docker exec redmine passenger-config restart-app /usr/src/redmine
default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      enable_starttls_auto: true
      address: "smtp.gmail.com"
      port: 587
      domain: "smtp.gmail.com"
      authentication: :login
      user_name: "example@gmail.com"
      password: "P@ssw0rd"
_EOF_
```
http://redmine.jp/faq/general/mail_notification/

## Memcached の設定
```bash
docker exec redmine sh -c "echo 'config.cache_store = :mem_cache_store, \"memcached\"' > config/additional_environment.rb" && \
docker exec redmine sh -c "echo \"gem 'dalli'\" > Gemfile.local" && \
docker exec redmine bundle install && \
docker exec redmine passenger-config restart-app /usr/src/redmine
```
`config.cache_store` は直接 `:dalli_store` と記載する事例が多かったが、`:mem_cache_store` の方が汎用性が高いように見えるのでそちらを採用した。 [^mem_cache_store]
`gem 'dalli'` は Gemfile への追記が難しかったので Gemfile.local に記載した。より適切な方法があれば教えて欲しい。

[^mem_cache_store]: [:mem_cache_store vs. :dalli_store? · Issue #21595 · rails/rails](https://github.com/rails/rails/issues/21595)

### 動作確認
```bash
curl --verbose telnet://127.0.0.1:11211
```
```text:出力例
* About to connect() to 127.0.0.1 port 11211 (#0)
*   Trying 127.0.0.1...
* Connected to 127.0.0.1 (127.0.0.1) port 11211 (#0)
```
```bash
stats items
```
```text:出力例
STAT items:15:number 1
STAT items:15:number_hot 0
STAT items:15:number_warm 0
STAT items:15:number_cold 1
STAT items:15:age_hot 0
STAT items:15:age_warm 0
STAT items:15:age 4
STAT items:15:evicted 0
STAT items:15:evicted_nonzero 0
STAT items:15:evicted_time 0
STAT items:15:outofmemory 0
STAT items:15:tailrepairs 0
STAT items:15:reclaimed 0
STAT items:15:expired_unfetched 0
STAT items:15:evicted_unfetched 0
STAT items:15:evicted_active 0
STAT items:15:crawler_reclaimed 0
STAT items:15:crawler_items_checked 0
STAT items:15:lrutail_reflocked 0
STAT items:15:moves_to_cold 1
STAT items:15:moves_to_warm 0
STAT items:15:moves_within_lru 0
STAT items:15:direct_reclaims 0
STAT items:15:hits_to_hot 0
STAT items:15:hits_to_warm 0
STAT items:15:hits_to_cold 0
STAT items:15:hits_to_temp 0
END
```
```text
quit
```
telnet 接続で動作確認を行う場合は事前に docker-compose.yml で `11211` ポートを空けておくこと。

## SSL の設定
https://github.com/sameersbn/docker-redmine#ssl

## テーマの追加
```bash
yum -y install git unzip && \
themes=/var/www/redmine/public/themes && token=0c7a1fefdd47f3a96fb57a4f94450dbdf98dd && \
curl -L https://www.redmineup.com/license_manager/40766?token=${token} -o circle_theme.zip && unzip $_ -d ${themes}/ && \
curl -L https://www.redmineup.com/license_manager/40830?token=${token} -o a1_theme.zip && unzip $_ -d ${themes}/ && \
git clone --depth 1 https://github.com/akabekobeko/redmine-theme-minimalflat2 ${themes}/minimalflat2 && cd $_ && rm -fr * && git checkout origin/master -- src && mv src/* . && rmdir -p src && cd - && \
git clone --depth 1 https://github.com/themondays/Dwarf ${themes}/dwarf && cd $_ && rm -fr * && git checkout origin/master -- production/dwarf && mv production/dwarf/* . && rmdir -p production/dwarf && cd - && \
git clone --depth 1 https://github.com/tsi/redmine-theme-flat ${themes}/flat && \
git clone --depth 1 https://github.com/hardpixel/minelab ${themes}/minelab && \
git clone --depth 1 https://github.com/lqez/redmine-theme-basecamp-with-icon ${themes}/basecamp-with-icon && \
git clone --depth 1 https://github.com/makotokw/redmine-theme-gitmike ${themes}/gitmike && \
git clone --depth 1 https://github.com/farend/redmine_theme_farend_basic ${themes}/farend_basic && \
git clone --depth 1 https://github.com/farend/redmine_theme_farend_fancy ${themes}/farend_fancy && \
git clone --depth 1 https://github.com/Nitrino/flatly_light_redmine ${themes}/flatly_light && \
git clone --depth 1 https://github.com/mrliptontea/PurpleMine2 ${themes}/purplemine2 && \
git clone --depth 1 https://github.com/Froiden/fedmine ${themes}/fedmine && \
git clone --depth 1 https://github.com/vsc55/redmine-theme ${themes}/pixel-cookers && \
git clone --depth 1 https://github.com/FabriceSalvaire/redmine-improved-theme ${themes}/sass_theme
```
redmineup.com の token は各自で取得して差し替えること。

## プラグインの追加
```bash
plugins=/var/www/redmine/plugins && token=0c7a1fefdd47f3a96fb57a4f94450dbdf98dd && \
curl -L https://www.redmineup.com/license_manager/25768?token=${token} -o redmine_questions-0_0_7-light.zip && unzip $_ -d ${plugins}/ && \
curl -L https://www.redmineup.com/license_manager/30308?token=${token} -o redmine_favorite_projects-2_0_3-light.zip && unzip $_ -d ${plugins}/ && \
curl -L https://www.redmineup.com/license_manager/48678?token=${token} -o redmine_agile-1_4_6-light.zip && unzip $_ -d ${plugins}/ && \
curl -L https://www.redmineup.com/license_manager/48735?token=${token} -o redmineup_tags-2_0_2-light.zip && unzip $_ -d ${plugins}/ && \
curl -L https://www.redmineup.com/license_manager/42723?token=${token} -o redmine_people-1_3_2-light.zip && unzip $_ -d ${plugins}/ && \
curl -L https://www.redmineup.com/license_manager/48844?token=${token} -o redmine_checklists-3_1_11-light.zip && unzip $_ -d ${plugins}/ && \
curl -L https://www.redmineup.com/license_manager/47729?token=${token} -o redmine_crm-4_1_2-light.zip && unzip $_ -d ${plugins}/ && \
git clone --depth 1 https://github.com/syagawa/redmine_absolute_datetime ${plugins}/redmine_absolute_datetime && \
git clone --depth 1 https://github.com/haru/redmine_wiki_extensions ${plugins}/redmine_wiki_extensions && \
#git clone --depth 1 https://github.com/AlphaNodes/redmine_tweaks ${plugins}/redmine_tweaks && \
git clone --depth 1 https://github.com/cdwertmann/line_numbers ${plugins}/line_numbers && \
git clone --depth 1 https://github.com/suer/redmine_japanese_help ${plugins}/redmine_japanese_help && \
git clone --depth 1 https://github.com/onozaty/redmine-view-customize ${plugins}/view_customize && \
git clone --depth 1 https://github.com/peclik/clipboard_image_paste ${plugins}/clipboard_image_paste && \
git clone --depth 1 https://github.com/akiko-pusu/redmine_issue_templates ${plugins}/redmine_issue_templates && \
git clone --depth 1 https://github.com/akiko-pusu/redmine_issue_badge ${plugins}/redmine_issue_badge && \
git clone --depth 1 https://github.com/akiko-pusu/redmine_banner ${plugins}/redmine_banner && \
git clone --depth 1 https://github.com/tleish/redmine_editor_preview_tab ${plugins}/redmine_editor_preview_tab && \
git clone --depth 1 https://github.com/stpl/redmine_issue_history ${plugins}/redmine_issue_history && \
git clone --depth 1 https://github.com/haru/redmine_theme_changer ${plugins}/redmine_theme_changer && \
git clone --depth 1 --branch redmine-3.4-support https://github.com/codeout/redmine_already_read ${plugins}/redmine_already_read && \
docker exec redmine bundle install --jobs=4 --without development test && \
docker exec redmine bundle exec rake redmine:plugins:migrate RAILS_ENV=production && \
docker exec redmine passenger-config restart-app /usr/src/redmine
```
redmineup.com の token は各自で取得して差し替えること。

## バックアップ手順

### バックアップディレクトリの作成
```bash
mkdir /var/www/redmine/backup
```

### 手動バックアップ

#### データベース
```bash
docker exec mysql mysqldump redmine | gzip > /var/www/redmine/backup/redmine_db_`date +%F`.sql.gz
```

#### ファイル
```bash
cd /var/www/redmine && \
tar cvf backup/redmine_files_`date +%F`.tar.gz files
```

### 自動バックアップ

#### データベース
```bash
cat << '_EOF_' > /etc/systemd/system/backup-redmine-db.service
[Unit]
Description=Backup Redmine database

[Service]
Type=oneshot
ExecStart=/bin/bash -c "docker exec mysql mysqldump redmine | gzip > /var/www/redmine/backup/redmine_db_`date +%F`.sql.gz" && \
 find /var/www/redmine/backup -name redmine_db_*.tar.gz -mtime +14 | xargs rm
_EOF_
```
```bash
cat << '_EOF_' > /etc/systemd/system/backup-redmine-db.timer
[Unit]
Description=Backup Redmine database

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
_EOF_
```

#### ファイル
```bash
cat << '_EOF_' > /etc/systemd/system/backup-redmine-files.service
[Unit]
Description=Backup Redmine files

[Service]
Type=oneshot
ExecStart=/bin/bash -c "cd /var/www/redmine && tar -cf backup/redmine_files_`date +%F`.tar.gz files" && \
 find /var/www/redmine/backup -name redmine_files_*.tar.gz -mtime +14 | xargs rm
_EOF_
```
```bash
cat << '_EOF_' > /etc/systemd/system/backup-redmine-files.timer
[Unit]
Description=Backup Redmine files

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target
_EOF_
```
```bash
mkdir /var/www/redmine/backup && \
systemctl daemon-reload && \
systemctl enable backup-redmine-{db,files}.timer
```

## バージョンアップ手順

### Redmine 本体の更新
```bash
docker pull redmine && docker-compose restart && docker container prune
```

### テーマの更新
```bash
themes=/var/www/redmine/public/themes && cd ${themes} && \
for var in $(ls) ; do cd ${var} ; git checkout `git tag | tail -n 1` ; cd .. ; done
rm -rf ${themes}/circle_theme && curl -L https://www.redmineup.com/license_manager/40766?token=0c7a1fefdd47f3a96fb57a4f94450dbdf98dd -o circle_theme.zip && unzip $_ -d ${themes}/ && \
rm -rf ${themes}/a1_theme && curl -L https://www.redmineup.com/license_manager/40830?token=0c7a1fefdd47f3a96fb57a4f94450dbdf98dd -o a1_theme.zip && unzip $_ -d ${themes}/
```

### プラグインの更新
```bash
cd /var/www/redmine/plugins && \
for var in $(ls) ; do cd ${var} ; git checkout `git tag | tail -n 1` ; cd .. ; done && \
cd .. && \
docker exec redmine bundle install --jobs=4 --without development test && \
docker exec redmine bundle exec rake redmine:plugins:migrate RAILS_ENV=production && \
docker exec redmine bundle exec rake tmp:cache:clear tmp:sessions:clear && \
docker exec redmine passenger-config restart-app /usr/src/redmine
```

## TODO
* SSL 対応

## 参考 URL
* https://hub.docker.com/_/redmine/
* https://github.com/docker-library/redmine
* http://guide.redmine.jp/RedmineInstall/

## Redmine 関連記事
* [Redmineのtextile記法のテーブル - Qiita](https://qiita.com/bezeklik/items/e821a2816041f73ebb1f)
* [CentOS 7 に Redmine 3.3 をインストールする - Qiita](https://qiita.com/bezeklik/items/483b61c637c805f2945f)
* [Redmine 3.4 を CentOS 7.4 にインストールする - Qiita](https://qiita.com/bezeklik/items/0b1b54bc944804420501)
* [CentOS 7.4 で Docker の Redmine を動かす - Qiita](https://qiita.com/bezeklik/items/d3c82926da104ef0c5a3)
* [Redmine を Docker 公式イメージで運用する - Qiita](https://qiita.com/bezeklik/items/b5c39136a8db23e2e81c)