Wordpress + Heroku + PostgreSQL + Amazon S3 = ¥0 / 無料でサイト運営

Shunsuke Sawada

WordpressをHerokuで運営すると何かと楽だなぁと思ってやってみた。タダだし。
でも実際はけっこうハマったりもした。書いておかないと確実に忘れる。

2015/06/01
Herokuの新プラン発表で18時間だけ無料になってしまいました。
Herokuが無料でなくなる日 | Workabroad.jp
24時間稼働は$7かかります。
  
  
2015/02/20追記
パーマリンクを変更しても、しばらくするとまた元に戻るという現象が起こりました。
mod rewriteの設定をすれば直るようです。
http://blog.mah-lab.com/2013/05/01/wordpress-on-heroku/
  
  
2015/02/02追記
wp-configの設定が足りなかったので修正
  
  
最初は自力でやろうかなと思ったけど、途中でハマりだしたので他の人の力を借りようということに。
2015年1月現在では Wordpress 4.1 になっている。
wordpress-heroku

Screen Shot 2015-01-30 at 3.34.45 PM

ローカル開発環境

まずはローカル開発環境。
面倒だけど一回やってしまえば後のデプロイは楽なはず。
Rails + Heroku コンビネーションが多いから同じようにデプロイできるのは嬉しい。

ダウンロードしてフォルダの名前変える。

1
2
$ git clone git://github.com/mhoofman/wordpress-heroku.git
$ mv wordpress-heroku my-wordpress

Git repository を作って、リモートも登録しましょう。
Gitの流れは前にRailsバージョンで書いたのでこちらを参照。
herokuでRailsアプリを公開する手順をゆっくり丁寧に。 | Workabroad.jp

PostgreSQL

Wordpressは普通MySQLだけど、さっきのレポジトリからダウンロードしたものには既にプラグインがインストールしてあって、PostgreSQLが使えるようになっている。
プラグインはこちら。
WordPress › PostgreSQL for WordPress (PG4WP) « WordPress Plugins
※Wordpressの管理画面から操作するような普通のプラグインではない。

なので、PostgreSQLのDBつくります。

1
2
3
4
5
6
7
$ sudo -u postgres psql
DB作成
postgres=# create database my-wordpress owner yourname;
確認
postgres=# \l
終了
postgres=# \q

Apacheの設定と環境変数

最終的にHerokuにデプロイするので、DBの接続情報を環境変数に登録しておく。
1つのIPで複数のプロジェクトを開発してるから、VirtualHostで切り替える。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
Apache設定ファイルの編集
$ sudo vi /etc/httpd/conf/httpd.conf

↓

<VirtualHost *:80>
    ServerName     dev.yoursite.com
    DocumentRoot   "/var/www/html/my-wordpress"
    setEnv WP_ENV development #必要だったら
    setEnv WP_DB_URL xxxxxxxxxxxxxxxxxxxxxxxxxx
    setEnv WP_DB_NAME xxxxxxxxx
    setEnv WP_DB_USER xxxxxxxxx
    setEnv WP_DB_PASSWORD xxxxxxxxx
</VirtualHost>

setEnvで環境変数を登録しておいて、
PHP側では getenv('WP_DB_NAME') のように使う。

DBのURLはこんな書式。
// postgres://USER_NAME:PASSWORD@HOST:5432/DB_NAME
  
Apache起動

1
2
$ service httpd start
$ service httpd restart 起動してたら再起動

  
ブラウザでdev.yoursite.comにアクセスした時に、
そのIPに行ってもらう必要があるからHost設定をする。
hoster
Mac使ってたら Hoster が便利。
http://www.redwinder.com/macapp/hoster/

Wordpressの設定

先ほど追加した環境変数を設定ファイルに反映させる。
WP_DB_HOSTはローカルだとだいたいlocalhost、HerokuだとDB追加した時に値を取得できる。

wp-config.php

php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

// ** Heroku Postgres settings - from Heroku Environment ** //
$db = parse_url(getenv('WP_DB_NAME'));

/** MySQL database username */
define('DB_USER', getenv('WP_DB_USER'));

/** MySQL database password */
define('DB_PASSWORD', getenv('WP_DB_PASSWORD'));

/** MySQL hostname */
define('DB_HOST', getenv('WP_DB_HOST'));

?>

  
省略しますが、こちらも環境変数にしましょう。
便利なジェネレータはこちら

php
1
2
3
4
5
6
7
8
define('AUTH_KEY',         'xxxxxx');
define('SECURE_AUTH_KEY',  'xxxxxxxx');
define('LOGGED_IN_KEY',    'xxxxxxxx');
define('NONCE_KEY',        'xxxxxxxx');
define('AUTH_SALT',        'xxxxxxxx');
define('SECURE_AUTH_SALT', 'xxxxxxxx');
define('LOGGED_IN_SALT',   'xxxxxxxx');
define('NONCE_SALT',       'xxxxxxxx');

   
ちなみに、ローカル開発環境と本番環境のconfigを分けたいこともある。
そんな時はこんな感じ。環境変数 WP_ENV をセットしておくことを忘れずに。
herokuの方には、 heroku config:set WP_ENV=production としておく。
参考:Multi Environment WordPress wp-config.php

php
1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
if ( getenv('WP_ENV') === "development" ) {

    define('WP_HOME','http://dev.your_site.com');
    define('WP_SITEURL','http://dev.your_site.com');

} elseif ( getenv('WP_ENV') === "production" ) {

    define('WP_HOME','http://your_site.com');
    define('WP_SITEURL','http://your_site.com');

}
?>

  
wp-config.php 13行目
$_ENV['DATABASE_URL']getenv('WP_DB_NAME') に入れ替えた。

php
1
2
3
4
5
6
<?php
  if (preg_match('/localhost/', getenv('WP_DB_NAME'))) {
    preg_match('/(.*)\/wp-.*\/(\w*\.php)+$/', $_SERVER['REQUEST_URI'], $path);
    return ("http://" . $_SERVER['HTTP_HOST'] . $path[1]);
  }
?>

  
これでブラウザからアクセスすると、Wordpressの初期設定画面が表示されるはず。
この例ではdev.my-wordpress.comです。(Hosterの設定)

Amazon S3

Herokuを前提にしているので、画像の保存先を別に設ける必要があります。
RailsでいつもやっているようにAmazon S3に保存したいところです。

Bucket
Amason S3にいって、適当な名前のBucketを作ってください。
Bucket Policyの設定もしておきましょう。
Policyのサンプルはこちらのページで。
https://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html
Granting Read-Only Permission to an Anonymous User でいいと思います。
   
IAM
Wordpressに画像をアップロードする権限を与えなければいけないので、
IAMに行って適当にユーザーを作って、S3に関する権限を与えます。
Key と Secret が取得できたら、Wordpress内で使うので保存しておきましょう。
  
WP Read-Only
wordpress-herokuにはS3を使うプラグインが予め入ってます。
※デフォルトではアクティブでないので、Plugins / Installed Plugins にいってONにする。
プラグインはこちら。
WordPress › WP Read-Only « WordPress Plugins

Settings / WPRO Setting で先ほどのKeyとSecretを入力したら完了。
ちょっとハマったのが、Regionの選択。
何らかの理由でSydneyのRegionとかを使っている場合は、WPROのRegionセレクトオプションに存在しません。

WPRO Plugin Settings ‹ Washoku Lovers — WordPress

  
だから自分で付け加えた。
Region一覧はAmazonの公式から。
http://docs.aws.amazon.com/general/latest/gr/rande.html#s3_region

wpro.php 350行目あたり

php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<select name="wpro-aws-endpoint" id="wpro-aws-endpoint">
<?php
    $aws_regions = array(
        's3.amazonaws.com' => 'US East Region (Standard)',
        's3-us-west-2.amazonaws.com' => 'US West (Oregon) Region',
        's3-us-west-1.amazonaws.com' => 'US West (Northern California) Region',
        's3-eu-west-1.amazonaws.com' => 'EU (Ireland) Region',
        's3-ap-southeast-1.amazonaws.com' => 'Asia Pacific (Singapore) Region',
        's3-ap-southeast-2.amazonaws.com' => 'Asia Pacific (Sydney) Region', //追加した
        's3-ap-northeast-1.amazonaws.com' => 'Asia Pacific (Tokyo) Region',
        's3-sa-east-1.amazonaws.com' => 'South America (Sao Paulo) Region'
    );
    // Endpoints comes from http://docs.amazonwebservices.com/general/latest/gr/rande.html

    foreach ($aws_regions as $endpoint => $endpoint_name) {
        echo ('<option value="' . $endpoint . '"');
        if ($endpoint == get_option('wpro-aws-endpoint')) {
            echo(' selected="selected"');
        }
        echo ('>' . $endpoint_name . '</option>');
    }
?>
</select> 

Herokuの設定

ローカル環境でWordpressが動きだしたので、次はHeroku。
普通にアプリ作成して、Addonを追加。
PostgreSQLとSendGridを使います。

PostgreSQLの情報をHerokuの環境設定にセット。

1
2
3
4
5
$ heroku config:set WP_DB_URL=xxxxxxx
$ heroku config:set WP_DB_NAME=xxxxxxx
$ heroku config:set WP_DB_USER=xxxxxxx
$ heroku config:set WP_DB_PASSWORD=xxxxxxx
$ heroku config:set WP_DB_HOST=xxxxxxx

SendgridのIDとパスワードも取得。

1
2
3
4
$ heroku config
↓
SENDGRID_PASSWORD:           xxxxxxxx
SENDGRID_USERNAME:           [email protected]

取得できたらローカルのWordpressに戻って、Settings / SendGrid Settings に保存しておきます。

今回はやってないけどMandrillでやる方法も見つけた。
http://www.andrewgertig.com/2013/05/set-up-wordpress-on-heroku
Mandrillの方が無料で送れるメールの数は多いはず。

Composer

このままデプロイしても確かに動くんだけど、画像をアップロードした時に、サムネイル画像が生成されない。オリジナル画像しか保存されなくて、記事に挿入すると「でか!」てなります。
それはGDがないから。

Wordpressのルートに conposer.json をつくってデプロイする必要がある。
HerokuのPHP拡張リストはこちら。
https://devcenter.heroku.com/articles/php-support

internal identifier に ext- をつけるのがルールらしい。

composer.json

1
2
3
4
5
6
7
{
  "require": {
    "php": "~5.6.0",
    "ext-gd": "*",
    "ext-mbstring": "*"
  }
}

Composerはこちら
https://getcomposer.org/

Herokuドキュメントにはローカルにイントールしてどうのこうのと書いてあるけど、
composer.jsonをルートに置いてデプロイするだけで一応動く。

あんまり関係ないけど、
Resize images before upload というWordpressのプラグインは結構良かったりする。アップロードする前に画像をリサイズしてくれるので、待ち時間が早くなる。6MBの画像をサーバーに送る必要なんてないもんね。

デプロイ

さーて。やっとHerokuにPushしましょ。
ローカルでGit commitしておいて、

1
$ git push heroku master

ファイル数多いから最初は時間かかるかも。
これでHerokuでWordpressが動くと思います。

S3も初年度無料だし、HerokuもPostgresSQL10000行まで無料。
カスタムドメインで運用する場合は多分 Route53 の料金がかかるけど全然大したことない。

Herokuのカスタムドメインの設定はこちら。
heroku で 独自ドメインを使う際の最善策を考えた | Workabroad.jp

なによりサーバーをあんまり意識しなくていいのは素敵だね。

参考

HerokuにWorpPressをPostgreSQLで構築する
WordPressのブログをherokuで立ち上げて、何かメリットあるの? | mah365
  

775
Shunsuke Sawada

おすすめの記事

justhostがハッキングされてる件
Wordpressのアップロード作業を楽にする
qTranslateで Hide Untranslated Content オプションがうまく動かなくなった場合の対処