tl;dr
- ローカルでShoryukenの開発をするためにSQSのmockとなるものをたてたい
- 簡単のためにdocker-composeを使いたい
- SQSの代替としてElasticMQを使う
- motoやlocalstackだと罠がある
Shoryukenをローカル開発するときの問題点
Shoryukenを起動するにはSQSに繋ぐ必要がありますがローカルからAWSに繋げたくないので、SQSコンパチのミドルウェアをなんらかローカルで起動する必要がありまが、Shoryukenのwikiをみるとmotoを使えばできるよ、と書いてあります。
たしかにmotoをインストールして、そこにつなぐようにすればローカルで開発できますが、開発環境構築に手間がかかってしまうので、やっぱりdocker-compose up
一発で済ませたいところです。
Dockerでmotoを使う上での問題点
docker-composeするためにmotoのDockerイメージがほしいわけなんですが、motoのofficialなイメージはありません。1
なにかいいのないかな?って思ってたところにlocalstackの存在を思いだしました。
こちらはofficialなイメージが存在します。
いい感じです。
localstackとdocker-compose up
の問題点
localstackのrepositoryにはdocker-compose.ymlがおいてあるので、これを参考にShoryuken workerとlinkさせればうまくいきそうです。
以下のような感じでしょうか。
version: '3.2'
services:
worker:
build: .
command: ["shoryuken", "-C", "config/shoryuken.yml"]
tmpfs:
- /app/tmp
volumes:
- .:/app
- bundle_install:/usr/local/bundle
depends_on:
- sqs
environment:
RAILS_ENV: ${RAILS_ENV:-development}
SQS_URL: http://sqs:4576
sqs:
image: localstack/localstack
environment:
- SERVICES=sqs
- DOCKER_HOST=unix:///var/run/docker.sock
ports:
- 4576:4576
volumes:
- localstack:/tmp/localstack
- /var/run/docker.sock:/var/run/docker.sock
volumes:
bundle_install:
localstack:
しかしながら、これでdocker-compose up
してもworkerがSQSに接続できず、起動しません。
どうやらlocalstackはcontainerが立ち上がってすぐにSQSに繋げるわけではなく、container起動後指定したSERVICES
起動していく仕組み2らしく、depends_on
を指定していてもworkerから繋げません。
Shoryukenは起動時にSQSに接続して、queueが存在するかどうか確認してエラーだったら落ちてしまうのでこれだと使えません。
試してないですが、これはmotoも同じ3(たぶん)なので、別の手段を考える必要があります。
(追記)
Dockerのofficialドキュメントに記述がありました。
wait-if-forなどでwrapすることで、TCPコネクションをみて起動するのがよさそうです。
これだとlocalstackでもいけるかも。(confのmount次第)
ElasticMQを使う
localstackのSQS部分はElasitcMQを起動しているんですが、localstackを挟まずに直でElasticMQを使うようにしてみます。
結論として、これならdepends問題は解消されます。
ElasitcMQのDockerイメージはs12v/elasticmqを使うことにします。
version: '3.2'
services:
worker:
build: .
command: ["shoryuken", "-C", "config/shoryuken.yml"]
tmpfs:
- /app/tmp
volumes:
- .:/app
- bundle_install:/usr/local/bundle
depends_on:
- sqs
environment:
RAILS_ENV: ${RAILS_ENV:-development}
SQS_URL: http://sqs:9324
sqs:
image: s12v/elasticmq
ports:
- 9324:9324
volumes:
bundle_install:
実はこれでもだめで、SQS自体には繋げるのですがまだcreate queueされてないのでやはりworkerが落ちてしまうのです。
worker起動前にcreate queueの処理を挟むか?とか考えますが、他にいい方法はないのでしょうか?
elasticmq.conf
をmountして解決する
色々ググってMocking SQS with ElasticMQ and docker-composeという記事を発見4しました。
Done! Enjoy your queue on port 9324! Happy messaging!
Not so fast, we are still not done here: as we are most likely using elasticMQ for testing, we also do not want to manually create our queues. We can provide a config file describing the queues we want to be in place:
ってことでconfig fileをおいておけばqueueが勝手に作られるらしい。
以下のようなconfigを用意します。
node-address {
protocol = http
host = sqs
port = 9324
context-path = ""
}
rest-sqs {
enabled = true
bind-port = 9324
bind-hostname = "0.0.0.0"
sqs-limits = strict
}
generate-node-address = false
queues {
default{ }
}
queues
の中に作っておきたいqueue5を書いておくのと、node-address.host
にdocker-compose経由で参照するhost名指定します。
そしてこれをmountする。
version: '3.2'
services:
worker:
build: .
command: ["shoryuken", "-C", "config/shoryuken.yml"]
tmpfs:
- /app/tmp
volumes:
- .:/app
- bundle_install:/usr/local/bundle
depends_on:
- sqs
environment:
RAILS_ENV: ${RAILS_ENV:-development}
SQS_URL: http://sqs:9324
sqs:
image: s12v/elasticmq
ports:
- 9324:9324
volumes:
- ./config/elasticmq.conf:/etc/elasticmq/elasticmq.conf
volumes:
bundle_install:
$ docker-compose up -d
$ aws --endpoint-url=http://localhost:9324 sqs list-queues
{
"QueueUrls": [
"http://sqs:9324/queue/default"
]
}
無事workerも起動しました