daichi.dev

ブログをHerokuからOpenShiftに移行する

@daichirata

Herokuを無料で使い続けることが難しくなってしまい、以前のブログ(Sinatra/Lokka)はどこかに移行しておきたいと思い色々検討した。

意外とHerokuの様に使えるPassがなくて、低スペックとはいえ無料で無制限にっていうのは色々と難しい所あったのかなーとか思いつつもとりあえず、ブログだけ移行できればよかったので3つのアプリまでは無料で動かすことが出来て、Herokuライクに使えそうなOpenShift Onlineに移行してみた。 Onlineの方はDockerを使ったOpenShift v3ではなくGearとかCartridgeの奴。

rhc

WebConsoleも不自由しないくらいには作りこまれているがOpenShift Developersが全てrhcコマンドなので、先ずはrhcをインストールする。大体herokuコマンドのような物だと思えば良い。

$ gem install rhc

ちなみに、OpenShift Developersは結構細かくドキュメントが記載されていて正直ここを見ながらやるだけで特に移行に困ることはなかったの結構良かった。

次に、rhcのセットアップを行う。

$ rhc setup

聞かれたとおりに登録メールアドレスやパスワードを入力していく。初めのほうで

If you have your own OpenShift server, you can specify it now. Just hit enter to use the server for OpenShift Online: openshift.redhat.com.
Enter the server hostname: |openshift.redhat.com|

と聞かれるかもしれないが、今回はOpenShift OnlineなのでそのままEnterで問題ない。

Please enter a namespace (letters and numbers only) |<none>|:

の部分に関してはユーザーごとのnamespaceを自分で決めることが出来てそれがドメインの一部になる。 私はdaichをnamespaceにしたのでアプリは http://xxxx-daich.rhcloud.com というFQDNが割り当てられることになる。

Application

今のところ作成可能なアプリケーションは以下のとおり。

Do-It-Yourself 0.1                      rhc create-app <app name> diy-0.1
JBoss Application Server 7              rhc create-app <app name> jbossas-7
JBoss Data Virtualization 6             rhc create-app <app name> jboss-dv-6.1.0
JBoss Enterprise Application Platform 6 rhc create-app <app name> jbosseap-6
JBoss Unified Push Server 1.0.0.Beta1   rhc create-app <app name> jboss-unified-push-1
JBoss Unified Push Server 1.0.0.Beta2   rhc create-app <app name> jboss-unified-push-2
Jenkins Server                          rhc create-app <app name> jenkins-1
Node.js 0.10                            rhc create-app <app name> nodejs-0.10
PHP 5.3                                 rhc create-app <app name> php-5.3
PHP 5.4                                 rhc create-app <app name> php-5.4
PHP 5.4 with Zend Server 6.1            rhc create-app <app name> zend-6.1
Perl 5.10                               rhc create-app <app name> perl-5.10
Python 2.6                              rhc create-app <app name> python-2.6
Python 2.7                              rhc create-app <app name> python-2.7
Python 3.3                              rhc create-app <app name> python-3.3
Ruby 1.8                                rhc create-app <app name> ruby-1.8
Ruby 1.9                                rhc create-app <app name> ruby-1.9
Ruby 2.0                                rhc create-app <app name> ruby-2.0
Tomcat 6 (JBoss EWS 1.0)                rhc create-app <app name> jbossews-1.0
Tomcat 7 (JBoss EWS 2.0)                rhc create-app <app name> jbossews-2.0
Vert.x 2.1                              rhc create-app <app name> jboss-vertx-2.1
WildFly Application Server 10           rhc create-app <app name> jboss-wildfly-10
WildFly Application Server 8.2.1.Final  rhc create-app <app name> jboss-wildfly-8
WildFly Application Server 9            rhc create-app <app name> jboss-wildfly-9

Sinatraを動かしたいのでRuby 2.0を使用する。

$ rhc app create anewcomer ruby-2.0

Application Options
-------------------
Domain:     daich
Cartridges: ruby-2.0
Gear Size:  default
Scaling:    no

Creating application 'anewcomer' ... done

Waiting for your DNS name to be available ... done

Cloning into 'anewcomer'...
Warning: Permanently added the RSA host key for IP address 'xxx.xxx.xxx.xxx' to the list of known hosts.

Your application 'anewcomer' is now available.

  URL:        http://anewcomer-daich.rhcloud.com/
  SSH to:     xxxx
  Git remote: xxxxx
  Cloned to:  /path/to/dir/anewcomer

Run 'rhc show-app anewcomer' for more details about your app.

後は出力されたGit remoteにpushするだけで良い。

Database

今のところ追加出来るCartridgeは以下のとおり。

$ rhc cartridge list

jbossas-7                JBoss Application Server 7              web
jboss-dv-6.1.0 (!)       JBoss Data Virtualization 6             web
jbosseap-6 (*)           JBoss Enterprise Application Platform 6 web
jboss-unified-push-1 (!) JBoss Unified Push Server 1.0.0.Beta1   web
jboss-unified-push-2 (!) JBoss Unified Push Server 1.0.0.Beta2   web
jenkins-1                Jenkins Server                          web
nodejs-0.10              Node.js 0.10                            web
perl-5.10                Perl 5.10                               web
php-5.3                  PHP 5.3                                 web
php-5.4                  PHP 5.4                                 web
zend-6.1                 PHP 5.4 with Zend Server 6.1            web
python-2.6               Python 2.6                              web
python-2.7               Python 2.7                              web
python-3.3               Python 3.3                              web
ruby-1.8                 Ruby 1.8                                web
ruby-1.9                 Ruby 1.9                                web
ruby-2.0                 Ruby 2.0                                web
jbossews-1.0             Tomcat 6 (JBoss EWS 1.0)                web
jbossews-2.0             Tomcat 7 (JBoss EWS 2.0)                web
jboss-vertx-2.1 (!)      Vert.x 2.1                              web
jboss-wildfly-10 (!)     WildFly Application Server 10           web
jboss-wildfly-8 (!)      WildFly Application Server 8.2.1.Final  web
jboss-wildfly-9 (!)      WildFly Application Server 9            web
diy-0.1                  Do-It-Yourself 0.1                      web
cron-1.4                 Cron 1.4                                addon
jenkins-client-1         Jenkins Client                          addon
mongodb-2.4              MongoDB 2.4                             addon
mysql-5.1                MySQL 5.1                               addon
mysql-5.5                MySQL 5.5                               addon
phpmyadmin-4             phpMyAdmin 4.0                          addon
postgresql-8.4           PostgreSQL 8.4                          addon
postgresql-9.2           PostgreSQL 9.2                          addon
rockmongo-1.1            RockMongo 1.1                           addon
switchyard-0             SwitchYard 0.8.0                        addon
haproxy-1.4              Web Load Balancer                       addon

Note: Web cartridges can only be added to new applications.

(*) denotes a cartridge with additional usage costs.

(!) denotes a cartridge that will not receive automatic security updates.

Herokuではデフォルトのまま使用していたのでPostgreSQLだったが今回はMySQL5.5を使用する。

$ rhc cartridge add mysql-5.5mysql-5.5 --app anewcomer

Adding mysql-5.5 to application 'anewcomer' ... done

mysql-5.5 (MySQL 5.5)
---------------------
  Gears:          Located with ruby-2.0
  Connection URL: mysql://$OPENSHIFT_MYSQL_DB_HOST:$OPENSHIFT_MYSQL_DB_PORT/
  Database Name:  xxxx
  Password:       xxxx
  Username:       xxxx

MySQL 5.5 database added.  Please make note of these credentials:

       Root User: xxxx
   Root Password: xxxx
   Database Name: xxxx

Connection URL: mysql://$OPENSHIFT_MYSQL_DB_HOST:$OPENSHIFT_MYSQL_DB_PORT/

You can manage your new MySQL database by also embedding phpmyadmin.
The phpmyadmin username and password will be the same as the MySQL credentials above.

UserやPasswordが出力されているが、基本的にDBの情報は全て環境変数として提供されているのでそこからアクセスする。 MySQL on OpenShift

Heroku to OpenShift

アプリケーションを作成した際に出来た初期リポジトリをクローンしてきて、中にある.openshiftディレクトリをherokuにDeployしているアプリにコピーしておく。 その後openshiftをremoteとして追加してpushする。内部ではPassengerが動いていてRackベースのアプリはconfig.ruを元に起動する。

# Template Repository Layout
tmp/               Temporary storage
public/            Content (images, CSS, etc. available to the public)
config.ru          This file is used by Rack-based servers to start the application.
.openshift/        Location for OpenShift specific files
    action_hooks/  See the Action Hooks documentation
    markers/       See the Markers section below

次にOpenShiftで動かすために変更した部分。

database.yml

production:
  dsn: <%= "#{ENV['OPENSHIFT_MYSQL_DB_URL']}/#{ENV['OPENSHIFT_APP_NAME']}" %>

Gemfile

# RubyGemsミラーがOpenShift内部にあってこっちのほうが早い
# https://developers.openshift.com/en/ruby-getting-started.html#_ruby_mirror
source 'http://mirror.ops.rhcloud.com/mirror/ruby/'

# 1.5.2でなければ動かない
gem 'rack', '1.5.2'

config.ru

# default_externalを直接指定しておかないとうまく動かない所がある。
# Railsを参考にしたけどこの辺のベストプラクティスよくわかってない。
Encoding.default_external = Encoding::UTF_8
Encoding.default_internal = Encoding::UTF_8

次に環境変数を設定する。人によっては不要かもしれない。

$ rhc env set RACK_ENV=production BUNDLE_WITHOUT=development:test:postgresql -a anewcomer

最後に、Passengerのhot deployに対応させておく。

$ touch .openshift/markers/hot_deploy

.openshiftにはこういう設定や、DeployやStart等のActionHookを置いてくことになる。

取り敢えずここで一旦remoteにpushしたらデプロイが実行されると思うので、 その後sshで接続してrakeタスクを実行してDBをセットアップして動作確認を行う。

$ rhc app ssh anewcomer

# $OPENSHIFT_REPO_DIRにデプロイされたアプリケーションのPathがセットされてる
> cd $OPENSHIFT_REPO_DIR
> bundle exec rake db:setup RACK_ENV=production

特に問題がなければこれで一旦初期状態のアプリが表示されていると思う。

Data Migration

データの移行にはtapsを使う。

$ gem i taps sqlite3 mysql pg

herokuはDBへのエンドポイントがあったがOpenShiftには多分無い。 接続したい場合にはrhcにport-forwardを行うコマンドがあるのでそれで一時的に接続できるようにする。

$ rhc port-forward anewcomer

Checking available ports ... done
Forwarding ports ...

To connect to a service running on OpenShift, use the Local address

Service Local                OpenShift
------- --------------- ---- ------------------
httpd   127.0.0.1:8080   =>  xx.xx.xx.xx:8080
mysql   127.0.0.1:3306   =>  xx.xx.xx.xx:3306
ruby    127.0.0.1:26226  =>  xx.xx.xx.xx:26226

Press CTRL-C to terminate port forwarding

別ターミナルでtapsのサーバーを立てる。

taps server 'mysql://username:password@127.0.0.1:3306/app_name?encoding=utf8' tapsuser tapspass

MySQLの接続情報は作成時に表示さていた情報。わからない場合はsshしてechoするかWebConsoleで確認できるかも。

あとはHerokuのPostgreSQLからpushする。

taps push 'postgres://username:password@xxx.xxx.xxx.xxx.compute-1.amazonaws.com:5432/dbname' http://tapsuser:tapspass@localhost:5000

これだけで異なるミドルウェア・PaaS間でのデータ移行が済んでしまうtapsは最高に便利。

Naked Domain

OpenShiftもHerokuと同じようにCNAMEでのカスタムドメイン設定しか出来ないので、aliasだけ設定しておく

$ rhc alias add anewcomer a-newcomer.com

あとはapex alias等の参照先を、最初に付与されたFQDN(anewcomer-daich.rhcloud.comとか)に設定すれば転送されるはず。

Action Hook

最後に、pushするたびに自動的にmigrationを実行させたいので実行権限付きのファイルを.openshift/action_hooks/deployに置く。

#!/bin/bash

echo "Starting deploy script"
cd $OPENSHIFT_REPO_DIR

bundle exec rake db:migrate RACK_ENV="production"

他にも色々なActionが用意されてるので大抵のことはカバーできそう。

終わり

結構調べながらやってたんだけどそこそこスムーズに移行できてよかった。 OpenShiftも個人でブログを動かすくらいにしか使っていない分の使い勝手は全く問題ないと思う。

ただ、ブログに対してアプリケーションを動かすこと自体がちょっとめんどくさくなってしまって今はGithub Pages + Jekyllで運用しているんだけど、こうやってちょっと頑張って移行した手前そのうち向こうのブログにも何か書いていきたい。