ティーポットは珈琲を淹れられない

ソフトウェアエンジニアK5のブログ

ローカルDocker環境でS3Mockを利用する

2020年10月12日

AWS 環境で動作させているシステムの開発をしていて、ローカルの Docker 環境に S3 と同じ API で動作するモックがあったらいいなと思って調べたら、当然のようにありました。

S3 のモックサーバー候補

とりあえず見つかったのは以下です。

上2つが有力候補。 3つ目の Fake S3 は古いバージョンはオープンソースだけど新しいバージョンは有料っぽい? 後ろ2つは adobe/S3Mock が似たようなプロジェクトとして紹介してました。

今回は findify/S3Mock を試した後に、結局 adobe/S3Mock を利用しました。

実際のプロジェクトでは TypeScript を使っているのですが、ここでは Javascript で解説します。

なぜ adobe/S3Mock にしたか?

findify/S3Mock でデフォルトのバケットをコンテナ作成時に最初から作成しておく方法がすぐに分からなかったからです。 もちろん API を呼んで CreateBucket することはできます。

dokcer-compose.yml の用意

docker-compose の設定は以下のようにしました。 Node.js 環境も dokcer-compose で用意しておきます。

docker-compose.yml
version: '3.7'

services:
  # Node.js環境。開発時のnpmコマンド実行はここで行う。
  node:
    image: node:12.18.3-alpine3.12
    volumes:
      - ./:/project:delegated
    tty: true
    working_dir: /project
    environment:
      # AWS-SDKを動作させるのにダミーでいいので設定しておく必要がある
      AWS_REGION: ap-northeast-1
      AWS_ACCESS_KEY_ID: local
      AWS_SECRET_ACCESS_KEY: dummy

  s3:
    image: adobe/s3mock
    environment:
      - initialBuckets=my-bucket

initialBuckets を指定することでコンテナ作成時にバケットも作成することができます。inisitalBuckets と複数形になっていますが、リストで複数作成させることができるようです。

     - initialBuckets=my-bucket1,my-bucket2,my-bucket3

Node.js 環境の用意

コンテナを起動しておきましょう。

$ docker-compose up -d

node コンテナに入って作業します。alpine 版を使ってるので bash が入っていなくて sh を指定します1

$ docker-compose exec node sh

ここからは node コンテナ内でのコマンド実行の場合は、先頭を $ ではなく # で表します。

package.json を作成します。中身は適当でいいです。

# npm init

AWS SDK をインストールします。

$ npm install aws-sdk

AWS SDK でのアクセス

適当に index.js とかの名前でファイルを作成しましょう。 まずは s3 クライアントオブジェクトを作成します。

const AWS = require('aws-sdk');

const s3 = new AWS.S3({
  apiVersion: '2006-03-01',
  // docker-compose環境の中ではサービス名がそのままホスト名として使える。s3コンテナの9090番ポートを指定。
  endpoint: 'http://s3:9090',
  // S3Mock使う時は <バゲット名>.hostname:9090 でなく hostname:9090/<バゲット名> になってもらわないと困る
  s3ForcePathStyle: true,
});

endpoint と s3ForcePathStyle を指定する必要があります。

S3 の URL は昔は https://s3-<リージョン >.amazonaws.com/<バケット名> というパス形式と呼ばれるものが使われていました。 今は https://<バケット名>.s3-<リージョン>.amazonaws.com/ という仮想ホスト形式が使われています。 しかし S3Mock を使うときに仮想ホスト形式になってもらってはアクセスできないので、パス形式を利用するように指定しています。

9090 番ポートは HTTP 用で、9191 番ポートが HTTPS 用だそうです。HTTP しか試してませんが。

あとは普通に使ってもらえば大丈夫です。


  1. alpine を使っているのは、本番環境の Fargate 用コンテナをサイズの小さい alpine で作るつもりでいて、開発環境も同じに合わせたかったからです。debian を使った方が色々とカスタマイズが楽だと思います。


© 2016-2020 K5