Minio (S3互換) で バージョン管理したデータを含めて永続化する

## はじめに

S3を利用したプロジェクトをローカルで開発するためにMinioを利用しました。
Minioは、Amazon S3と互換性のあるオブジェクトストレージです。

デフォルトのバケットを作成する方法はQiitaやissueに情報がありました。
本投稿では、別の方法でバージョン管理したバケット・ファイルを含めて永続化する環境を作成しました。

[Create default buckets via environment variables in docker #4769](https://github.com/minio/minio/issues/4769)

## issueの内容

issueでコメントされている方法は、minio/mcコマンドを別環境から実行してバケットを作成する方法が書かれていました。

```yml:docker-compose.yml
version: "2"
services:
  minio:
    image: minio/minio
    ports:
      - "9000:9000"
    volumes:
      - ./test/.minio/data:/export
      - ./test/.minio/config:/root/.minio
    environment:
      - "MINIO_ACCESS_KEY=AKIAIOSFODNN7EXAMPLE"
      - "MINIO_SECRET_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY"
    command: server /export

  createbuckets:
    image: minio/mc
    depends_on:
      - minio
    entrypoint: >
      /bin/sh -c "
      /usr/bin/mc config host add myminio http://minio:9000 AKIAIOSFODNN7EXAMPLE wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY;
      /usr/bin/mc rm -r --force myminio/somebucketname;
      /usr/bin/mc mb myminio/somebucketname;
      /usr/bin/mc policy download myminio/somebucketname;
      exit 0;
      "
```

また、永続化のためにhostのvolumeをデータディレクトリにマウントすることは推奨されていないようです。

ここではmcコマンドでバケットを作成するのではなく、予め作成しておいたバケット・ファイルをコンテナ起動時にコピーすることでデータの永続化を行います。

## ディレクトリ構成

```text
.
├── minio                       # Minio関連ディレクトリ
│   ├── config                  # /root/.minio
│   ├── data                    # /data(Minioデータ格納先)
│   ├── export                  # /export(Minioへ展開するデータ格納先)
│   │   └── test-bucket         # デフォルト作成バケット
│   │       ├── .gitkeep
│   │       └── data.csv        # テストファイル
│   └── policies                # バケットポリシー格納ディレクトリ
│       └── buckets
│           └── test-bucket     
│               └── policy.json # デフォルト作成バケットポリシー
├── .gitignore
└── docker-compose.yml
```

予め登録しておきたいバケット・ファイルを`export`ディレクトリに作成し、コンテナ起動時に`data`ディレクトリにコピーします。
`policies`ディレクトリにはバケットに適用するポリシーを格納します。

本投稿は`test-bucket`バケットをデフォルトで作成する例です。

## ポリシーファイルの作成

ディレクトリ構成に沿ってファイルを作成します。

```json:policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "*"
        ]
      },
      "Action": [
        "s3:GetBucketLocation",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::test-bucket"
      ]
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "*"
        ]
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::test-bucket/*"
      ]
    }
  ]
}
```

## docker-compose.ymlの作成

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

services:
  minio:
    container_name: example_minio
    image: minio/minio:latest
    ports:
      - 9090:9000 # VSCodeと競合するので9090番ポートを指定
    environment:
      - MINIO_ACCESS_KEY=admin
      - MINIO_SECRET_KEY=password
    entrypoint: sh
    command: -c "
      mkdir -p /data/.minio.sys/buckets;            # バケット設定情報格納フォルダの作成
      cp -r /policies/* /data/.minio.sys/;          # バケットポリシーをコピー
      cp -r /export/* /data/;                       # バージョン管理ファイルをコピー
      find /data -name '.DS_Store' -type f -delete; # 不要ファイル削除
      find /data -name '.gitkeep' -type f -delete;  # 不要ファイル削除
      /usr/bin/minio server /data;                  # サーバ起動
      "
    volumes:
      - ./minio/data:/data
      - ./minio/export:/export
      - ./minio/config:/root/.minio
      - ./minio/policies:/policies
```

`minio`ディレクトリ配下の不要なファイルはバージョン管理から除外します。

```text:.gitignore
/minio/config
/minio/data
```

作成したdocker-composeを起動してバケット、ファイルが出来ていることを確認します。

```bash
$ docker-compose up -d
```

## 確認

バケットが作成されたかAWS CLIで確認します。

### 認証情報設定

```bash
$ aws configure --profile minio
AWS Access Key ID [None]: admin
AWS Secret Access Key [None]: password
Default region name [None]: us-east-1
Default output format [None]: json
```

### 確認

```bash
$ aws s3 ls s3://test-bucket --endpoint-url http://localhost:9090 --profile minio
2019-03-13 00:16:15         10 test.csv
```

バケットがあること、ファイルが作成されていることを確認できました。
Minio管理画面からも同様にファイルの確認が可能です。

## まとめ

Minioを使うことでAWS上にバケットを作成することなく、ローカル開発環境を構築出来ました。
CLIだけでなく、SDKからも接続できるので本番とローカルで大きな差異がなくプログラムを書けるかと思います。

また、バージョン管理したファイルを予め登録しておくことで複数人で開発する際の環境構築時の負担を軽減できますね！

[daisukeArk/example-minio - GitHub](https://github.com/daisukeArk/example-minio)