オープンソースのPaaSソフトウェア CloudFoundry の技術情報やイベント告知などを掲載します

2015-07-24

Redmine を Cloud Foundry で動かす

「Cloud Foundry 百日行」第36日目は,Ruby-on-Rails ベースの project management ソフト Redmine です。今さら説明の必要のない超有名アプリケーションだと思いますが,これも Cloud Foundry の上で動かすことができます。

基本情報

手順の概要は以下の通りです。

  • 1) ソースコードの取得
  • 2) セッション・ストアの秘密鍵の生成
  • 3) データベース・サービスの作成とアプリとのバインド
  • 4) 初期データ投入に必要な環境変数の設定
  • 5) アプリの更新・起動
  • 6) 動作確認

1. ソースコードの取得

公式サイトのインストール手順 では, http://www.redmine.org/projects/redmine/wiki/Download から tarball をダウンロードするか,リポジトリーからコードをチェックアウトすると書いてあるので,ここでは GitHub の公式ミラーからソースコードをチェックアウトします。

$ git clone https://github.com/redmine/redmine.git
$ cd redmine

今回は最新の master ではなく,最新安定版 (検証時点では 3.0.4) を使うことにします。

$ git checkout 3.0.4

2. セッション・ストアの秘密鍵の生成

公式サイトのインストール手順には, セッション・ストアの秘密鍵の生成 が含まれています。これはコマンド的には bundle exec rake generate_secret_token を実行すれば良いのですが,このコマンドを正常に実行する前提条件として,

  • Ruby と bundler gem のインストール
  • bundle install の実行
  • config/database.yml が存在すること

が必要になります。

今回は1番目の「Ruby と bundler gem のインストール」は既に終わっているものとして,2番目以降について順次述べていきます。

bundle install の実行

$ bundle install --path vendor/bundle --without rmagick

--path vendor/bundle は,ローカルの vendor/bundle ディレクトリーに Ruby の gem をインストールするというオプションです。必須ではありませんが,これを付けないと,この Redmine だけで使う gem が Ruby 全体の gem を入れるディレクトリーにインストールされ,「ライブラリー汚染」の原因になるので,付けたほうが無難です。

--without rmagick は,rmagick gem のインストールをスキップするためのオプションです。これも必須ではないのですが,これを付けないと rmagick をインストールするために追加のパッケージ (Ubuntu では libmagickwand-dev, imagemagick 等) のインストールが必要になります。今回 Redmine はローカルの環境ではなく Cloud Foundry 上で実行するので,ローカルにこれらのパッケージを入れる必要はありません。つまり bundle exec rake generate_secret_token を実行できる環境を整えるだけのための bundle install なので,rmagick のインストールはスキップすることにしました。

config/database.yml の作成

これも,ただ単に形式の整ったファイルが存在すればいいので, config/database.yml.example をコピーするだけでOKです。

$ cp config/database.yml.example config/database.yml

セッション・ストアの秘密鍵の生成

前提が整ったので,本来の目的であるセッション・ストアの秘密鍵生成を行います。

$ bundle exec rake generate_secret_token

config/initializers/secret_token.rb というファイルができていて,内容が以下のようになっていればOKです (当然ですが代入式の右辺値はこの値とは異なるはずです)。

$ cat config/initializers/secret_token.rb
# This file was generated by 'rake generate_secret_token', and should
# not be made visible to public.
# If you have a load-balancing Redmine cluster, you will need to use the
# same version of this file on each machine. And be sure to restart your
# server when you modify this file.
#
# Your secret key for verifying cookie session data integrity. If you
# change this key, all old sessions will become invalid! Make sure the
# secret is at least 30 characters and all random, no regular words or
# you'll be exposed to dictionary attacks.
RedmineApp::Application.config.secret_key_base = '431137b97013042fb346ce3f5517c773d2e7dca562651ab389e81768e52bd9507710f8144437159a'

これでセッション・ストア秘密鍵が生成できました。

3. データベース・サービスの作成とアプリとのバインド

次に,データベース・サービスを作成し,アプリにバインドします。

データベース・サービスの作成

MySQL サービスを作成します。

$ cf create-service p-mysql 100mb my4red
Creating service instance my4red in org nota-ja / space 100 as nota-ja...
OK

アプリを停止状態でプッシュ

サービスとバインドするために,アプリを停止状態でプッシュするのですが,このままプッシュすると vendor/bundle 内のファイルも全てアップロードされてしまいます。Cloud Foundry 側で bundle install が実行されるため,これらは実際にはアップロード不要なので, .cfignore ファイルを予め作成して,vendor/bundle をアップロード対象から除外します。

$ emacs .cfignore
$ cat .cfignore
vendor/bundle/

アプリを停止状態でプッシュします。

$ cf push redmine --no-start
Creating app redmine in org nota-ja / space 100 as nota-ja...
OK
..
Done uploading
OK

アプリとサービスのバインド

$ cf bind-service redmine my4red
Binding service my4red to app redmine in org nota-ja / space 100 as nota-ja...
OK
TIP: Use 'cf restage redmine' to ensure your env variable changes take effect

4. 初期データ投入に必要な環境変数の設定

公式サイトのインストール手順 に従って,初期データの投入を自動で行うために環境変数 REDMINE_LANG を予め設定しておきます。これが未設定だと,初期データ投入時に対話的に入力を求められてしまい,Cloud Foundry では入力のすべがないためエラーが発生してしまいます。

$ cf set-env redmine REDMINE_LANG ja

日本語を使用したいので, ja に設定しました。

Setting env variable 'REDMINE_LANG' to 'ja' for app redmine in org nota-ja / space 100 as nota-ja...
OK
TIP: Use 'cf restage' to ensure your env variable changes take effect
$ cf env redmine
Getting env variables for app redmine in org nota-ja / space 100 as nota-ja...
OK
..
User-Provided:
REDMINE_LANG: ja
..

5. アプリの更新・起動

起動コマンドを設定してアプリを更新・起動します。

$ cf push redmine -c 'bundle exec rake db:migrate && bundle exec rake redmine:load_default_data && bundle exec rails server --port=$PORT' -t 180

ポイントは2つ。

1つは起動コマンドでデータベース・スキーマの設定 (bundle exec rake db:migrate) と初期データの投入 (bundle exec rake redmine:load_default_data) を行ったのちに,環境変数で指定された待ち受けポートでアプリを起動する (bundle exec rails server) こと。

もう1つは,データベース・スキーマの設定にけっこう時間がかかるので,タイムアウトを長めに設定する (-t 180) ことです。

Updating app redmine in org nota-ja / space 100 as nota-ja...
OK
..
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: redmine.10.244.0.34.xip.io
last uploaded: Thu Jul 23 03:59:09 UTC 2015
stack: cflinuxfs2
buildpack: Ruby

     state     since                    cpu    memory           disk      details
#0   running   2015-07-23 01:01:16 PM   0.0%   143.5M of 256M   0 of 1G

アプリが起動しました。

6. 動作確認

ブラウザーでアプリにアクセスしてみます。

初期画面はこんな感じです:

公式サイトの情報 に従い,初期ユーザー admin でログインします:

ログインできました:

新しいプロジェクトを作ってみます:

作成が成功し,プロジェクト一覧に表示されました:

参考情報

今回 Cloud Foundry 上に構築した Redmine はほぼ問題なく使えるのですが,添付ファイル等がローカル・ファイルシステムに保存されるため,再起動したりスケールアウトした時に添付ファイル等へのアクセスに問題が生じます。これを回避するために,添付ファイル等をオブジェクト・ストレージに保存するという方法があります。

今回は検証環境にオブジェクト・ストレージが用意できなかったため試してみることができませんでしたが,ご要望があれば別途試してみたいと思います。

今回使用したソフトウェア