やること
アップロードした画像をS3に保存し、CloudFrontで画像を配信するシステムをローカル環境で再現します。
背景
minIOの画像をパブリックアクセスで表示しようとすると、認証処理が煩雑?というかできなさそう?だったので、いっそのことその処理は軽量なwebサーバのexpressに任せてしまおうというお話です。
ハマった点
minIOのS3エンドポイントを指定するときに、パス形式にしないとアクセスエラーとなってしまいます。
ただし、amazon S3自体はパス形式URLの非推奨となる予定なので、注意が必要です。
仮想ホスティング形式
http://mybucket.s3.ap-northeast-1.amazonaws.com/
パス形式
http://s3.ap-northeast-1.amazonaws.com/mybucket/
ディレクトリ構成
.
├── docker-compose.yml
├── minio
│ └── Dockerfile
└── node
├── Dockerfile
├── package.json
└── server.js
Docker
docker-compose.yml
version: "3.8"
services:
minio:
build: ./minio
ports:
- "9000:9000"
- "9001:9001"
environment:
- MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD=minio123
entrypoint: sh
command: -c "
/opt/bin/minio server /data --address :9000 --console-address :9001;"
volumes:
- ./minio/data:/data
mc:
image: minio/mc
depends_on:
- minio
entrypoint: >
/bin/sh -c "
mc alias set myminio http://minio:9000 minio minio123;
mc mb myminio/mybucket;
"
node:
build: ./node
image: node
ports:
- 8080:8080
minIO
minIOは更新が多いので雑に最新版を持ってきます。
minio/Dockerfile
FROM minio/minio:latest
node
node/Dockerfile
FROM node:18-alpine
WORKDIR /usr/src/app
COPY ./package*.json ./
RUN npm install
COPY . .
EXPOSE 8080
CMD [ "npm", "start" ]
package.json
node/package.json
{
"name": "express",
"version": "1.0.0",
"description": "Node.js on Docker",
"author": "First Last <first.last@example.com>",
"main": "server.js",
"scripts": {
"start": "node server.js"
},
"dependencies": {
"express": "^4.16.1",
"aws-sdk": "*"
}
}
expressで画像表示のGETリクエスト処理
node/server.js
'use strict';
const express = require('express');
const aws = require('aws-sdk');
//s3のアクセス情報
const s3Client = new aws.S3({
accessKeyId: "minio",
secretAccessKey: "minio123",
region: "ap-northeast-1",
endpoint: "http://minio:9000/",
//ここをtrueにしないとエラーになる
s3ForcePathStyle : true
})
// バケットの情報を設定
let bucketName = 'mybucket';
// Constants
const PORT = 8080;
// App
const app = express();
app.get('/:pictureName', (req, res) => {
let key = req.params.pictureName;
s3Client.getObject({Bucket : bucketName,Key : key},
function(err,data) {
if (!err) {
res.set("Content-Type", data.ContentType);
res.send(data.Body);
}
}
);
});
app.listen(PORT, () => {
});
docker composeをビルト&起動
処理高速化のためにnodeはコンテナ内に入れています。
docker-compose up -d --build
minIOに画像をアップロードしてexpressで表示
minIOにログイン
http://localhost:9000
にアクセス
userとパスワードはdocker-compose.yml
で定義した
environment:
- MINIO_ROOT_USER=minio
- MINIO_ROOT_PASSWORD=minio123
画像をアップロード
Object Browserにdocker-composeのmcクライアントで設定したmybuketが表示されているので、その中に画像をアップロードします。
画像を表示
アップロードした青い画像.pngをexpressで表示確認します。
http://localhost:8080/青い画像.png
しっかり表示できました。
awssdkを使ってminIOに接続する際は、仮想ホスティング形式ではなく、パス形式にするように、指定しないとアクセスエラーしまうところにかなり時間使ってしまいました。
phpとnode.jsは指定必須でした。
参考文献