やりたいこと
- 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 の場合
- リクエストのホスト名が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`の意義が腑に落ちました。