WP Offload Media LiteプラグインでWordPressの画像をCloudFront+S3から配信
先日、WordPressサイトをレンタルサーバーからAWSに移行する案件がありました。
WebサーバーはEC2、DBサーバーはRDSを使用、画像をS3に保存し、CloudFrontから配信するようにしました。
WordPressの画像をS3+CloudFrontから配信する方法と、WP Offload Media Liteプラグインの使い方については、以下の記事など参考にしました。
ありがとうございます。
・Wordpressの画像をS3+CloudFrontで配信する – Nonsense J
https://nonsensej.xyz/articles/wp/1772
・WordPressの画像ファイルをS3に保存する(メディア機能連携) – つかびーの技術日記
http://tech-blog.tsukaby.com/archives/972
基本的には、上記の参考記事のとおりの設定手順で問題ないのですが、ここでは、僕がつまづいた箇所、気になった箇所について記載します。
- 作業前にバックアップを取得
- 「Access Denied Bucket」のエラー
- S3バケットへのアクセス権限はアクセスキーではなくIAMロールで
- プラグインのObject Versioning設定はOFFに
- 過去にメディアライブラリに登録した画像の扱い
- CloudFrontキャッシュクリアプラグインの導入
Webサイトと構成図
ここに記載するWebサイトの情報は、次のとおりとします。
- サイトURL: https://example.jp/
- CloudFront配信のURL: https://static.example.jp/
- S3バケット名: static-example
構成図は次のとおりです。
作業前にバックアップを取得
この作業に限った話ではありませんが、
設定変更作業を始める前に、バックアップをとっておき、万一作業ミスがあっても、作業前の状態に戻せるようにしましょう。
とくに、WordPress DBデータの過去記事内の画像参照URLをCloudFront向けに書き換える操作は非常に危険で、ミスがあると、Webページで画像が全く表示されなくなることもあり得ます。
DBデータは、RDSを使用しているならスナップショットを取得します。
Point in time recoveryでリカバリーできる、ということであれば、スナップショットは不要でしょう。
RDSを使用せずにEC2上でMySQLサーバーを稼働しているのなら、phpMyAdminやWP-DBManagerプラグインでDBデータのバックアップを取得(ダンプ)しましょう。
あるいは、EBSボリュームのスナップショットを取得するほうが簡単かもしれません。
「Access Denied Bucket」のエラー
WP Offload Media Liteプラグインを使用する場合、S3バケットの設定で、「ブロックパブリックアクセス」を解除する必要があります。
デフォルトの有効な状態から解除しないと、WP Offload Media LiteプラグインでS3バケット名を設定したときに、以下のような「Access Denied Bucket」のエラーとなります。
この点については、WP Offload Media Liteプラグインオフィシャルのクイックスタートガイドに説明があります。
(参考)
・Offload Media Lite, Amazon S3 Quick Start Guide
https://deliciousbrains.com/wp-offload-media/doc/amazon-s3-quick-start-guide/
「5. Configure WP Offload Media to offload newly uploaded media to an Amazon S3 bucket」の箇所。
なお、S3バケットの設定で「ブロックパブリックアクセス」を解除して公開状態としても、CloudFrontのディストリビューション設定において「Restrict Bucket Access」を有効にしてS3バケットに反映させれば、結果的に、パブリックアクセスできない状態(=閲覧ユーザーからはS3バケットに直接アクセスできず、CloudFront経由でのアクセスのみ許可される)となります。
CloudFrontディストリビューションの「Origins and Origin Group」設定。
このとき、S3バケットのバケットポリシーは以下のようになっており、Origin Access Identityによって、アクセスが制限されていることがわかります。
{ "Version": "2008-10-17", "Id": "PolicyForCloudFrontPrivateContent", "Statement": [ { "Sid": "1", "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity <Distribution ID>" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::static-example/*" } ] }
S3バケットへのアクセス権限はアクセスキーではなくIAMロールで
プラグインの設定「Storage Provider」では、オブジェクトストレージのサービス「Amazon S3」とアクセス設定方法を選択しますが、ここは、IAMロールを利用した
「My server is on Amazon Web Services and I’d like to use IAM Roles」
とするのがよいでしょう。
このためには、プラグイン設定の前に、S3バケットへのアクセス権限を付与したIAMポリシーを、EC2に適用しているIAMロールにアタッチしておきます。
「サーバー上には極力アクセスキー情報を保存せず、IAMロールを使用する」のは、AWSも推奨するEC2運用の定石ですね。
Webサーバーとして、AWS以外のクラウドサービスやVPSサーバーを使用する場合は、IAMロールのような機能はありませんから、wp-config.phpにアクセスキー情報を記載するとよいでしょう。
プラグインのObject Versioning設定はOFFに
プラグインのバージョニング機能がデフォルトで有効になっており、この場合、パスに日時を表す数字7桁のディレクトリ1階層が追加となります。
(バージョニングON時)
https://static.example.jp/wp-content/uploads/2020/06/29182909/test.jpg
(バージョニングOFF時)
https://static.example.jp/wp-content/uploads/2020/05/test.jpg
不要であれば、「Object Versioning」をOFFにします。
過去にメディアライブラリに登録した画像の扱い
WP Offload Media Liteプラグインをインストール設定し、サーバー上に保存されている既存の画像をS3バケットにアップロードしても、過去にWordPressのメディアライブラリに登録した画像は、S3バケットに完全には対応していません。
具体的には、次のような制限事項があります。
- 画像をメディアから削除しても、S3上の画像ファイルが削除されない。
- 記事作成時に「メディアを追加」で画像を貼り付けたとき、画像のURLパスが、CloudFront経由のものにならない。
この制限事項を解消するため、DBのwp_postmetaテーブルに、S3バケットに関する情報を追加(INSERT)します。
(2021.2.12追記)
※WP Offload Media 2.3以降では、メタデータは wp_as3cf_items テーブルに保存するようになったそうですが、wp_postmeta テーブルへの追加でも、うまく動作するようです。そのうち動作しなくなるかも。
(2021.2.12追記ここまで)
実行するSQL insert文は、以下の参考記事に記載のとおりです。
(参考)
・yukihirai0505/wp_offload_s3_migration.md – GitHub
https://gist.github.com/yukihirai0505/fdca5530fc4bcb32b1072ffaca789ffd
他の記事では、
「SQL INSERT文を生成して、それらをすべて実行する」
という記載も見受けられますが、画像ファイルが大量にあるときはSQL文も大量で、それを1行ずつ実行するのは難しいと思います。
それなら、最初からINSERT文を実行するようなSQL文を使ったほうが簡単でしょう。
※僕もphpMyAdminでCSVに落とすなどいろいろ試したのですが、うまく実行できませんでした。やり方が下手だったのかもしれませんが。
SQL文は、phpMyAdminで実行するのでも、サーバー上でmysqlコマンドから実行するのでも、どちらでもよいでしょう。
SQL INSERT文の中の、、、
s:16:"your-bucket-name";
↑ここは、S3バケット名と、バケット名の文字数に合わせましょう。
たとえば、バケット名が static-example であれば、以下のようになります。
(2021.2.12追記)
ここは、CloudFrontから配信するドメイン名(CNAME)とします。
今回の例では、static.example.jp で、17文字ですね。
s:17:"static.example.jp";
(2021.2.12追記ここまで)
同様に、「メディア」のパスの部分、、、
LENGTH('wp-content/uploads/'), ... ':"wp-content/uploads/',
↑ここも、「メディア」のパスを変更したときは、それに合わせて変更します。
https://static.example.jp/img/
とするのであれば、以下のようにします。
LENGTH('img/'), ... ':"img/',
CloudFrontキャッシュクリアプラグインの導入
(2021.2.3 この項修正しました。)
WordPressで記事を編集する担当者自身がCloudFrontのキャッシュクリアを実行できるよう、プラグインを導入します。
これについては、当初は、
「画像を更新する際は、必ずファイル名を変更する運用にすればキャッシュクリアは不要では?」
と提案しました。
ですが、運用サイドから以下のようなご要望があるとのことで、キャッシュクリアする手段が必要となりました。
- WordPressのメディアライブラリに登録せずに、S3クライアントから直接S3にアップロードする画像もある。
- 画像をアップしてWebでの表示を確認してから、画像を修正したいことがわりとよくある。
- そのときに、キャッシュの期限切れを待たずにすぐに確認したい。
- 画像を更新するときにファイル名を変更すると、記事内のURLパスも変更しなければならないが、それは手間がかかる。
そこで、CloudFrontのキャッシュクリアには課金が発生することをご説明したうえで、WordPressのキャッシュクリアプラグイン「C3 Cloudfront Cache Controller」を導入することにしました。
・WordPressプラグイン C3 Cloudfront Cache Controller
https://ja.wordpress.org/plugins/c3-cloudfront-clear-cache/
C3 Cloudfront Cache Controller は、本来、記事を公開もしくは公開した記事を更新したときに、関連するURLのキャッシュを削除する機能ですが、ここでは、「Flush All Cache」ボタンでCloudFrontにあるすべてのキャッシュを削除することを想定しています。
このプラグインにアクセスを許可するIAMポリシーについては、以下の記事を参考に、対象とするCloudFrontディストリビューションを限定するとよいでしょう。
・WordPressプラグインのC3 Cloudfront Cache ControllerのIAMの設定を少しだけ厳しくする – Simple is Beautiful
https://blog.kozakana.net/2020/02/aws-iam-settings-for-c3-wordpress-plugin/
※このプラグインは残念ながら、WP Offload Media LiteプラグインのようにIAMロールには対応していません。IAMポリシーをアタッチしたIAMユーザーのアクセスキーを設定しないと、キャッシュクリアが動作しないようになっています。
まとめ
WordPress on AWSにおいて、画像をS3に保存し、CloudFrontから配信する際の、WP Offload Media Liteプラグインの設定、使い方に関して、自分がつまづいた点や気になったことについて記載しました。
画像やその他の静的ファイルを、CloudFront+S3から配信し、WebリクエストをEC2から外部に逃がすことで、EC2のサーバー負荷を下げることができ、サーバーのコストダウンにつながります。
なお、今回AWSに移行、対応したWebサイトは、株式会社PLUS様が運営する「エピリノ」です。
・エピリノ
https://epilino.jp/
移行により、特にスマホでの画像の表示が速くなったとうかがっています。
掲載許可をいただき、ありがとうございます!