docker compose cliでecsにデプロイした話
TL; DR
docker compose ecs integrationとは
- Deploy applications on Amazon ECS using Docker Compose | Containers
- Docker Compose for Amazon ECS Now Available - Docker Blog
2020年11月に発表されて、待望の機能が来たと結構な反響があったように思います
仕事でPhoenixのアプリを作る機会があり、そこでこのスタックを採用したのでハマったところを紹介していきます
概要、必要なこと、アーキテクチャなどはほぼ以下のドキュメントに書いてあるのでそちらをご覧ください
ふわっとまとめると、docker-compose.ymlに基づいてAWSのリソースを良い感じに用意してくれるコマンドです
ハマったところ
ECSって何、ECRって何
本当に無知でdockerをデプロイできるサービスぐらいにしかECSを理解していなかった
そのため、ECRって何という状態だった
- ECSはElastic Container Service
- ECRはElastic Container Registry
ECRはDocker HubみたいにDocker imageをhostingできるサービス
ECSはcluster
を作成して、task
を定義して、service
を実行するものっぽい
clusterはEC2なんかのコンピューティングリソース
taskはその名の通り仕事、実体的には単数 or 複数のdockerのcontainer定義
serviceはtaskをclusterで何個走らせるかを決める
これらを統合して、docker compose cliを使うとデプロイはこんな感じになるはず
- サーバーを書く
- buildしてDocker imageに固める
- ECRなどのDocker image hosting serviceにpushする
docker compose up
port:80が使えない
Unix系のOSにて、デフォルトでは1024以下のportはroot権限がないと使用できないらしい
- javascript - Error: listen EACCES 0.0.0.0:80 OSx Node.js - Stack Overflow
- unix - Why are ports below 1024 privileged? - Stack Overflow
これを回避する方法は以下
- nginxでリバースプロキシを立てて、アプリサーバーを直接ALBに紐付けない
- rootユーザーでアプリサーバーを起動する
- port mappingする
2はセキュリティ的に推奨される感じではなさそうです
3はecs integrationではサポートされていません
このあたりはいかに詳しいです
- ECS integration Compose features | Docker Documentation
- ECS integration composefile examples | Docker Documentation
- Docker-ECS load balancer, HTTPS and routing · Issue #1472 · docker/compose-cli · GitHub
別のcontainerで立つ以上portのabstractionは利がない & compose specがroutingに関することに関与しないのでECS integrationでもそれを踏襲する方針のようです
この事実が分かるまで、いつものlocal開発向けのdocker-compose.ymlのように80:4000
をやろうとしてdocker compose up
でエラーを踏んでissueを漁りドキュメントを読むというのを繰り返しました
ということで、素直に1でいきます
nginx.confを書いて、アプリサーバーと同じくbuildしてECRにpushして解決
その際に、後述のサービス検出の話でハマりました
サービス検出
英語だとService Discovery
恥ずかしながらService Discoveryが何を指しているかさっぱり分かっていなかったが少し理解した
nginxでリバースプロキシを立てたが、どうやってnginxに来た通信をpPhoenixのアプリサーバーに向けるのかという話
つまり、ECSでcontainer間通信を実現する方法が分からなくてハマりました
実はドキュメントに書いてあります
Deploying Docker containers on ECS | Docker Documentation
Services are registered automatically by the Docker Compose CLI on AWS Cloud Map during application deployment. They are declared as fully qualified domain names of the form:
<service>.<compose_project_name>.local.
app.hoge-project.local
のようなドメインでサービスのcontainer間で通信ができるようになります
当初やりたいことがService Discoveryであることが分かっていなかったため、いろんなクエリでググった末に以下のページにたどり着いてようやく理解できました
ということでnginx.confにphoenixのアプリサーバーのドメイン名を書いて完了
Migration
これはハマったというよりもハックで乗り切った感じの話
基本的にサーバーを書いていると発生するMigrationですが、それをECSのサービスとして定義するとdocker compose cliの仕様上、ちょっと困ったことになります
docker compose convert
をすると分かりますが、service.deploy.replicas
に値を設定しないとECSのサービス定義のdesiredCountは1にデフォルトで設定されます
そのため、DB migrationのサービスが起動 -> 正常終了 -> desiredCountが1なので、再度起動 -> 正常終了のループを延々と繰り返します
最初はdocker compose conver
で生成されたCloudFormation templateをカスタマイズしようと思いましたが、上手いこといかなかったので方針を切り替えました
結果、docker compose upを走らせた後に、migrationの終了を確認してからマネジメントコンソールでNumber of Taskを0にするように手動で回避しています
この辺、上手い方法があったら教えていただけると 🙏
Command support
ecs contextでsupportされているコマンドは筆者が試した限りでは以下だけでした。
- docker compose up
- docker compose down
- docker compose logs
- docker compose convert
runが使えないので上述のDB migrationで困ったりしてました
runはsupportしてほしいという要望が既に上がっています
Add docker run support to ECS · Issue #829 · docker/compose-cli · GitHub
ちなみにdocker compose down
をするとupで作成されたすべてのAWSリソース(既存のリソースは除く)が破棄されるのでお気をつけください
既存のAWSリソースの使用
ここに説明があります
Deploying Docker containers on ECS | Docker Documentation
VPCだけでいけるかと思いましたが、ドメインのヒモ付のため、LBも既存のものを使うようにしました
最後に
docker compose ecs integration、まだ荒削りな部分もありますが、production運用も十分に視野に入ってくると思います
もちろん、凝ったことをやろうとすると足りない部分も多いのでそのあたりはissueに起票したりでfeedbackしていくと良さそうです
これで、好きな言語やフレームワークでサーバーをcontainerにしてデプロイするのが簡単になりました
どんどん使っていきたいところ
おしまい