Wordpressの画像をS3+CloudFrontで配信する


環境

WordPress 4.8.3


AWS設定手順

IAM設定

まず、WordpressとAWSの連携に使うIAMユーザーを準備します
今回の手順ではバケット側のポリシーで権限付与するので
IAM側の権限設定は適当で良いです

準備したIAMユーザーの以下を控えておいてください
・ARN
・アクセスキーID
・シークレットアクセスキー

S3設定

次にS3にてWordpress用のバケットを用意し
バケットポリシーに以下を設定します

{  
    "Version": "2012-10-17",  
    "Statement": [  
        {  
            "Sid": "AllowBucketAccess",  
            "Effect": "Allow",  
            "Principal": {  
                "AWS": "arn:aws:iam::準備したIAMのARN"  
            },  
            "Action": [  
                "s3:GetBucketLocation",  
                "s3:ListBucket",  
                "s3:PutObject",  
                "s3:PutObjectAcl",  
                "s3:GetObject",  
                "s3:DeleteObject"  
            ],  
            "Resource": [  
                "arn:aws:s3:::対象のバケット/*",  
                "arn:aws:s3:::対象のバケット"  
            ]  
        }  
    ]  
}  

CloudFront設定

ユーザーにS3へ直接画像を取りに来させる事も可能なのですが
転送料金が結構高くなるのでCloudFront経由でS3に繋がせるようにします

まずloudFrontの設定画面にて「Create Distribution」をクリックします

次にWebの「Get Started」をクリックします。

「Origin Domain Name」にCloud Front経由にしたいS3バケットを指定します
テキストボックスに見えますが、クリックすると選択肢が表示されます
「Origin Domain Name」を選択すると、「Origin ID」にも勝手に値が入ります

上記入力したら下までスクロールして「Create Distribution」をクリックします

CloudFrontの一覧に戻りますので
先ほど作成したDistributionのStatusが『Deployed』になるのを待ちます

これでCloudFront経由でS3へアクセスできるようになりました
アクセスできるドメインは上図の「Domain Name」を参照してください

独自ドメインでアクセスしたい場合は上部メニューの
「Distribution Settings」より編集画面を開き
以下のように設定してください

Route 53設定

CloudFrontを独自ドメインで使う場合はDNS設定もしておきます

Wordpress設定

まずは普通にWordpressを構築します
(ここは手順割愛)

プラグイン:Amazon Web Services

プラグインの新規追加で『Amazon Web Services』を入れます

次にwp-config.phpにIAMのアクセスキーを設定します
(下記「AAA…」と「BBB…」は該当のものに書き換えてください)

define( 'DBI_AWS_ACCESS_KEY_ID', 'AAAAAAAAAAAAAAAAA' );  
define( 'DBI_AWS_SECRET_ACCESS_KEY', 'BBBBBBBBBBBBBBB' );  

これでWordpressとAWSの連携ができるようになります

プラグイン:WP Offload Media Lite

次にプラグインの新規追加で『WP Offload Media Lite』を入れます

インストール&有効化後、設定メニューに「Offload Media」が追加されるので
利用するバケットを指定します
左下の『Browse existing buckets』から選択するのが楽だと思います

バケット選択後、いくつか設定項目が出てきます
まず、デフォルトでは画像URLがS3直アクセスになってしまうので
「Custom Domain」をCloudFront経由のURLに変更します
(xxxxx.cloudfront.net または 指定した独自ドメイン)

サーバー側に画像ファイルを残したくない場合は
『Remove Files From Server』をONにしておきます。

※注意
上図Warningにも出てますが、もしかしたらプラグインによってはサーバー内に
画像ファイルを残しておかないと正常に動かないものもあるかもしれません
その場合はOFFにするかプラグイン側をどうにかするかしてください

既存の画像ファイルをS3に移行したい場合

こちらを参考にしました
https://php-java.com/archives/2228

まず既存画像ファイルをS3にアップロードします
階層は「wp-content/uploads/2018/・・・」のようにします

次にSQLでDBを更新します
SQL内の以下部分は各環境に合わせて書き替えてください
webserver_hostname:WEBサーバーのホスト名
cloudfront_hostname:CloudFrontのホスト名

以下、S3のリージョンは東京である前提にしています
東京でない場合はS3のホスト名も該当のものに書き換えてください

まず記事内の画像URL差し替え

UPDATE wp_posts  
SET post_content = REPLACE(post_content, "https://webserver_hostname/wp-content/uploads/", "https://cloudfront_hostname/wp-content/uploads/");  

次にアイキャッチの画像URL差し替え

UPDATE wp_posts  
SET guid = REPLACE(guid, "https://webserver_hostname/wp-content/uploads/", "https://cloudfront_hostname/wp-content/uploads/");  

次にmeta情報に各画像ファイルのS3の情報を追加します
(UPDATEではなくINSERT)

以下のSELECT文にてINSERT文を生成できるので
生成したINSERT文を実行すれば完了です
SQL内の s3_bucket_name の部分は対象バケット名に書き換えてください
また、S3バケットが東京リージョンでない場合はap-northeast-1の部分も書き換えてください

SELECT  CONCAT('insert into wp_postmeta(post_id, meta_key, meta_value) values('  
, post_id, ', \'amazonS3_info\', \'a:4:{s:8:\"provider\";s:3:\"aws\";s:6:\"region\";s:14:\"ap-northeast-1\";s:6:\"bucket\";s:14:\"s3_bucket_name\";s:3:\"key\";s:',length(meta_value) + 19,':\"wp-content/uploads/', meta_value, '\";}\');'  
) AS record from wp_postmeta where meta_key = '_wp_attached_file';  

Wordpressのバージョン等によってはINSERT文を少し変えないといけないかもしれません
INSERTすべき文を正確に知るためには一度Wordpress上で新規画像を登録して
wp_postmetaテーブルに追加されたレコードを確認するのが一番だと思います