LoginSignup
7

Docker ComposeでminIO + expressで簡易画像表示APIを作成する

Last updated at Posted at 2023-04-27

やること

アップロードした画像を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

を入力します。
image.png

画像をアップロード

Object Browserにdocker-composeのmcクライアントで設定したmybuketが表示されているので、その中に画像をアップロードします。

image.png

画像を表示

アップロードした青い画像.pngをexpressで表示確認します。
http://localhost:8080/青い画像.png
image.png

しっかり表示できました。
awssdkを使ってminIOに接続する際は、仮想ホスティング形式ではなく、パス形式にするように、指定しないとアクセスエラーしまうところにかなり時間使ってしまいました。

phpとnode.jsは指定必須でした。

参考文献

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
What you can do with signing up
7