PythonからLocalStackのS3へ繋ぐ際の注意


たくさんはまったので備忘録。

LocalStackへ接続するにあたりAWSアクセスキー、AWSシークレットキーの代わりにエンドポイントURLを設定する必要があるが、
s3fsを利用していると(内部的にはboto3を利用しているらしい)
endpoint_urlの引数の設定の仕方が意地悪(公式ドキュメント化されていないらしい。

There is an undocumented parameter in the current verison client_kwargs={'endpoint_url': 'https:...'} which is the desired one.

また、docker-composeではコンテナ名がドメインのエイリアスに使えるのだが
こちらの記事

を参考にさせていただいて、
エイリアス名を固定で.envファイルに外出ししようとしたのだが
作成されるコンテナ名には_nのsuffixがつき、
_が使われているとエンドポイントURLのValidationエラーに引っかかって
ValueError: Invalid endpoint:のエラーを返す(涙)

ケバブケース(-)に置き換えてdocker-compose.ymlファイル内で
container_nameを設定してあげることで解決

※なお、コンテナ間での通信が不要であれば上記記事のやり方が適切かと思います

hoge.py
import os
import boto3
import s3fs

endpoint_url=os.getenv("S3_ENDPOINT", None)

boto3.resource('s3', endpoint_url=endpoint_url)
s3fs.S3FileSystem(client_kwargs=dict(endpoint_url=endpoint_url))
docker-compose.yml
version: "3.7"

services:
  python:
    environment:
      S3_ENDPOINT: "http://aws-container:4572"
      AWS_ACCESS_KEY_ID: "dummy"
      AWS_SECRET_ACCESS_KEY: "dummy"
    tty: true
    container_name: python-container
    depends_on:
      - aws

  aws:
    image: localstack/localstack:0.11.5
    environment:
      SERVICES: "s3"
      AWS_ACCESS_KEY_ID: "dummy"
      AWS_SECRET_ACCESS_KEY: "dummy"
    ports:
      - "4566:4566"
      - "4572:4572"
    container_name: aws-container