Middlemanで作ったサイトをAmazon S3にデプロイする手順

middleman

Middlemanで生成したサイトをAmazon S3にデプロイする手順をご紹介します。既に同じような記事はありますが、ちょっと古かったり抜け落ちたりしていることが多いので、今回改めて書いてみました。

なお、そもそもS3でのバケットの作成や独自ドメインで使う設定方法を知りたい方は下の記事をご覧下さい。

ムームードメインで取得した独自ドメインをAmazon S3に適用する手順

おすすめはmiddleman-s3_sync

S3にデプロイするならmiddleman-s3_syncというプラグインをおすすめします。Middlemanのデプロイで最も使われているのは、middleman-deployというプラグインなのですが、かなり原始的なものでサイトを更新するたびに全てのファイルをアップロードします。middleman-s3_syncは変更されたファイルのみ更新してくれますし、処理中のプログレス表示が綺麗で見やすいです。

middleman-s3_syncの導入方法

gemのインストール

Gemfileに以下を記載し、コマンドラインでbundle installを実行します。

1
2
gem 'middleman-s3_sync', "~> 3.0"
gem 'mime-types'

Middlemanのバージョン3系を使っている場合は、上のように"~> 3.0"と書いて、middleman-s3_syncも3系が使われるようにする必要があります。既にバージョン4系(現時点ではベータ段階)を使っている場合は、バージョン指定無しでOKです。

2行目のgem 'mime-types'が無いと、後でmiddleman s3_syncというコマンドを実行する時に下のエラーが出ます。

1
uninitialized constant Fog::Storage::MIME (NameError)

エラーログの全量はこちら

S3の認証情報の記載

Middlemanのプロジェクトのルートディレクトリに.s3_syncというファイルを作成し、以下を記載します。YOURACCESSKEYyourSeCretKeyexample.comの部分はご自身のS3の対象のバケットのものに変更してください。

1
2
3
4
---
aws_access_key_id: YOURACCESSKEY
aws_secret_access_key: yourSeCretKey
bucket: example.com

実はこちらは、config.rbに直接書くこともできます。ただ、センシティブな情報であるため、上のように.s3_syncに書き、このファイルをgitの管理から外すことをお勧めします。.gitignoreに以下を追加します。

1
/.s3_sync

config.rbの設定

以下のように追記し、s3_syncをactivateします。

1
2
3
activate :s3_sync do |s3_sync|
  s3_sync.region = 'ap-northeast-1'
end

前の手順で.s3_syncを作成していれば、上のようにリージョンの指定だけでOKです。ap-northeast-1は東京リージョンの場合ですので、ご自身が利用するリージョンのものに修正してください。デフォルトのリージョン(おそらくus-west-1)を使う場合は、単に一行activate :s3_syncと書けばよいようです。

S3側のバケットポリシーの設定

S3の管理画面から対象のバケットのプロパティを開く

S3の管理画面step1

アクセス許可をクリック

S3の管理画面step2

「バケットポリシーの編集」をクリック

バケットポリシーがまだ存在しない場合は、「バケットポリシーの追加」となっています。

S3の管理画面step3

ポリシーを入力

このような入力フォームに入力し、「保存」をクリックします。

S3の管理画面step4

入力するテキストは以下です。example.comはご自身が使うバケット名に変えて下さい。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
{
	"Version": "2012-10-17",
	"Statement": [
		{
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:*",
			"Resource": "arn:aws:s3:::example.com"
		},
		{
			"Effect": "Allow",
			"Principal": "*",
			"Action": "s3:*",
			"Resource": "arn:aws:s3:::example.com/*"
		}
	]
}

インデックスドキュメントとエラードキュメントの設定

S3では「インデックスドキュメント」と「エラードキュメント」をどのファイルにするか指定できます。

インデックスドキュメント

ルートURLにアクセスされた時に表示するhtmlファイル。通常はindex.html

エラードキュメント

存在しないURLにアクセスされた時に表示するhtmlファイル。

インデックスドキュメントは、middelmanの場合でも通常index.htmlが生成されているのであまり考える必要はないと思います。エラードキュメントは、ご自身のMiddlemanの設定で生成されたファイルを指定してあげる必要があります。

私の場合は、エラードキュメントはsourceディレクトリ直下に以下のような404.slimというファイルで生成しています。(ご自身の好きなpathでOK)

1
2
3
4
5
6
7
- content_for :title, "このURLに記事はありません。"
article.article
  p
    |このURLに記事はありません。5秒後に自動的にTopページに行きます。反応しない場合は下のボタンを押してください。
  meta http-equiv="refresh" content="5;URL=/"
  p style="text-align:center;"
    = link_to "Topページへ", "/", class: "btn"

S3側の設定する場所は、対象のバケットのプロパティから「静的ウェブホスティング」をクリックすると表示されます。

directory_indexesを有効にしている場合は、以下の画像のように404/index.htmlというpathになります。していない場合は、404.htmlとなります。

手順のstep5

デプロイが終わった後にでも、存在しないURLにわざとアクセスしてみて、指定したファイルが表示されるか確認してみてください。

このエラードキュメントの設定は、必須事項というわけではないので、手間と感じる場合はしなくても大丈夫です。ただ、この機能はS3が提供してくれてる便利な機能なので、利用したいところです。

デプロイの実行

まず、以下を実行しサイトを生成します。

1
middleman build

以下でデプロイを実行します。

1
middleman s3_sync

正常に終了すれば、大体以下のように表示されます。(通常もっと多いです。)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ middleman s3_sync
     s3_sync  Let's see if there's work to be done...
Processing sitemap |Time: 00:00:01 | ========================================================================== | Time: 00:00:01
Processing remote files |Time: 00:00:00 | ===================================================================== | Time: 00:00:00
     s3_sync  Ready to apply updates to example.com.
     s3_sync  Creating feed.xml
     s3_sync  Creating images/bg_line-60f9363a.svg
     s3_sync  Creating images/logo-880728ed.png
     s3_sync  Creating images/quote-218844a0.gif
     s3_sync  Creating images/rank1_mini-3b28d88c.gif
     s3_sync  Creating images/rank2_mini-6d4a76f4.gif
     s3_sync  Creating images/rank3_mini-f13e8010.gif
     s3_sync  Creating tags/perl/index.html
     s3_sync  Creating 2015/12/index.html
     s3_sync  Creating index.html

エラーが発生した場合

もし下のようなエラーが発生した場合、

1
/Users/hoge/.rbenv/versions/2.1.2/lib/ruby/2.1.0/openssl/buffering.rb:383:in `syswrite_nonblock': Bad address (Errno::EFAULT) (Excon::Errors::SocketError)

エラーの全量はこちら

以下のようにopensslを再インストールすると治る場合があります。

1
2
3
sudo brew update
sudo brew uninstall --force openssl
sudo brew install openssl

現状私の端末でインストールされているのはopenssl-1.0.2e.yosemite.bottle.tar.gzというバージョンです。

変更すると差分だけデプロイしてくれる

何かファイルを変更したり、削除してみてくてください。

そして、middlean buildmiddleman s3_syncを実行すると、

1
2
3
4
5
6
7
8
9
$ middleman s3_sync
     s3_sync  Let's see if there's work to be done...
Processing sitemap |Time: 00:00:02 | ========================================================================== | Time: 00:00:02
Processing remote files |Time: 00:00:00 | ===================================================================== | Time: 00:00:00
     s3_sync  Ready to apply updates to xn--u9j3gqe3a6cwa2i7453a79t.com.
     s3_sync  Creating company-ranking-for-cobol-programmers-salary/index.html
     s3_sync  Updating tags/objective-c/index.html
     s3_sync  Updating 2015/12/index.html
     s3_sync  Deleting company-ranking-for-salary-of-perl-programmer/index.html

こんな感じで、全部アップロードするのではなく、必要に応じて、追加、更新、削除をしてくれます。何百ページものコンテンツ量になってきた時、通常はデプロイにすごく時間がかかってしまうのですが、middleman-s3_syncを使っていれば最小限のデプロイ時間で済みます。

まとめ

いかがでしたでしょうか。MiddlemanはS3と非常に相性がよいことがおわかりいただけるのではないかと思います。S3は金額も月10円レベルと非常にお安いので、もうMiddlemanとS3の組み合わせは、手放せなくなりますね。

バージョン情報

  • middleman (3.4.0)
  • middleman-s3_sync (3.3.4)
  • mime-types (2.6.2)

参考

羊毛や小麦