

ECS FargateでnginxとNode.js動かすなら、まずtask cpu 512 / memory 1024でよさそう
この記事は、構成と文章の整理にAIを使っています。
あくまで読みやすくするための補助で、内容そのものをAIにすべて任せて書いているわけではありませんが、ところどころ相談しながら整えています。
ECS FargateでnginxとNode.jsを1タスクに載せる構成、CPU/メモリどれくらい割り振ればいいのか毎回悩むので一旦基準を決めた。
先に:Node.jsならnginx自体が不要なことが多い
前提として、ALB配下でNode.js(Express / Fastify など)を動かすだけなら、nginxをsidecarに載せる必然性は薄い。TLS終端・ヘルスチェック・ルーティングはALBが担うので、ALB → Node.js 直結で足りるケースがほとんど。
要否の判断軸は ALB配下のEC2でnginxって要る?フレームワーク別に見てみた にまとめた。ECS Fargateでも同じ考え方でよい。
この記事の配分例は、「すでにnginx+Node.jsの2コンテナ構成になっている/外すコストのほうが高い」場合の出発点として読むのがよい。
結論
SSRなし、主にCRUDみたいな軽めのAPIなら、こんな感じで始めればよさそう。
Task: cpu: 512 memory: 1024
nginx: cpu: 96 memoryReservationMiB: 128 memoryLimitMiB: 256
node: cpu: 416 memoryReservationMiB: 704 memoryLimitMiB: 896 command: - node - --max-old-space-size=512nginxは軽いのでメモリもCPUも小さめでいい。Node.js側に寄せる。
もう少しアクセスが多い環境(数十〜数百RPS)なら task cpu 1024 / memory 2048 くらいに上げる。重い処理があるならさらに cpu 2048 / memory 4096。
memoryReservationMiBとmemoryLimitMiBの違い
memoryReservationMiB: ソフトリミット。ECSがスケジューリング判断に使う値で、実際はこれを超えて使っても即座には落ちないmemoryLimitMiB: ハードリミット。これを超えるとOOM Killされる
なので普段の使用量をreservationに、瞬間的に許容できる上限をlimitに置く、というのが基本の考え方らしい。
あと、各コンテナのreservation/limitを単純に足し算してもTask全体のメモリ上限にはならない。Task Memoryを超えたらそこでOOMになるので、コンテナごとの割り当てはTask全体の枠内に収まるように決める必要がある。
CDKで書くとハマったポイント
FargateTaskDefinition にタスクレベルのメモリを渡すとき、memoryMiB を指定すると通らない。
// これは動かないconst task = new ecs.FargateTaskDefinition(this, 'Task', { cpu: 512, memoryMiB: 1024,});memoryMiB はEC2/Fargate共通の基底クラスTaskDefinition用のプロパティで、Fargate専用のFargateTaskDefinitionでは存在しない。正しくはmemoryLimitMiB。
const task = new ecs.FargateTaskDefinition(this, 'Task', { cpu: 512, memoryLimitMiB: 1024,});コンテナ単位のaddContainerではmemoryReservationMiB/memoryLimitMiBのままでいいので、タスクレベルとコンテナレベルで名前の対応が微妙にずれてるのが混乱ポイントだった。
運用で見る指標
一旦小さめで始めて、以下を見ながらスケールを決める。
- CPUUtilization が60%を超えてくる
- MemoryUtilization が70%を超えてくる
- ALBのTargetResponseTime p95が300msを超えてくる
このあたりが継続的に厳しければ、まずタスク数を増やす(スケールアウト)。それでも常時高いなら cpu/memory 自体を1段階上げる(スケールアップ)方向で考える。