干し石榴長文用

長文以外はTumblrへ徐々に移します。

コンテナ間でS3rverにアクセスする

やりたいこと

  • test時のS3アクセスをローカルのS3rverに向けたい
  • S3rverをコンテナ化してコンテナ間でアクセスしたい

駄目だった例

./s3rver/Dockerfile

FROM node:13-alpine

EXPOSE 4568
RUN npm install -g s3rver \
 && mkdir -p /var/lib/s3

ENTRYPOINT ["/usr/local/bin/s3rver", "-a", "0.0.0.0", "-d", "/var/lib/s3"]

./docker-compose.yml

version: "3"
networks:
  default:
    driver: bridge
services:
  main:
    build: .
  s3rver:
    build: ./s3rver

mainコンテナのシェル

# aws --profile s3rver --endpoint-url http://s3rver:4568 s3api create-bucket --bucket test

An error occurred (NoSuchBucket) when calling the ListBuckets operation: The specified bucket does not exist

バケット作ろうとしてNoSuchBucketとは…

何故なのか

答えはs3rver/lib/middleware/vhost.jsにありますが、要するに

  • リクエストのホスト名が bucket_name.s3.endpoint の場合
    • バケット名はbucket_name
    • endpointのデフォルトは `amazonaws.com`
    • endpointは起動オプションの `--service-endpoint` で上書き可能
  • リクエストのホスト名がIPアドレスでも `localhost` でもない場合
    • リクエストpathが /hostname に書き換えられる

つまり、http://s3rver:4568 でアクセスした場合、パス部が /s3rver になり「s3rverというバケットに対するリクエスト」として解釈されるようです(恐らく)。

解決策

  • S3rverのエンドポイントを `local` にする
  • docker-compose上のサービス名を `s3.local` にする
  • mainコンテナから `http://s3.local:4568` でアクセスする

./s3rver/Dockerfile

FROM node:13-alpine

EXPOSE 4568
RUN npm install -g s3rver \
 && mkdir -p /var/lib/s3

ENTRYPOINT ["/usr/local/bin/s3rver", "-a", "0.0.0.0", "/var/lib/s3", "--service-endpoint", "local"]

./docker-compose.yml

version: "3"
networks:
  default:
    driver: bridge
services:
  main:
    build: .
  s3.local:
    build: ./s3rver

mainコンテナのシェル

# aws --profile s3rver --endpoint-url http://s3.local:4568 s3api create-bucket --bucket test
{
    "Location": "/test"
}

S3rver起動オプションの `--service-endpoint`の意義が腑に落ちました。