docker-composeでMinIO立ててLaravelでS3ごっこしゅる

# はじめに

ハロー皆さま！　たのしいLaravelライフを送っていますか？

普通にローカル上でLaravelアプリを立てて、そこでファイルをアップロードすると、アップロードしたファイルは `approot/storage/app` 配下に行くことになりますが本番ではなかなかそうなることは少ないと思います。
まあ、VPS1台立ててそこで全部賄うとか、そういう運用になってたらアレですが……

例えばAWSでLaravelアプリを運用するとき、アプリケーションはEC2複数台で構成するとして、アップロードしたファイルはどっちのインスタンスからも見れないと困るので、S3に置くことになると思うんですよね。
ECSで複数タスク使うんだったらなおさら無理なわけですよ。
で、ローカルで開発するときに、アップロードはいいとしても、ダウンロードの処理のところがオブジェクトストレージ使うのかそうでないのかで全然変わっちゃうので、やっぱローカルでもS3使いてえなってなるのが人情なんでしょうけど、ローカルの開発用にS3のバケット用意してくれるところはなかなかない気がします。
そこでS3互換のオブジェクトストレージアプリのMinIOさんに頼ろうぜって話です。

https://min.io/

# やり方

公式にも書かれてはいるのですが、いかんせん英語ですし、書かれてるとおりにやっても微妙にうまく行かないので説明しますね。

https://min.io/docs/minio/container/operations/install-deploy-manage/deploy-minio-single-node-single-drive.html

まあ、多分 `docker compose` を使うことになると思うので、 `docker-compose.yml` の例をおいておきます。

```yml:docker-compose.yml
version: '3'

services:

  # ローカルで試せるs3互換
  minio:
    image: "minio/minio:RELEASE.2023-01-02T09-40-09Z.fips"
    volumes:
      - "./minio/data:/data:delegated"
    ports:
      - ${MINIO_API_PORT}:9000
      - ${MINIO_CONSOLE_PORT}:9001
    environment:
      - MINIO_ROOT_USER=${MINIO_ROOT_USER}
      - MINIO_ROOT_PASSWORD=${MINIO_ROOT_PASSWORD}
      - MINIO_SERVER_URL=${MINIO_SERVER_URL}
    command: server /data --console-address :9001
```

`image` は今回は普通にDockerhubを使っていますが、 `quay.io` からも入れられるそうです。
その時はこんな感じになりますね。

```yaml:quay.io用
  # ローカルで試せるs3互換
  minio:
    image: "quay.io/minio/minio"
```

柔軟に色々できるように一部環境変数を入れています。
`.env` ファイル使うなり、シェルで環境変数設定するなりするといいでしょう。

こんな感じですね。

```.env（Docker側）
# minio
MINIO_API_PORT=9000
MINIO_CONSOLE_PORT=9001
MINIO_ROOT_USER=user
MINIO_ROOT_PASSWORD=password
MINIO_SERVER_URL=http://localhost:9000
```

`MINIO_ROOT_USER` と `MINIO_ROOT_PASSWORD` 凝ったのにするとなぜかこのあとで紹介するコンソール画面に入れなくなるので、なるべくあっさりしたものにしましょう。

ここまでできたらサクサクっと `docker compose up -d` しましょう。
すると `http://localhost:9001` でこんな画面にアクセスできるはずです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/57811/dccfed3f-1516-d50b-8d1c-7fefa3fc5969.png)

これが例のコンソール画面ですね。`MINIO_ROOT_USER` と `MINIO_ROOT_PASSWORD` で設定したものを入力して `Login` すると中には入れるようになります。
やったね！

# docker-composeするだけでバケット作っておきたい

チーム開発してるときに「MinIO立ち上げるところまでは面倒見るけど、バケットは自力で作ってね」って運用でもいいんですが、説明する手間は少しでも少ないほうがいいですよね。
そんなときには `docker-compose.yml` にこれを書き加えるとバケットの作成までやってくれます。

```yaml:docker-compose.yml
  # Bucketの作成（すぐに死ぬ）
  createbuckets:
    image: "minio/mc"
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      echo start_up;
      sleep 5;
      /usr/bin/mc config host add myminio http://minio:9000 ${MINIO_ROOT_USER} ${MINIO_ROOT_PASSWORD};
      /usr/bin/mc mb myminio/${MINIO_BUCKET_NAME};
      exit 0;
      "
```

これ、何をやっているかというと、 `mc` というMinIOのcliツールでバケット生成をしているものになります。

環境変数の `MINIO_BUCKET_NAME` は例によって `.env` に入れておきましょう

# Laravel側の設定をしよう

ローカルのLaravelからMinIOに作ったS3互換のバケットにアクセスするにはLaravelソース直下の `.env` に以下のものを書けばいいのです。
Laravelのバージョンによって違うのですが、とりあえず本記事執筆時の最新の9のものを書いておきます。

```.env（Laravel側）
FILESYSTEM_DISK='s3'
AWS_ENDPOINT=http://minio:9001
AWS_ACCESS_KEY_ID= #Docker側の.envのMINIO_ROOT_USER
AWS_SECRET_ACCESS_KEY= #Docker側の.envのMINIO_ROOT_PASSWORD
AWS_S3_DEFAULT_REGION=us-east-1
AWS_BUCKET= #Docker側の.envのMINIO_BUCKET_NAME
```

あとはこれで普通に `Storage` ファサードからアクセスできるようになります。
詳しい使い方はこちらをご覧ください。

https://readouble.com/laravel/9.x/ja/filesystem.html

# おわりに

というわけで2年前に下書きに入れたっきりにしてた記事をようやく公開できるようにしました。
お正月最高！　ということで皆様も最高の2023年を送ってくださいまし！