Laravel+Docker+minioでS3の実行環境をローカル環境に構築する

ローカル環境にてminioの設定を行いましたが、途中、minioのエンドポイントが名前解決されず3時間ほど詰まりましたので、忘備録として記載。

## パッケージインストール
Laravel9.0 公式より
```
composer require league/flysystem-aws-s3-v3 "^3.0"
```


## docker-compose.ymlにminoの設定を追加

```docker-compose.yml
networks:
  project-network:
    name: project-network
   

  // 中略
services:
  minio:
    image: quay.io/minio/minio
    container_name: minio
    ports:
      - 9000:9001 # php-fmpで9000ポートを使用している場合、9000番以外を指定
      - 9001:9002
    networks:
      - project-network
    environment:
      - MINIO_ROOT_USER=minio
      - MINIO_ROOT_PASSWORD=minio1234
    entrypoint: sh
    command: -c "/opt/bin/minio server /export --address :9001 --console-address :9002"
    volumes:
      - ./docker/minio/data:/export
```
### 解説
- portについて
    - 9000:9001
        - 9000番：クライアント（ブラウザ）からのリクエスト用ポート
            - imageタグ等からアクセスする際は、こちらのポートを利用
        - 9001番：minioの待ち受けポート
            - php-fpmを利用している場合、デフォルトで待ち受けポート9000を利用しているため、minioでは9000番以外を指定する必要があることに注意
    - 9001:9002
        - minioのWebコンソールにアクセスするためのポート設定


## minioにアクセスし、バケットを作成
- http://localhost:9001/login にアクセスし、minioのコンソールログイン画面に遷移する。
- UsernameとPasswordは、dokcer-composeで指定した値を入力し、ログイン
- Bucketの「Create Bucket」ボタンをクリックし「test」というバケットを作成

## Laravelでファイルストレージの設定を行う
filesystems.phpでs3の設定を、下記のように行う。

```Laravel/config/filesystems.php
    // 省略
       's3' => [
            'driver' => 's3',
            'key' => env('AWS_ACCESS_KEY_ID'),
            'secret' => env('AWS_SECRET_ACCESS_KEY'),
            'region' => env('AWS_DEFAULT_REGION'),
            'bucket' => env('AWS_BUCKET'),
            'url' => env('AWS_URL'),
            'endpoint' => env('AWS_ENDPOINT'),
            'use_path_style_endpoint' => env('AWS_USE_PATH_STYLE_ENDPOINT', false),
            'throw' => true, // minioのエラーをcatchしたい場合はtrue
        ],



```

環境変数でS3の情報を定義

```.env（Laravel）
AWS_ACCESS_KEY_ID=minio
AWS_SECRET_ACCESS_KEY=minio1234
AWS_SESSION_TOKEN=
AWS_DEFAULT_REGION=ap-northeast-1
AWS_BUCKET=test
# ローカル環境のみ必要
AWS_URL=http://localhost:9000
AWS_ENDPOINT=http://mino:9001
AWS_USE_PATH_STYLE_ENDPOINT=true

```
### AWS_URLについて
外部のクライアント（ブラウザ等）からアクセス用URLを生成する際に利用するURL。

### AWS_ENDPONTについて
PHPコンテナからminoコンテナにアクセスする際のminioのエンドポイント。
phpのコード上からminioに対して処理をする際のパスとして利用される。
※同一dockerネットワーク内からのアクセスであれば、service名を指定する。
例）http://mino:9001



### AWS_USE_PATH_STYLE_ENDPOINT=true　について
true に設定すると、デフォルトで S3 パススタイルのエンドポイントにリクエストが送信されます。

```
http://minio:9001/{bucket名}/リソース名
```

falesに設定すると、仮想ホスト形式のパスでエンドポイントにリクエストが送信されます。

```
http://{バケット名}.minio:9001//リソース名
```

ローカル環境でdocker-composeを使用している場合、仮想ホスト形式だとホスト名を名前解決できず、minioへのアクセスに失敗します。
```
例）
http://minio:9001 → 名前解決される
http://test.minio:9001 → docker-networkのホスト名に登録がなので名前解決されない
```

したがってローカル環境でminioを使う場合は、trueに設定します。

逆にテスト環境や本番環境ではfalseに設定しないと、AWSのS3側でエラーとなります。

参考：
https://docs.aws.amazon.com/aws-sdk-php/v3/api/class-Aws.S3.S3Client.html
https://docs.aws.amazon.com/ja_jp/AmazonS3/latest/userguide/VirtualHosting.html

## フィアルアップロード確認
phpのコンテナに入りtinkerにて下記のコマンドを打ち、trueが返って来ればOKです。

```sh
# php artisan tinker
Psy Shell v0.11.8 (PHP 8.1.13 — cli) by Justin Hileman
>>> Storage::disk('s3')->put('hello.json', '{"hello": "world"}')
=> true

```

以上で、Laravelとminioによるローカル環境でのS3実行環境を整えることができました。


参考：
MinIO を使ってローカルでの開発環境の外部ストレージを Amazon S3 からローカルのコンテナへ置き換える
https://www.ritolab.com/posts/232

Laravel 9.x ファイルストレージ
https://readouble.com/laravel/9.x/ja/filesystem.html



Minio: An Open-Source S3 Compliant Storage Service
https://laravel-news.com/minio-s3-compliant-storage