Redmine を Azure App Service に構築する

　Redmine 4.1.1 を Azure App Service に構築する手順です。IaaS ではなく PaaS を利用するようにしています。本稿の前提条件および注意事項を、以下に箇条書きにしています

* PaaS の **App Service on Linux (Web App for Containers)** と **Azure Database for MySQL** を使用します。IaaS の Virtual Machine を使用しません
* Azure Database for MySQL の従量課金が発生する手順が含まれています
* 空白のデータベースを新しく作成して構築します。既成のデータベースをクラウドへリフトする手順ではありません
* PaaS で初期構築するまでを記載しています。実運用を想定したセキュリティ、パフォーマンスのカスタマイズは含まれていません
* Redmine は 4.1.1，Ruby は 2.6，Azure Database for MySQL は 5.7 を使用しています

　本稿の手順をすすめるためには Azure サブスクリプション、リソースグループ、App Service プラン が必要です。サブスクリプション等の作成方法はここでは説明していませんので Microsoft Docs の説明を参考にしてください

- [Azure 無料アカウントの作成][01]
- [Azure portal を使用して リソース グループを管理する][02]
- [Azure で App Service プランを管理する][03]

[01]: https://azure.microsoft.com/free/
[02]: https://docs.microsoft.com/azure/azure-resource-manager/management/manage-resource-groups-portal
[03]: https://docs.microsoft.com/azure/app-service/app-service-plan-manage

## 手順

　手順は次の 3 段階に分けています。Infrastructure as Code のように自動化したかったところですが、主に Azure Portal の画面操作と Docker Desktop for Mac の CLI を使用しています

1. [Azure Database for MySQL を作成する][10]  
   データベース サーバーとして使用する MySQL サーバーと空白のデータベースを作成します。この手順は [Microsoft Docs のクイック スタート][11] の内容を参考にします
2. [Redmine のデータベースを構築する][20]  
   空白のデータベースに Redmine のテーブル等を作成します。Rake の db:migrate コマンドを使用するため、まずラップトップ等のシステムに Redmine をインストールします。この手順は [Redmine.org の Installation Guide][21] の内容を参考にします
3. [Web App for Containers を構築する][30]  
   Redmine の Docker 公式イメージ から App Service を作成します。Docker イメージの使用方法については [Docker Hub の Redmine の説明][31] を参考にします

### Azure Database for MySQL を作成する

　Azure Portal 等を使用して Azure Database for MySQL サーバーを作成します。Azure Portal を使用した作成手順は [Microsoft Docs のクイック スタート][11] に詳しい説明があります（同じ内容を本稿に転載することはしません）。このときに作成したサーバー情報は Redmine の config/database.yml の設定で必要になるため、控えておきます。

　MySQL サーバーを作成した後は、空白のデータベースを作成します。ローカル環境 または Azure Cloud Shell の mysql クライアントからサーバーへ接続できるようにファイアウォール規則を適宜設定しておきます。データベースの名前は任意ですが、ここでは `redmine` とします。

```shell-session:redmineデータベースを作成する
user@Azure:~$ mysql --host={サーバー名}.mysql.database.azure.com \
  --user={ログイン名}@{サーバー名} -p
Enter password:
Welcome to the MariaDB monitor.  Commands end with ; or \g.
Your MySQL connection id is 65486
Server version: 5.6.47.0 MySQL Community Server (GPL)

Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

MySQL [(none)]> CREATE DATABASE redmine CHARACTER SET utf8mb4;
Query OK, 1 row affected (0.264 sec)
```

　データベースの作成までできたら、後続の手順で必要になる database.yml の設定内容（データベース名、サーバー名、ログイン名、パスワード）をまとめておきます。

```yaml:config/database.yml
production:
  adapter: mysql2
  database: {redmine のデータベース名}
  host: {サーバー名}.mysql.database.azure.com
  username: {ログイン名}@{サーバー名}
  password: {パスワード}
  encoding: utf8mb4
```

[11]: https://docs.microsoft.com/azure/mysql/quickstart-create-mysql-server-database-using-azure-portal

### Redmine のデータベースを構築する

　Azure Database for MySQL に作成した空白のデータベースに Redmine の動作に必要なテーブル等を作成していきます。Rake のマイグレーションファイルを使用する（rake db:migrate）ため [redmine.org の Installation Guide][21] に沿って、ラップトップ等のシステムに Redmine をインストールします。

　この記事では macOS を使用していますが、システムにプリインストールされている Ruby を使おうとすると [nokogiri][22] や [tiny_tds][23] 等の依存パッケージ関連のエラーが起きやすいため、[Docker Desktop for Mac][24] と [ruby:2.6 の Docker コンテナ][25] を使用しています

```shell-session:rakeマイグレーションファイルの実行
% docker pull ruby:2.6
% docker run -it -p 3000:3000 ruby:2.6 bash

## redmine.org からアーカイブファイルを取得します
/# cd /usr/local/src/
/usr/local/src# wget https://www.redmine.org/releases/redmine-4.1.1.tar.gz
/usr/local/src# tar xfz redmine-4.1.1.tar.gz
/usr/local/src# cd redmine-4.1.1

## Azure Database for MySQL の接続情報を設定します
## ruby の Docker コンテナで vi が使えなかったためヒアドキュメントにて
/usr/local/src/redmine-4.1.1# cat -<<EOF > config/database.yml
production:
  adapter: mysql2
  database: {redmine のデータベース名}
  host: {サーバー名}.mysql.database.azure.com
  username: {ログイン名}@{サーバー名}
  password: {パスワード}
  encoding: utf8mb4
EOF

## 依存パッケージをインストールします
/usr/local/src/redmine-4.1.1# bundle install --without development test
## セッション ストア シークレットを作成します
/usr/local/src/redmine-4.1.1# bundle exec rake generate_secret_token
## スキーマオブジェクトをつくり、デフォルト構成データを読み込みます
/usr/local/src/redmine-4.1.1# bundle exec rake db:migrate RAILS_ENV=production
/usr/local/src/redmine-4.1.1# bundle exec rake redmine:load_default_data RAILS_ENV=production REDMINE_LANG=ja
```

　rake によるビルドが完了したらデータベースの構築は完了です。この時点で、ローカル環境の WEBrick Web サーバー（localhost:3000）と Azure Database for MySQL のデータベースサーバーで動作を確認できるはずです

```shell-session:WEBrickによる動作確認
/usr/local/src/redmine-4.1.1# bundle exec rails server webrick -e production
=> Booting WEBrick
=> Rails 5.2.4.2 application starting in production on http://0.0.0.0:3000
=> Run `rails server -h` for more startup options
 INFO  WEBrick 1.4.2
 INFO  ruby 2.6.6 (2020-03-31) [x86_64-linux]
 INFO  WEBrick::HTTPServer#start: pid=10010 port=3000
```

　このときに admin ユーザーのパスワードやアプリケーションのタイトルを規定値から変更しておきます。初期構築時の管理ユーザーは [Installation Guide][26] に説明があるとおり `login: admin，password: admin` でログインできます

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/fb2af890-26f6-d95d-0be8-e3351a113234.png" width="600px" />

[21]: https://www.redmine.org/projects/redmine/wiki/RedmineInstall
[22]: https://nokogiri.org/tutorials/installing_nokogiri.html#macos
[23]: https://stackoverflow.com/questions/24394476/unable-to-gem-install-tiny-tds-os-x-mavericks
[24]: https://hub.docker.com/editions/community/docker-ce-desktop-mac
[25]: https://hub.docker.com/_/ruby
[26]: https://www.redmine.org/projects/redmine/wiki/RedmineInstall#Step-10-Logging-into-the-application

### Web App for Containers を構築する

　次に、Azure Portal に画面を戻して、App Service を作成します。ここではイメージ ソースを [Docker Hub の Redmine][31] とし、App Service プランの価格レベルは無料の F1 とします。

| 設定項目 | 設定値 |
|:--|:--|
| **App Service の名前** | **<任意の名前>** .azurewebsites.net |
| **公開 (Publish)** | Docker Container |
| **オプション** | Single Container |
| **イメージ ソース** | Docker Hub |
| **アクセスの種類** | Public |
| **イメージとタグ (Image:Tag)** | redmine:latest (4.1.1) |

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/e8835bc9-4462-1519-3612-64e50b4b098c.png" width="600px" />

　Docker Hub の Redmine 公式イメージから作成した直後の時点では、データベース アダプターが SQLite3 となっています。SQLite3 のままでも動作はしますが、先の手順で構築した Azure Database for MySQL をデータベースサーバーと参照するように App Service のアプリケーション設定に MySQL の接続情報を設定します。

| App Service のアプリケーション設定 | 設定値 |
|:--|:--|
| **REDMINE_DB_DATABASE** | \<MySQL のデータベース名\> |
| **REDMINE_DB_ENCODING** | utf8mb4 |
| **REDMINE_DB_MYSQL** | \<MySQL のサーバー名\> .mysql.database.azure.com |
| **REDMINE_DB_USERNAME** | \<MySQL のログイン名\>@\<MySQL のサーバー名\> |
| **REDMINE_DB_PASSWORD** | \<MySQL のパスワード\> |

　設定値を入力したら、変更を保存してアプリケーションを再起動します。Azure Portal でアプリケーションの設定を追加する方法は [Microsoft Docs][32] に詳しい説明があります。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/92a46431-e7ad-817d-10c8-a2db55559dba.png" width="600px" />

　アプリケーションの再起動後、App Service から Azure Database for MySQL へ接続できていれば、「管理/情報」画面の Database adapter が Mysql2 になっていることを確認できます。App Service から MySQL サーバーへ接続できない場合は、ファイアウォール規則で拒否されていないかどうかを注意して確認します。

| 既定のアダプタ: SQLite3 | 設定変更後のアダプタ: Mysql2 |
|:-:|:-:|
| <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/6c4379b9-90f5-bf05-5321-9800658f9f27.png" /> | <img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/58/4cc1a84d-36c4-bb63-a844-9b7050432492.png" /> |

　何かエラーが発生している場合は Azure Portal の コンテナーの設定 (Container settings) のブレードのログから原因がわかる可能性があります。

[10]: #azure-database-for-mysql-を作成する
[20]: #redmine-のデータベースを構築する
[30]: #web-app-for-containers-を構築する
[31]: https://hub.docker.com/_/redmine/
[32]: https://docs.microsoft.com/azure/app-service/configure-common