Dockerネットワーク内のminioで署名付きURLを使う時のTIPS

April 28, 2019

はじめに

minioはs3互換のオブジェクトストレージサーバです。
GitHub - minio/minio: MinIO is an open source object storage server compatible with Amazon S3 APIs

開発環境等でs3の代替として導入されている現場もあるのではないでしょうか。
localstackを使うパターンもあるかと思いますが、シンプルにs3の機能が欲しいだけの時はminioのほうが軽くて必要十分な場合が多いかなと思います。
今回はdocker-composeで起動する開発環境にminioを組み込もうとした際に少し悩んだことがあったので、自分なりの対処方法を書いてみます。

課題

Dockerネットワーク内で取得した署名付きURLに、Dockerネットワーク外から接続できない。

環境の説明

こんな感じで署名付きURLを利用するWebアプリケーションがあるとする。

  1. リクエスト(クライアント→アプリケーション)
  2. 署名付きURL発行(アプリケーション⇄s3)
  3. 署名付きURLを返す(アプリケーション→クライアント)
  4. 署名付きURLに接続(クライアント→s3)

この時、アプリケーションとクライアントは、どちらも同じURL(ホスト名)でs3に接続できる。

https://my-backet.s3-ap-northeast-1.amazonaws.com/some/photo.jpg?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Security-Token=xxxx...

本番環境はこれで問題なし。

さて、その開発環境でs3のモック的にminioを導入し、もろもろ一式をdocker-composeで立ち上げるとする。
この時アプリケーションはDockerネットワーク内でminioコンテナに接続するが、クライアントからはホスト経由でブリッジをまたいで接続することになるので、アプリケーションで取得した署名付きURLでクライアントからは接続できない。

具体的には、仮にコンテナ名が minio だった場合、以下のようなURLが生成される。

http://minio:9000/my-backet/some/photo.jpg?X-Amz-Content-Sha256=UNSIGNED-PAYLOAD&X-Amz-Security-Token=xxxx...

しかしその名前はDockerネットワーク内でしか使えないので、Dockerネットワーク外のクライアントからは接続できない。そらそうだ。

ちなみに署名付きURLにリクエストを送信する時は、取得時と同じメソッドとヘッダーを使用する必要がある。そのため取得したURLを無理矢理クライアント側からアクセスできるホスト名に変更したりはできない。
AWS SDK for PHP バージョン 3 での Amazon S3 の署名付き URL - AWS SDK for PHP

対処

アプリケーションからもクライアントからも、同じホスト名で名前解決できるようにする。
具体的にはDNSなりhostsファイルなりを修正し、クライアント側からも http://minio:9000/xxx のように、Dockerネットワーク内と同じホスト名でminioに接続できるようにする。

終わりに

あまりイケてない気がするので、もっとうまいやり方があればご教授ください。。。
過去に似たようなケースに対応するためのissueも挙がっていたようですが、採用されなかったみたいですね。
Set default URL for presignedUrl · Issue #2848 · minio/minio · GitHub

@j_untanaka on Twitter

dockerAWSs3minio