概要
ローカルでS3が使えるように環境を作る。
アプリなどから画像をS3に登録してサイト側で閲覧できるようにしたい。
お知らせ
minIOのバージョンがアップされています。
この記事のminIOは1つ前のもの (RELEASE.2021-06-17T00-10-46Z) です。
※ 最新のminIOの場合、異なる部分があると思うのでご注意ください
<参考サイト>
※ MinIOを使ってローカルで外部ストレージをAmazonS3から置き換える
ファイル構成
├ docker
│ └ minio
│   ├ config               ... minio設定 (git管理対象外)
│   ├ data                 ... minioデータ (git管理対象外) 
│   ├ export
│   │ └ static             ... 起動時に取り込むファイル
│   │   ├ 150x150.png
│   │   └ 640x480.png
│   └ policies
│     └ buckets
│        └ static
│           └ policy.json  ... staticバケットのポリシー定義
│
│.gitignore
├ docker-compose.yml
└ REAMDE.md
※ github: https://github.com/reflet/docker-s3
docker設定
minio を 9090 ポートで起動する設定となっています。
※ 起動時に docker/minio/export/... を取り込むように設定しています
※ 最新版は仕様が変わっているのでバージョン指定( RELEASE.2021-06-17T00-10-46Z )しています
version: '3'
services:
  minio:
    image: minio/minio:RELEASE.2021-06-17T00-10-46Z
    container_name: 'minio'
    ports:
      - 9090:9000
    environment:
      - MINIO_ACCESS_KEY=minio
      - MINIO_SECRET_KEY=minio123
    entrypoint: sh
    command: -c "
      mkdir -p /data/.minio.sys/buckets;
      cp -r /policies/* /data/.minio.sys/;
      cp -r /export/* /data/;
      /usr/bin/minio server /data;
      "
    volumes:
      - ./docker/minio/data:/data
      - ./docker/minio/export:/export
      - ./docker/minio/config:/root/.minio
      - ./docker/minio/policies:/policies
Bucketのポリシー設定
static バケットのポリシー設定を記述します。
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "*"
        ]
      },
      "Action": [
        "s3:GetBucketLocation",
        "s3:ListBucket"
      ],
      "Resource": [
        "arn:aws:s3:::static"
      ]
    },
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": [
          "*"
        ]
      },
      "Action": [
        "s3:GetObject",
        "s3:PutObject",
        "s3:DeleteObject"
      ],
      "Resource": [
        "arn:aws:s3:::static/*",
        "arn:aws:s3:::static"
      ]
    }
  ]
}
サーバ起動
下記コマンドにて、dockerコンテナを起動します。
$ docker-compose up -d
管理画面
minioの管理画面へアクセスできます。
※ ID、PASSは、 docker-compose.yml に記載されています。
$ open http://127.0.0.1:9090/
S3ファイルへアクセス
下記URLにて static バケットのファイルにアクセス可能です。
※ アプリなどからアクセスする際に指定するURLとなります
$ open http://127.0.0.1:9090/static/hoge.txt
$ open http://127.0.0.1:9090/static/150x150.png
$ open http://127.0.0.1:9090/static/640x480.png
AWS SDK for PHP
AWS SDK for PHP で使う場合は、以下のようにエンドポイントの指定が必要となります。
※ アクセス元が、docker内のコンテナか、docker外のホストかで「 endpoint 」が変わります
date_default_timezone_set('Asia/Tokyo');
require 'vendor/autoload.php';
$s3 = new Aws\S3\S3Client([
        'version' => 'latest',
        'region'  => 'ap-northeast-1',
        'credentials' => [
            'key'    => 'minio',
            'secret' => 'minio123',
        ],
        'endpoint' => 'http://minio:9000',        // ← 追加 (docker内からアクセス)
        // 'endpoint' => 'http://127.0.0.1:9090', // ← 追加 (ホストからアクセス)
        'use_path_style_endpoint' => true,        // ← 追加
]);
minioのファイル操作 (awscliコマンド)
管理画面から操作できますが、まとめて画像ファイルをアップしたいなどの場合、
aws-cliコマンドで操作した方が楽そうです。
$ aws --version
もし、コマンドが無い場合は追加する。
# MacOS
$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"
$ brew -v
$ brew install awscli
$ aws --version
# Ubuntu
$ sudo apt-get -y install unzip
$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
$ unzip awscliv2.zip
$ sudo ./aws/install
$ aws --version
Config設定
プロフィールを作成する。
$ aws configure --profile minio
AWS Access Key ID [None]: minio
AWS Secret Access Key [None]: minio123
Default region name [None]: ap-northeast-1
Default output format [None]: json
プロフィール一覧を確認してみる。
$ aws configure list-profiles
プロフィール(minio)の設定状況を確認してみる。
$ aws configure list --profile minio
バケット内のファイル一覧を確認する
# docker内からアクセス: --endpoint-url http://minio:9000
$ aws --profile minio --endpoint-url http://127.0.0.1:9090/ s3 ls s3://static
2020-10-25 09:33:53          5 hoge.txt
画像をまとめて転送する
media フォルダをまとめて static バケットに送る。
# docker内からアクセス: --endpoint-url http://minio:9000
$ aws --profile minio --endpoint-url http://127.0.0.1:9090/ s3 sync media s3://static/media
画像をまとめて削除する
media フォルダを削除する
# docker内からアクセス: --endpoint-url http://minio:9000
$ aws --profile minio --endpoint-url http://127.0.0.1:9090/ s3 rm s3://static/media/ --recursive
ファイルを追加する
# docker内からアクセス: --endpoint-url http://minio:9000
$ aws --profile minio --endpoint-url http://127.0.0.1:9090/ s3 cp fuga.txt s3://static
upload: ./hoge.txt to s3://static/fuga.txt
フォルダを追加する
# docker内からアクセス: --endpoint-url http://minio:9000
$ aws --profile minio --endpoint-url http://172.17.100.101:9090/ s3api put-object --bucket static --key hoge/ 
ファイルを削除する
# docker内からアクセス: --endpoint-url http://minio:9000
$ aws --profile minio --endpoint-url http://127.0.0.1:9090/ s3 rm s3://static/hoge.txt
delete: s3://static/hoge.txt
minioのファイル操作 (curlコマンド)
Linuxサーバであれば、ほぼ存在する「 curlコマンド 」で操作してみる。
ファイルを取得する
# docker内からアクセス: 127.0.0.1:9090 → http://minio:9000
$ curl http://127.0.0.1:9090/static/hoge.txt
ファイルを登録する (認証なし)
「 /tmp/hoge.txt 」を転送する例です。
# docker内からアクセス: http://127.0.0.1:9090 → http://minio:9000
$ export FILE='hoge.txt'
$ export URL='http://127.0.0.1:9090/static/${FILE}'
$ export PATH='/tmp/${FILE}'
$ curl -i --request PUT ${URL} \
  --upload-file ${PATH} \
  -H "x-amz-acl: bucket-owner-full-control"
ファイルを登録する (認証あり)
「 /tmp/hoge.txt 」を転送する例です。
# docker内からアクセス: http://127.0.0.1:9090 → http://minio:9000
export S3_KEY="minio"
export S3_SECRET="minio123"
export RESOURCE="/static/hoge.txt"
export CONTENT_TYPE="application/octet-stream"
export DATE=`date -R`
export _SIGNATURE="PUT\n\n${CONTENT_TYPE}\n${DATE}\n${RESOURCE}"
export SIGNATURE=`echo -en ${_SIGNATURE} | openssl sha1 -hmac ${S3_SECRET} -binary | base64`
curl -v -X PUT http://127.0.0.1:9090${RESOURCE} \
  -T /tmp/hoge.txt \
  -H "Host: 127.0.0.1:9090" \
  -H "Date: ${DATE}" \
  -H "Content-Type: ${CONTENT_TYPE}" \
  -H "Authorization: AWS ${S3_KEY}:${SIGNATURE}"
ファイルを登録する (認証なし - PHP)
PHPで curl_exec() 関数にて送信を試してみる。
$file = '/tmp/hoge.txt';
$fp   = fopen($file, 'rb');
$size = filesize($file);
// docker内からアクセス: http://127.0.0.1:9090 → http://minio:9000
$url = 'http://127.0.0.1:9090/static/' . basename($file);
$ch  = curl_init($url);
curl_setopt($ch, CURLOPT_PUT, true);
curl_setopt($ch, CURLOPT_INFILE, $fp);
curl_setopt($ch, CURLOPT_INFILESIZE, $size);
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_HEADER, true);
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 4);
curl_setopt($ch, CURLOPT_TIMEOUT, 5);
curl_setopt($ch, CURLOPT_HTTPHEADER, ['x-amz-acl: bucket-owner-full-control']);
$response = curl_exec($ch);
$info = curl_getinfo($ch);
curl_close($ch);
// 結果を見てみる
var_dump($info, $response)
以上


