最新の Redmine 4 を Docker 公式イメージで運用する

CentOS 7.6 に Redmine 4.0 を Docker 公式イメージを利用してセットアップする手順の解説。

「[Redmine を Docker 公式イメージで運用する](https://qiita.com/bezeklik/items/b5c39136a8db23e2e81c)」は Redmine 3.x の記事だったので、 2019/03/31 にリリースされた Redmine 4.0.3 で再検証した。

## Redmine とは
![1280px-Redmine_logo.svg.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/15175/ec4cae8e-2793-172d-fcb1-a5086050fca1.png)
[Redmine](http://redmine.jp/) は Ruby on Rails で開発されているプロジェクト管理の OSS で、2006年にフランスの [Jean-Philippe Lang](https://www.redmine.org/users/1) によって開発された。ライセンスは [GPLv2](https://www.gnu.org/licenses/old-licenses/gpl-2.0.html) 。 [^COPYING] [^README_FOR_APP]
日本の参照数が最も多く [^trends-redmine] 、非アジア圏では未だに Trac の方が知名度が高い。 [^trends-trac] [^popcon-redmine] [^popcon-trac]

[^COPYING]: [/trunk/doc/COPYING - Redmine](https://www.redmine.org/projects/redmine/repository/entry/trunk/doc/COPYING)
[^README_FOR_APP]: "This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version." - [/trunk/doc/README_FOR_APP - Redmine](https://www.redmine.org/projects/redmine/repository/entry/trunk/doc/README_FOR_APP)

[^trends-redmine]: [Google トレンドで「redmine - すべての国、過去 12 か月間」の 地域別のインタレスト を見る](https://trends.google.co.jp/trends/explore/GEO_MAP/1573829400?hl=ja&tz=-540&q=redmine&sni=3)

[^trends-trac]: [redmine, trac - 調べる - Google トレンド](https://trends.google.co.jp/trends/explore?q=redmine,trac)

[^popcon-redmine]: [redmine - Popularity Contest Statistics -- Debian Quality Assurance](https://qa.debian.org/popcon-graph.php?packages=redmine)

[^popcon-trac]: [trac - Popularity Contest Statistics -- Debian Quality Assurance](https://qa.debian.org/popcon-graph.php?packages=trac)

### Redmine 3.x と 4.x の違い
システム要件に以下の違いがある。 [^requirements]
特に Ruby on Rails が 4.2 から 5.2 に変更されている影響で一部のプラグインで動作しなくなるものがある。

[^requirements]: https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Requirements

| Redmine | 3.3 / 3.4 | 4.0 |
|:-:|:-:|:-:|
| Ruby on Rails | 4.2 | 5.2 |
| Ruby | 1.9.3 - 2.4 | 2.2.2 - 2.6 |
| MySQL | 5.0 - 5.1 | 5.5 - 5.7 |
| PostgreSQL | 8.3 - 9.1 | 9.2 - |
| SQL Server | ? | 2012 - |

## 本稿の特徴
* Docker 公式イメージを使用
* ホスト OS に CentOS 7 を、データベースに MySQL 8.0 を使用
* データベースの文字コードは `utf8mb4` を使用
* themes, plugins, files および一部の設定ファイルはホスト OS からマウント
* Memcached の導入
* ホスト OS 上ですべて操作
* コマンドラインから一括設定変更
* systemd の Timer による自動バックアップ設定
* [記事分離予定] テーマ、プラグインの一括インストール
* [TODO] バージョンアップ手順 
* [TODO] SSL 対応

## Redmine の Docker イメージ
[Docker Hub](https://hub.docker.com/search/?q=redmine&type=image) で検索すると700を超えるイメージが見つかるが、スターを5件以上獲得しているのは以下の5つ。

|Docker イメージ名|スター数|ダウンロード数|
|---|--:|--:|
|[redmine](https://hub.docker.com/_/redmine) (公式イメージ)| 795 | 10000K |
|[sameersbn/redmine](https://hub.docker.com/r/sameersbn/redmine/)| 307 | 10000K |
|[bitnami/redmine](https://hub.docker.com/r/bitnami/redmine)| 43 | 500K |
|[74th/redmine-all-in-one](https://hub.docker.com/r/74th/redmine-all-in-one)| 10 | 7.9K |
|[inspiredgeek/redmine-alpine](https://hub.docker.com/r/inspiredgeek/redmine-alpine)| 7 | 10K |

## Docker のセットアップ
### Docker のインストール
```bash
yum --assumeyes install yum-utils && \
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \
yum --assumeyes install docker-ce && \
systemctl start docker && \
systemctl enable docker
```
CentOS Extras リポジトリから 1.13.1 がパッケージでインストールできるが、[公式リポジトリ](https://docs.docker.com/install/linux/docker-ce/centos/#install-using-the-repository)を利用すると最新版がインストールできる。
2019/10/09 時点での最新バージョンは 19.03.3 になる。

### Docker Compose のインストール
```bash
curl --location \
     --output /usr/local/bin/docker-compose \
     $(curl --silent --show-error \
            https://api.github.com/repos/docker/compose/releases/latest \
            | grep 'Linux-x86_64"' \
            | grep url \
            | cut --delimiter='"' --fields=4 \
     ) && \
chmod +x /usr/local/bin/docker-compose
```
EPEL リポジトリから docker-compose 1.18.0 がパッケージでインストールできるが、 [GitHub](https://github.com/docker/compose) からバイナリーをダウンロードすることで最新版が利用できる。
2019/10/09 時点での[最新バージョン](https://github.com/docker/compose/releases)は 1.24.1 になる。

[公式ドキュメントのインストール手順](https://docs.docker.com/compose/install/)ではバージョンを指定してダウンロードする方法が記載されているが、 [GitHub API](https://developer.github.com/v3/) を活用することで動的に最新版を取得することができる。

## 格納ディレクトリの作成
```bash
mkdir --parents --verbose /srv/redmine && \
matchpathcon $_ && \
semanage fcontext --add --type container_file_t $_ && \
restorecon -v $_ && \
matchpathcon $_
```
設定ファイル、添付ファイル、テーマ、プラグイン、ログの保存ディレクトリのマウント元として [FHS 3.0](http://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s17.html) や [GitLab](https://docs.gitlab.com/omnibus/docker/#run-the-image) を参考に `/srv/redmine` を作成。

[4.6. SELinux コンテキスト: ファイルのラベル付け - Red Hat Customer Portal](https://access.redhat.com/documentation/ja-jp/red_hat_enterprise_linux/7/html/selinux_users_and_administrators_guide/sect-security-enhanced_linux-working_with_selinux-selinux_contexts_labeling_files#sect-Security-Enhanced_Linux-SELinux_Contexts_Labeling_Files-Persistent_Changes_semanage_fcontext)

SELinux コンテキストのラベル名は RHEL 7.5 から `svirt_sandbox_file_t` が廃止されたので `container_file_t` を使用する。 [^svirt_sandbox_file_t]

[^svirt_sandbox_file_t]: ["新たに構築された 7.5 のシステムでは container_file_t しかないので fcontext を svrit_sandbox_file_t に設定できない" - 1525921 – Missing container_file_t context type within the container-selinux package shipped by rhel-7-server-extras-rpms](https://bugzilla.redhat.com/show_bug.cgi?id=1525921#c8)

ボリュームラベルの `:z` オプション等でコンテキストのラベル名を変更することもできる。 [^small-z] [^big-z]

[^small-z]: ["`z` オプションは、ボリュームの内容が複数のコンテナによって共有されていると Docker に伝えます。その結果、Docker は共有コンテント・ラベルとして内容をラベル付けします。" - ボリューム・ラベル - コンテナでデータを管理する — Docker-docs-ja 1.9.0b ドキュメント](http://docs.docker.jp/engine/userguide/dockervolumes.html#id6)

[^big-z]:  ["`Z` オプションは、内容はプライベートで共有されるべきではないラベルと Docker に伝えます。現在のコンテナのみが、プライベートに（個別に）ボリュームを利用可能です。" - ボリューム・ラベル - コンテナでデータを管理する — Docker-docs-ja 1.9.0b ドキュメント](http://docs.docker.jp/engine/userguide/dockervolumes.html#id6)


## Docker Compose

### configuration.yml
```bash:config/configuration.yml
mkdir --parents --verbose /srv/redmine/config && \
echo 'default:' > /srv/redmine/config/configuration.yml
```
メール設定で利用する `config/configuration.yml` ファイルを先にマウントしておくためにファイルを作成する。

### additional_environment.rb
```ruby:config/additional_environment.rb
mkdir --parents --verbose /srv/redmine/config && \
cat << "_EOF_" > /srv/redmine/config/additional_environment.rb
config.cache_store = :mem_cache_store, "memcached"
_EOF_
```
`config/additional_environment.rb` ファイルで Memcached を利用する設定をする。

`config.cache_store` は `:dalli_store` を指定する事例が多いが `:mem_cache_store` の方が汎用性が高いように見えるのでそちらを採用。 [^cache_store] [^mem_cache_store]

[^cache_store]: [:mem_cache_store vs. :dalli_store? · Issue #21595 · rails/rails](https://github.com/rails/rails/issues/21595)
[^mem_cache_store]: ["This cache store uses Danga's memcached server to provide a centralized cache for your application. Rails uses the bundled dalli gem by default." - 2.5 ActiveSupport::Cache::MemCacheStore - 2 Cache Stores - Caching with Rails: An Overview — Ruby on Rails Guides](https://guides.rubyonrails.org/caching_with_rails.html#activesupport-cache-memcachestore)

### Gemfile.local
```bash:Gemfile.local
cat << "_EOF_" > /srv/redmine/Gemfile.local
gem 'dalli'
_EOF_
```
Memcached を利用するために Ruby 用 Memcached クライアントの [dalli](https://github.com/petergoldstein/dalli) をインストールする `Gemfile.local` を用意する。

### docker-compose.yml ファイル
```yaml:docker-compose.yml
cat << "_EOF_" > /srv/redmine/docker-compose.yml
version: '3.7'
services:
  redmine:
    container_name: ${REDMINE:-redmine}
    image: redmine:4-passenger
    restart: always
    ports:
      - 80:3000
    depends_on:
      - ${REDMINE_DB_MYSQL:-mysql}
      - ${REDMINE_MEMCACHED:-memcached}
    environment:
      TZ: ${TZ}
      REDMINE_DB_MYSQL: ${REDMINE_DB_MYSQL:-mysql}
      REDMINE_DB_DATABASE: ${REDMINE_DB_DATABASE}
      REDMINE_DB_USERNAME: ${REDMINE_DB_USERNAME}
      REDMINE_DB_PASSWORD: ${REDMINE_DB_PASSWORD}
      REDMINE_DB_ENCODING: ${REDMINE_DB_ENCODING:-utf8mb4}
      VIRTUAL_HOST: ${VIRTUAL_HOST}
      VIRTUAL_PORT: ${VIRTUAL_PORT:-3000}
      LETSENCRYPT_HOST: ${VIRTUAL_HOST}
      LETSENCRYPT_EMAIL: ${LETSENCRYPT_EMAIL}
    volumes:
      - ${REDMINE_PATH:-.}/config/additional_environment.rb:/usr/src/redmine/config/additional_environment.rb
      - ${REDMINE_PATH:-.}/config/configuration.yml:/usr/src/redmine/config/configuration.yml
      - ${REDMINE_PATH:-.}/Gemfile.local:/usr/src/redmine/Gemfile.local
      - ${REDMINE_PATH:-.}/files:/usr/src/redmine/files:z
      - ${REDMINE_PATH:-.}/log:/usr/src/redmine/log:Z
      - ${REDMINE_PATH:-.}/plugins:/usr/src/redmine/plugins
      - ${REDMINE_PATH:-.}/public/themes:/usr/src/redmine/public/themes
  mysql:
    container_name: ${REDMINE_DB_MYSQL:-mysql}
    image: mysql:8
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    ports:
      - 3306:3306
    environment:
      TZ: ${TZ}
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
      MYSQL_DATABASE: ${REDMINE_DB_DATABASE}
      MYSQL_USER: ${REDMINE_DB_USERNAME}
      MYSQL_PASSWORD: ${REDMINE_DB_PASSWORD}
    volumes:
      - mysql:/var/lib/mysql
  memcached:
    container_name: ${REDMINE_MEMCACHED:-memcached}
    image: memcached
    restart: always
#    ports:
#      - 11211:11211
volumes:
  mysql:
    name: ${REDMINE_DB_MYSQL:-mysql}
_EOF_
```
Memcached を永続的に利用する場合は `config/additional_environment.rb` を、メール送信を永続的に利用する場合は `config/configuration.yml` をマウントする必要がある。

### .env ファイル
```ini:.env
DOMAIN=example.jp && \
FQDN=redmine.${DOMAIN} && \
cat << _EOF_ > /srv/redmine/.env
REDMINE_PATH=/srv/redmine
TZ=Asia/Tokyo
MYSQL_ROOT_PASSWORD=$(< /dev/urandom tr -dc 'A-Za-z0-9!$%&()*+,-./:;<=>?@[\]^_{|}~' | head -c 16; echo)
REDMINE_DB_MYSQL=mysql
REDMINE_DB_DATABASE=redmine_$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 8; echo)
REDMINE_DB_USERNAME=redmine_$(< /dev/urandom tr -dc 'A-Za-z0-9' | head -c 8; echo)
REDMINE_DB_PASSWORD=$(< /dev/urandom tr -dc 'A-Za-z0-9!$%&()*+,-./:;<=>?@[\]^_{|}~' | head -c 16; echo)
REDMINE_DB_ENCODING=utf8mb4
REDMINE_MEMCACHED=memcached
VIRTUAL_HOST=$(echo ${FQDN})
VIRTUAL_PORT=3000
LETSENCRYPT_HOST=$(echo ${FQDN})
LETSENCRYPT_EMAIL=redmine@$(echo $DOMAIN)
_EOF_
chmod 444 /srv/redmine/.env
```

### コンテナの起動
```bash
docker-compose --project-directory /srv/redmine up --detach && \
firewall-cmd --permanent --add-service=http{,s} && \
firewall-cmd --reload && \
firewall-cmd --list-services && \
sleep 30 && \
docker container logs --follow redmine
```
`Completed 200 OK` と表示されたら <kbd>Ctrl</kbd> + <kbd>c</kbd> で抜ける。

## 初期設定
### デフォルトデータのロード
```bash
docker exec redmine bundle exec rake redmine:load_default_data RAILS_ENV=production REDMINE_LANG=ja
```

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

### ロールと権限
```sql
cat << '_EOQ_' | docker exec --interactive mysql mysql redmine
UPDATE `roles` SET `permissions` = NULL WHERE `id` = '1' OR `id` = '2';
_EOQ_
```

### 設定
```sql
cat << '_EOQ_' | docker exec --interactive 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','---
- Git
'), -- 使用するバージョン管理システム
('commit_ref_keywords','refs,references,IssueID,*'), -- 参照用キーワード (refs,references,IssueID)
('commit_cross_project_ref','1'); -- 異なるプロジェクトのチケットの参照/修正を許可 (0)
_EOQ_
```

## メール設定

### ホスト OS の Postfix を利用する場合

#### Postfix の設定
```bash
cp --verbose /{usr/lib,etc}/systemd/system/postfix.service && \
sed --in-place \
    --expression="/After/ s/$/ docker.service/" \
    /etc/systemd/system/postfix.service && \
systemctl daemon-reload && \
grep After /{usr/lib,etc}/systemd/system/postfix.service && \
NETWORK=$(docker container inspect redmine --format='{{.HostConfig.NetworkMode}}') && \
SUBNET=$(docker network inspect ${NETWORK} --format='{{range .IPAM.Config}}{{.Subnet}}{{end}}') && \
GATEWAY=$(docker network inspect ${NETWORK} --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}') && \
echo ${NETWORK}, ${SUBNET}, ${GATEWAY} && \
postconf -d | egrep "^inet_interfaces|^mynetworks" && \
postconf -n | egrep "inet_interfaces|mynetworks" && \
sed --in-place=.org \
    --expression="/^inet_interfaces/ s|localhost\$|localhost, 127.0.0.1, ${GATEWAY}|" \
    /etc/postfix/main.cf && \
postconf -n | egrep "inet_interfaces|mynetworks" && \
systemctl restart postfix && \
firewall-cmd --permanent --zone=public \
             --add-rich-rule="rule family=\"ipv4\" source address=\"${SUBNET}\" service name=\"smtp\" accept" && \
firewall-cmd --reload && \
firewall-cmd --list-rich-rules
```
CentOS 7.6 minimal のバニラ状態を前提とした置換処理のため、環境に応じて適宜変更のこと。

#### configuration.yml
```yaml:config/configuration.yml
NETWORK=$(docker container inspect redmine --format='{{.HostConfig.NetworkMode}}') && \
GATEWAY=$(docker network inspect ${NETWORK} --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}') && \
cat << _EOF_ > /srv/redmine/config/configuration.yml
default:
  email_delivery:
    delivery_method: :smtp
    smtp_settings:
      address: ${GATEWAY}
      port: 25
      domain: redmine.example.jp
_EOF_
```

### Gmail を利用する場合
```yaml:config/configuration.yml
NETWORK=$(docker container inspect redmine --format='{{.HostConfig.NetworkMode}}') && \
GATEWAY=$(docker network inspect ${NETWORK} --format='{{range .IPAM.Config}}{{.Gateway}}{{end}}')
cat << _EOF_ > config/configuration.yml
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_
```

### Passenger の再起動
```bash
docker exec redmine bundle exec rails runner 'Rails.cache.clear' && \
docker exec redmine passenger-config restart-app /usr/src/redmine
```

## Memcached の設定
```bash
docker exec redmine bundle install && \
docker exec redmine passenger-config restart-app /usr/src/redmine
```

## バックアップ設定
```ini
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 > /srv/redmine/backup/redmine_db_`date +%F`.sql.gz" && \
 find /srv/redmine/backup -name redmine_db_*.sql.gz -mtime +14 | xargs rm
_EOF_
```
```ini
cat << '_EOF_' > /etc/systemd/system/backup-redmine-db.timer
[Unit]
Description=Backup Redmine database

[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target
_EOF_
```
```ini
cat << '_EOF_' > /etc/systemd/system/backup-redmine-files.service
[Unit]
Description=Backup Redmine files

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

[Timer]
OnCalendar=daily
RandomizedDelaySec=1h
Persistent=true

[Install]
WantedBy=timers.target
_EOF_
```
```bash
mkdir --parents --verbose /srv/redmine/backup && \
systemctl daemon-reload && \
systemctl enable backup-redmine-{db,files}.timer && \
systemctl list-unit-files | egrep "STATE|backup" && \
systemctl list-timers --all
```
## プラグイン
別記事として「[利便性の高い Redmine プラグイン - Qiita](https://qiita.com/bezeklik/items/ca5644f62e8a951cf1b2)」にまとめた。

## テーマ
### RedmineUP
```bash
yum --assumeyes install unzip && \
themes=/srv/redmine/public/themes && \
token=0c7a1fefdd47f3a96fb57a4f94450dbdf98dd && \
curl -L https://www.redmineup.com/license_manager/40766?token=${token} -o ~/circle_theme-2_1_3.zip && unzip -q $_ -d ${themes}/ ; \
curl -L https://www.redmineup.com/license_manager/40830?token=${token} -o ~/a1_theme-2_0_0.zip && unzip -q $_ -d ${themes}/
```
`token` は各自で [RedmineUP](https://www.redmineup.com/pages/ja/themes) から取得して差し替えること。

### GitHub
```bash
yum --assumeyes install git && \
themes=/srv/redmine/public/themes && \
curl -L https://github.com/akabekobeko/redmine-theme-minimalflat2/releases/download/v1.6.1/minimalflat2-1.6.1.zip -o ~/minimalflat2-1.6.1.zip && unzip -q $_ -d ${themes}/ ; \
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
```

## SSL 対応
```yaml
docker network create nginx-proxy && \
mkdir --parents --verbose /srv/nginx-proxy && \
cat << "_EOF_" > /srv/nginx-proxy/docker-compose.yml && \
docker-compose --project-directory /srv/nginx-proxy up --detach
version: '3.7'
services:
  nginx-proxy:
    container_name: ${NGINX_PROXY:-nginx-proxy}
    image: jwilder/nginx-proxy
    labels:
      - com.github.jrcs.letsencrypt_nginx_proxy_companion.nginx_proxy
    restart: always
    ports:
      - 80:80
      - 443:443
    volumes:
      - /srv/nginx-proxy:/etc/nginx/vhost.d
      - /srv/nginx-proxy:/usr/share/nginx/html
      - /srv/nginx-proxy/certs:/etc/nginx/certs:ro
      - /var/run/docker.sock:/tmp/docker.sock:ro
 letsencrypt:
    container_name:letsencrypt
    image: jrcs/letsencrypt-nginx-proxy-companion
    restart: always
    depends_on:
      - ${NGINX_PROXY:-nginx-proxy}
    volumes:
      - /srv/nginx-proxy:/etc/nginx/vhost.d
      - /srv/nginx-proxy:/usr/share/nginx/html
      - /srv/nginx-proxy/certs:/etc/nginx/certs:rw
      - /var/run/docker.sock:/var/run/docker.sock:ro
networks:
  default:
    name: ${NETWORK:-nginx-proxy}
_EOF_
```
https://hub.docker.com/r/jrcs/letsencrypt-nginx-proxy-companion
https://github.com/JrCs/docker-letsencrypt-nginx-proxy-companion
https://hub.docker.com/r/jwilder/nginx-proxy/
https://github.com/jwilder/nginx-proxy

## その他の 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)
* [bitnami でインストールした Redmine を Docker に移設した - Qiita](https://qiita.com/bezeklik/items/1840fdd7aef84cd979c7)