なおのつぼやき

Webエンジニアです。PHP/Laravel、あとRustを少々

PHPからS3へのファイルアップロードをLocalStackを使ってやってみる

ローカル環境からS3にファイルをアップするために本物を用意するのが面倒になっていた際にLocalStackと言うものを見つけたので使ってみた。

LocalStackって何

  • AWSのサービスのモックを用意してくれるすごいやつ

github.com

  • 今回はS3のモックを使ってみる

環境

  • PHP 7.4.10
  • Composer 1.10.13
  • LocalStack 0.11.6

準備

docker-compose.ymlの内容

version: '3'
services:
  localstack:
    image: localstack/localstack
    ports:
      - 4566:4566
    environment:
      - SERVICES=s3
      - AWS_ACCESS_KEY_ID=dummy
      - AWS_SECRET_ACCESS_KEY=dummy
      - AWS_DEFAULT_REGION=ap-northeast-1
  • ポートはLocalStackのv0.11.5以降は4566のみになったので1つだけ指定する
  • SERVICESで使うサービスを指定する(今回はS3のみ指定)
  • AWS_ACCESS_KEY_IDAWS_SECRET_ACCESS_KEYの値はなんでも良いです
  • AWS_DEFAULT_REGIONは東京リージョン
  • 永続化の設定とかあるけど今回はなし

Docker起動

$ docker-compose up -d --build

以降は起動している前提で書いていきます。

バケット作成

LocalStackのコンテナにAWS CLIも一緒に入っていたのでそこからコマンドでバケットを作成する。

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 ls s3://

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 mb s3://local-test
make_bucket: local-test

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 ls s3://
2020-10-11 21:47:34 local-test

s3にファイルアップロードするPHPのコード

パッケージのインストール

AWS SDK for PHPを使いたいのでComposerを使ってインストール

$ composer require aws/aws-sdk-php

PHPのコード

<?php

require_once 'vendor/autoload.php';

use Aws\S3\S3Client;

$config = [
    'credentials' => [
        'key' => 'dummy',
        'secret' => 'dummy',
    ],
    'region' => 'ap-northeast-1',
    'version' => 'latest',
    'endpoint' => 'http://localhost:4566',
    'use_path_style_endpoint' => true,
];

$s3 = new S3Client($config);

// アップロード
$result = $s3->putObject([
    'Bucket' => 'local-test',  // バケット名
    'Key' => 'hello.txt',      // s3のアップロード先
    'Body' => 'hello world!!', // ファイルの内容
]);

echo 'ファイルのURL => ' . $result['ObjectURL'] . PHP_EOL;

// 内容の取得
$result = $s3->getObject([
    'Bucket' => 'local-test',  // バケット名
    'Key' => 'hello.txt',      // s3のアップロード先
]);

echo 'ファイルの内容 => ' . $result['Body'] . PHP_EOL;

大事なところはendpointuse_path_style_endpointです。 LocalStackを使うと実際のS3のURLとは異なるなのでendpointバケット作成で使ったhttp://localhost:4566を設定する必要がある。

ただし、指定することでendpointhttp://{バケット名}.localhost:4566となり実行すると名前解決できずエラーが発生します。
そこでuse_path_style_endpointtrueを設定することでendpointがパス形式(http://localhost:4566/{バケット名})になり、実行可能になる。

動かしてみる

$ php s3.php
ファイルのURL => http://localhost:4566/local-test/hello.txt
ファイルの内容 => hello world!!

ファイルURLの表示とアップした内容の取得が表示していれば成功です。

確認

AWS CLIを使ってファイルがアップできているか見てみる。

$ docker-compose exec localstack aws --endpoint-url=http://localhost:4566 s3 ls s3://local-test
2020-10-11 23:49:33         13 hello.txt

ファイル名が表示していればOKです。

まとめ

LocalStackを使えば簡単にS3へのアップロードができました。
(ただ、エンドポイントあたりがややこしいです)

実際にS3を使っているとお金が、、、とかなったりしていろいろ面倒ですが、 LocalStackを使えばその辺は気にしなくてよくなるはず。