つかびーの技術日記

(情報)工学修士, 元SIer SE, 現Web系 SEの技術blogです。Scala, Java, JS, TS, Python, Ruby, AWS, GCPあたりが好きです。

WordPressの画像ファイルをS3に保存する(メディア機能連携)

      2015/06/25

このblogは2015/6現在、Wordpressで書いています。

画像表示はWordpressのメディア機能を使っています。この機能を使うとWordpressが動いてるサーバ内のwp-contents/uploadsディレクトリ内に画像を保存し、その画像を記事内表示できるようになります。

今回はこの画像をサーバ内ではなく、AWS S3に保存しようという記事です。後半は移行作業の話が出てくるので少し玄人向け(SQLへの理解が必要)です。

S3へ保存する理由

多分ほとんどの場合、S3へ保存しないでも良いと思います。普通にサーバ内保存で事足ります。ただ、以下のようなケースでは必要になってくるかと思います。

  • WordPressが動くサーバを複数台で構成(+LB)していて、どれか1台にだけ画像ファイルが保存されると困るケース
  • WordPressをdocker containerとして動かし、Immutableを実現しているので、画像ファイルが消えると困るケース

S3へ保存するプラグイン

WordPressメディアへ画像をアップロードすると自動的にS3へ保存する・・・。

自前で同期するスクリプトを書いたりしても良いですが、これを実現するプラグインがあります。

他にもいくつかあるようですが、この2つのどちらかが良いと思います。

Amazon S3 and Cloudfrontは今回自分で利用して上手く行っていますし、公式上での評価が高いです。

Nephila clavataは日本人が開発しており、解説サイトもあります。最近もアップデートされました。また後述する移行の部分の話にあるように、Nephilaの方が一部の機能が使えて良いです。

今回はAmazon S3 and Cloudfront pluginを利用したので、こちらで解説します。

Amazon S3 and Cloudfront pluginの設定

実はこれについては詳しく解説されているサイトが既にあります。

AWS CloudFrontを使ってWordPressのメディアファイルだけS3に配置する

基本こちらに従えば良いです。一応、このページでも簡単に解説します。

おおまかな手順は以下の通りです。

  1. Plugin管理ページからAmazon Web Servicesプラグインをインストールする(以下のプラグインの前提になってます)
  2. Plugin管理ページからAmazon S3 Cloud Frontプラグインをインストールする
  3. WordPress管理画面にAWSというリンクが表示されるので、設定ページへ飛ぶ
  4. AWSのAccess Key IDとSecret Access Keyを登録する(セキュリティを気にする場合はwp_configに書きましょう)
  5. Amazon S3 Cloud Frontの設定ページへ飛ぶ
  6. 画像ファイルの保存先であるバケットを選択する
    (自分の場合は画像はCloudFrontを通して配布する予定だったので”CloudFront or custom domain”を選択してCloudFront用に作成しておいたdomainである”resources.tech-blog.tsukaby.com”を入力しました。)

使ってみる(テスト)

この状態でメディア機能を使って画像をwordpressにアップロードすると、S3に画像が保存されるとともに、そこへのリンクが貼られるはずです。

試しにやってみるとこんな感じになります。

メディアライブラリ_‹_つかびーの技術日記_—_WordPressURLの部分に注目していただきたいのですが、通常ここはwp-contents/uploads/…となるはずですが、先ほど設定したresoruces.tech-blog.tsukaby.comになっています。自分はcustom domainを入れているのでこうなりますが、バケットを選択した人はそのバケットのURLになっていると思います。

S3の方を見てみると

S3_Management_Consoleこのように正しく格納されていることがわかります。

当然ですが、上記のプラグインが画像ファイルをS3にputするので、プラグインで設定したAWSのIDに対してS3の参照・登録権限が無いとうまくいきません。IAM調整しましょう。

過去ファイル移行の問題

上記の設定でうまくいきます。これでWordpressを複数台で分散構築してようが、Wordpressサーバを作り直ししようが、画像まわりは問題が無くなります。

ただ、プラグインを途中から使い始めた人は過去の画像データについて考慮する必要があります。

Amazon S3 CloudFrontプラグインは過去の画像ファイルまでS3に保存してくれる、というようなことはしてくれません。過去の画像ファイルへのパスは従来通りwp-contents/uploadsへのリンクとなっています。

ですので完璧にS3へデータ移行するのであればDB上のデータを操作する必要があります。

ここでもう無理だわ、と思った人は素直にNephila clavataを使うと良いと思います。こちらは試していませんが、どうやら過去のデータにも対応しているようです。(過去データにアクセスがあった時点でwp-contents/uploadsに保存されているものの場合、自動で移行してくれる。っぽい)

Amazon S3 CloudFrontプラグインも一応過去データに対応するようですが、それはProfessionalプラン?だとか別の何かが必要なようです。

 過去ファイルの移行

上記の問題があるので、ここからは手動で過去データの移行を行います。

まず、wp-contents/uploadsにあるファイルを全てS3上に移動します。

これは単にwp-contentsフォルダごとごっそりaws s3 cpするなりして移動するだけなので簡単かと思います。問題はDBの方です。

WordPressはMySQL DBにデータを保存します。いくつかテーブルがありますが、重要なのは以下です。

  • wp_posts
  • wp_postmeta

wp_postsはpostデータを格納するテーブルです。WordPressでは記事のテキストだけでなく、メディア機能でUploadした画像ファイルなどもpostデータ扱いです。ただし画像は画像へのリンクなどの情報が入るのであって、バイナリは別です。

wp_postmeaはpostデータのメタデータを格納するテーブルです。上記のプラグインはこのテーブルにデータを追加します。

1度上記プラグインをONにして、画像をUplaodしてみると分かりますが、meta_key = ‘amazonS3_info’というものがwp_postmetaに追加されていると思います。このレコードこそ、上記プラグインが利用するデータです。

meta_valueはこんな感じになっていると思います。

a:3:{s:6:"bucket";s:31:"resources.tech-blog.tsukaby.com";s:3:"key";s:63:"wp-content/uploads/2015/06/069a5367d28a64e4509cfc089df491bc.png";s:6:"region";s:14:"ap-northeast-1";}

後はもうお分かりかと思いますが、このようなレコードを既存の画像ファイルの分だけINSERTしてやればOKです。少々INSERT文を作るのが面倒ですが、SQLのSELECTなり、Excelなり工夫すれば出来るかと思います。ちなみに「なんかよく分からんjson形式っぽい」データで入っていると思うかと思いますが、難しいことはありません。s:63などとなっている部分は「Stringで63文字」という意味だったりa:3となっている部分は「Arrayで3個」という意味ですので、適宜INSERTするものにあわせて変えればOKです。

参考までに自分が作ったINSERT文生成SQLを載せておきます。

select CONCAT('insert into wp_postmeta(post_id, meta_key, meta_value) values(', post_id, ', \'amazonS3_info\', \'a:3:{s:6:\"bucket\";s:31:\"resources.tech-blog.tsukaby.com\";s:3:\"key\";s:', length(meta_value),&nbsp; ':\"wp-content/uploads/', meta_value, '\";s:6:\"region\";s:14:\"ap-northeast-1\";}\');') AS record from wp_postmeta where meta_key = '_wp_attached_file'&nbsp;<br>

こんな感じでINSERT文を作ってあげてから、それを実行します。

後は、過去の投稿記事内の画像へのhrefとsrcは古いURLになっていると思います。なので、それも置換して新しいS3のURLにします。参考までに自分が利用したSQLを載せておきます。

update wp_posts set post_content = replace(post_content, 'src="https://tech-blog.tsukaby.com/wp-content/uploads/', 'src="http://resources.tech-blog.tsukaby.com/wp-content/uploads/');

以上で移行作業は完了です。お疲れさまでした。

まとめ

  • S3上に画像ファイルを保存するWordPressプラグイン Amazon S3 and CloudFrontプラグインを紹介しました。
  • セットアップ手順と使用例を説明しました
  • 過去データの問題と移行手順について説明しました
  • 移行作業が難しい人にはNephila clavataをオススメします

それでは快適なWordPressライフをお過ごし下さい

 - サーバ, ツール , ,