AWS
sqs
LocalStack

LocalStackをDockerコンテナ内で使う場合に、SQSのQueueUrlがlocalhostになって困った話(解決済み)

はじめに

LocalStackは、AWSの各サービスをローカルで再現するためのフェイク環境です。
公式のDockerイメージを使うと便利です。

localstackは、AWS Summit Tokyo 2017での@twadaの講演で聞いたことがありましたが、今回初めて使いました。

Dockerコンテナ内でLocalStackを使う

下記のように、Dockerコンテナを構成していたとします。

# docker-compose.yml
version: '3'
services:
  app:
    build: .
    env_file: .env
    volumes:
      - .:/app
      - ~/.aws:/root/.aws
    working_dir: /app
    links:
      - localstack
  localstack:
    image: localstack/localstack
    ports:
      - '8080:8080'
      - '4576:4576' # For SQS

appコンテナから任意のQueueにメッセージを送信しようとすると、QueueUrlhttp://localhost:4576/queue/{QueueName}となり、下記のようにエラーが発生します。

Aws\Sqs\Exception\SqsException: Error executing "SendMessage" on "http://localhost:4576/queue/{QueueName}"; 
AWS HTTP error: cURL error 7: Failed to connect to localhost port 4576: Connection refused (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

appコンテナとlocalstackコンテナは、別のIPアドレスになるわけで、localhostではなくホスト名のlocalstackでアクセスしたいのですが、何故かlocalhostQueueUrlを返してきます。
もちろん、endpointは、http://localstack:4576を指定しています。

解決方法

READMEに解決方法が記載されていました。

`HOSTNAME_EXTERNAL`: Name of the host to expose the services externally (defaults to `localhost`). 
This host is used, e.g., when returning queue URLs from the SQS service to the client.

要するに、環境変数HOSTNAME_EXTERNALlocalstackを指定すればいいのです。

# docker-compose.yml
  localstack:
    image: localstack/localstack
    environment:
      - HOSTNAME_EXTERNAL=localstack

無事、QueueUrlhttp://localstack:4576/queue/{QueueName}となり、メッセージを送受信できるようになりました。

おわりに

@twadaが講演の中でおっしゃっていますが、LocalStackのようなFake Objectを使うことで、テストのために、依存ライブラリをインストールする必要がなくなり、テストもスッキリしますし、素早く開発が行えます。

今回のように、つまづくポイントがあったら、一つ一つ記事にしていきたいと思います。
ではでは。