- AWS
ECSタスク定義JSONの書き方|Fargate必須項目と環境変数secrets
ECS のタスク定義は、「どのイメージを、どれだけの CPU とメモリで、どんな環境変数とログ設定で動かすか」を書いた JSON で、Fargate で使う場合は family・networkMode(awsvpc)・cpu・memory・containerDefinitions の5つが土台になります。 ここに環境変数(environment)、機密情報(secrets)、ログ設定(logConfiguration)を足していくと、運用で使える形になります。
この記事では、Fargate 向けの最小の JSON から始めて、項目を1つずつ足した完成形までを、register-task-definition と describe-task-definition の出力つきで載せます。項目ごとの必須・任意と cpu・memory の組み合わせは早見表にし、describe の出力をそのまま再登録するときに削る項目、登録時に出るエラー文も扱います。
確認環境:Ubuntu 24.04 / AWS CLI 1.46.1 / jq 1.7。AWS の API をローカルで再現するツール(moto 5.2.3)で実行しています。掲載コマンドは接続先の指定を外してあり、実際の AWS でそのまま使える形です。アカウント ID は 123456789012、リージョンは ap-northeast-1 で統一しています。Fargate に固有の要件(ネットワークモード、cpu と memory の組み合わせ、ロールが必要になる条件、secrets の書式)は、AWS 公式ドキュメントの記載に沿っています。
タスク定義の項目早見表(Fargate)
タスク全体の項目
| 項目 | Fargate での扱い | 値の例 | 意味 |
|---|---|---|---|
| family | 必須 | "web-app" |
タスク定義の名前。登録のたびにリビジョン番号が増える |
| containerDefinitions | 必須 | コンテナ定義の配列 | 動かすコンテナの設定 |
| networkMode | 必須(awsvpc) |
"awsvpc" |
Fargate のタスクは awsvpc を使う |
| cpu | 必須 | "256" |
タスク全体の CPU。文字列で書く |
| memory | 必須 | "512" |
タスク全体のメモリ(MiB)。文字列で書く |
| requiresCompatibilities | 任意(書くのがおすすめ) | ["FARGATE"] |
Fargate の要件を満たすかを登録時に確かめる指定 |
| executionRoleArn | 条件つきで必須 | ロールの ARN | ECR のプライベートリポジトリからの pull、awslogs、secrets を使うときに必要 |
| taskRoleArn | 任意 | ロールの ARN | コンテナの中のアプリが AWS の API を呼ぶときの権限 |
| runtimePlatform | 任意 | {"cpuArchitecture":"X86_64","operatingSystemFamily":"LINUX"} |
CPU の種類と OS。省略時は X86_64 と LINUX |
コンテナ定義(containerDefinitions の要素)の項目
| 項目 | 扱い | 値の例 | 意味 |
|---|---|---|---|
| name | 必須 | "web" |
コンテナの名前 |
| image | 必須 | "...amazonaws.com/myapp/web:v1.2.0" |
イメージの URI。タグを省くと latest |
| essential | 任意(省略時 true) | true |
true のコンテナが止まると、タスク全体が止まる。少なくとも1つは true にする |
| portMappings | 任意 | [{"containerPort":8080}] |
公開するポート。awsvpc では containerPort だけ書けばよい |
| environment | 任意 | [{"name":"APP_ENV","value":"production"}] |
環境変数。値がそのまま JSON に残る |
| secrets | 任意 | [{"name":"DB_PASSWORD","valueFrom":"arn:..."}] |
Secrets Manager や Parameter Store の値を環境変数として渡す |
| logConfiguration | 任意 | {"logDriver":"awslogs","options":{...}} |
ログの送り先。Fargate で使えるのは awslogs・splunk・awsfirelens |
| healthCheck | 任意 | {"command":["CMD-SHELL","..."]} |
コンテナの中で実行するヘルスチェック |
「必須」「任意」と値の決まりは、AWS 公式ドキュメント「Fargate の Amazon ECS タスク定義パラメータ」の記載に基づいています。
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ECSタスク定義JSONの書き方|Fargate必須項目と環境変数secrets」
Fargate 向けの最小のタスク定義 JSON
次の JSON を taskdef-min.json として保存します。公開されている nginx のイメージを1つ動かすだけの形です。
{
"family": "web-min",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "256",
"memory": "512",
"containerDefinitions": [
{
"name": "web",
"image": "public.ecr.aws/nginx/nginx:stable",
"essential": true,
"portMappings": [
{ "containerPort": 80, "protocol": "tcp" }
]
}
]
}
登録する(register-task-definition)
aws ecs register-task-definition --cli-input-json file://taskdef-min.json
{
"taskDefinition": {
"taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-min:1",
"containerDefinitions": [
{
"name": "web",
"image": "public.ecr.aws/nginx/nginx:stable",
"cpu": 0,
"portMappings": [
{
"containerPort": 80,
"protocol": "tcp"
}
],
"essential": true,
"environment": [],
"mountPoints": [],
"volumesFrom": []
}
],
"family": "web-min",
"networkMode": "awsvpc",
"revision": 1,
"volumes": [],
"status": "ACTIVE",
"placementConstraints": [],
…(省略)…
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "256",
"memory": "512"
}
}
出力から分かることは3つあります。
- taskDefinitionArn の末尾の
:1がリビジョン番号です。同じ family で登録するたびに 2、3 と増えます - 書かなかった項目(コンテナの cpu、environment、mountPoints、volumesFrom、volumes など)が、既定値で補われて返ります
- revision、status、taskDefinitionArn は ECS が付ける項目で、入力の JSON には書きません
各項目の書き方の注意
| 項目 | 注意 |
|---|---|
| cpu / memory(タスク全体) | 引用符で囲んだ文字列で書く。 数値で書くと CLI の検証で止まる(後述のエラー文) |
| networkMode | Fargate では awsvpc。タスクごとに専用のネットワークインターフェイスが付く |
| portMappings | awsvpc では containerPort だけを書く。hostPort は省くか、containerPort と同じ値にする |
| image | ECR のプライベートリポジトリを使うときは、executionRoleArn も必要になる |
JSON ファイルを使わずにオプションで渡す形
項目が少なければ、コンテナ定義だけをファイルにして、残りをオプションで渡すこともできます。containers.json は containerDefinitions の配列部分だけを取り出したものです。
aws ecs register-task-definition \
--family web-cli \
--network-mode awsvpc \
--requires-compatibilities FARGATE \
--cpu 256 --memory 512 \
--container-definitions file://containers.json \
--query 'taskDefinition.[family,revision,cpu,memory]' --output text
web-cli 1 256 512
項目が増えると --cli-input-json で1つのファイルにまとめるほうが、差分を追いやすくなります。使える項目の一覧は aws ecs register-task-definition --generate-cli-skeleton で出力できます。
cpu と memory の有効な組み合わせ早見表
Fargate では、cpu と memory は決まった組み合わせの中から選びます。 AWS 公式ドキュメントの表を、タスク定義に書く値(cpu は CPU ユニット、memory は MiB)に直すと次のようになります。MiB の値は 1 GB を 1024 として換算したものです。
| cpu に書く値 | vCPU | memory に書ける値(MiB) | 公式の表記 | 対応 OS |
|---|---|---|---|---|
"256" |
0.25 | "512" "1024" "2048" |
512 MiB、1 GB、2 GB | Linux |
"512" |
0.5 | "1024" "2048" "3072" "4096" |
1〜4 GB | Linux |
"1024" |
1 | "2048" から "8192" まで 1024 刻み |
2〜8 GB | Linux、Windows |
"2048" |
2 | "4096" から "16384" まで 1024 刻み |
4〜16 GB(1 GB 刻み) | Linux、Windows |
"4096" |
4 | "8192" から "30720" まで 1024 刻み |
8〜30 GB(1 GB 刻み) | Linux、Windows |
"8192" |
8 | "16384" から "61440" まで 4096 刻み |
16〜60 GB(4 GB 刻み) | Linux |
"16384" |
16 | "32768" から "122880" まで 8192 刻み |
32〜120 GB(8 GB 刻み) | Linux |
"32768" |
32 | "61440" "122880" "249856" |
60 GB、120 GB、244 GB | Linux |
8 vCPU 以上は、Linux のプラットフォームバージョン 1.4.0 以降が必要です。
表にない組み合わせで登録すると、公式ドキュメント「Amazon ECS のタスク定義の無効な CPU またはメモリエラーのトラブルシューティング」によれば、AWS CLI では次のメッセージが返ります。
An error occurred (ClientException) when calling the RegisterTaskDefinition operation: Invalid 'cpu' setting for task.
同じページには、Terraform を使った場合は ClientException: No Fargate configuration exists for given values. と表示されることも載っています。どちらのメッセージも、まず上の表で cpu と memory の組を確かめるのが近道です。
環境変数を足す(environment)
機密ではない設定値は environment に書きます。name と value の組を並べる形です。
"environment": [
{ "name": "APP_ENV", "value": "production" },
{ "name": "LOG_LEVEL", "value": "info" }
]
- value は文字列です。数値や真偽値も
"8080""true"のように引用符で囲みます - environment の値は、タスク定義の JSON にそのまま残ります。describe-task-definition を実行できる人なら誰でも読めるので、パスワードや API キーは次の secrets に書きます
機密情報を渡す(secrets と valueFrom の書式)
secrets は、値そのものではなく「値の置き場所」を書く項目です。タスクの起動時に ECS が Secrets Manager や Systems Manager Parameter Store から値を取り出し、name に書いた名前の環境変数としてコンテナに渡します。
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/web/db-AbCdEf:password::"
},
{
"name": "API_TOKEN",
"valueFrom": "arn:aws:ssm:ap-northeast-1:123456789012:parameter/prod/web/api-token"
}
]
Secrets Manager の valueFrom
AWS 公式ドキュメント「Amazon ECS 環境変数を使用して Secrets Manager シークレットを渡す」に載っている書式です。
arn:aws:secretsmanager:region:aws_account_id:secret:secret-name:json-key:version-stage:version-id
後ろの3つ(json-key、version-stage、version-id)は省略できますが、省略するときもコロンは残します。
| 渡したいもの | valueFrom の末尾 | 例 |
|---|---|---|
| シークレット全体 | 何も付けない | ...:secret:prod/web/db-AbCdEf |
| JSON の中の1つのキー | :キー名:: |
...:secret:prod/web/db-AbCdEf:password:: |
| 特定のステージの値 | ::ステージ名: |
...:secret:prod/web/db-AbCdEf::AWSPREVIOUS: |
| 特定のバージョン ID の値 | :::バージョンID |
...:secret:prod/web/db-AbCdEf:::9d4cb84b-ad69-40c0-a0ab-cead3EXAMPLE |
- json-key を省くと、シークレットの中身全体が1つの環境変数に入ります。JSON で保存したシークレットなら、JSON の文字列がそのまま入ります
- version-stage と version-id は同時には指定できません。どちらも省くと、現在の値(AWSCURRENT)が使われます
- シークレット名の後ろの
-AbCdEfは、Secrets Manager が ARN に付ける6文字です。ARN はaws secretsmanager describe-secret --secret-id 名前 --query ARNで確かめられます
Parameter Store の valueFrom
AWS 公式ドキュメント「Amazon ECS 環境変数を使用して Systems Manager パラメータを渡す」によると、書き方は2通りあります。
| 条件 | 書き方 | 例 |
|---|---|---|
| タスクと同じリージョンのパラメータ | 完全な ARN、またはパラメータ名 | arn:aws:ssm:ap-northeast-1:123456789012:parameter/prod/web/api-token |
| 別のリージョンのパラメータ | 完全な ARN | arn:aws:ssm:us-east-1:123456789012:parameter/prod/web/api-token |
値が渡されるタイミング
どちらのページにも、機密情報はコンテナが最初に起動するときに渡され、あとでシークレットを更新・ローテーションしても、動いているコンテナには自動では反映されないと書かれています。新しい値を使うには、新しいタスクを起動するか、サービスを「新しいデプロイの強制」つきで更新します。
environment と secrets の使い分け
| 観点 | environment | secrets |
|---|---|---|
| タスク定義に残るもの | 値そのもの | 値の置き場所(ARN) |
| 向いている値 | 動作モード、ログレベル、接続先のホスト名 | パスワード、API キー、トークン |
| 必要なロール | なし | executionRoleArn(値を読む権限つき) |
| 値を変えたとき | タスク定義を登録し直す | タスクを起動し直す |
ログ設定を足す(logConfiguration と awslogs)
コンテナの標準出力と標準エラー出力を CloudWatch Logs に送る設定です。
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/web-app",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "web"
}
}
| オプション | 扱い | 意味 |
|---|---|---|
| awslogs-group | 必須 | 送り先のロググループ名 |
| awslogs-region | 必須 | ロググループがあるリージョン |
| awslogs-stream-prefix | 必須 | ログストリーム名の先頭に付く文字列 |
| awslogs-create-group | 任意(既定は false) | "true" にするとロググループを自動で作る |
| mode | 任意 | non-blocking または blocking |
| max-buffer-size | 任意(既定は 10m) | non-blocking のときのバッファの大きさ |
この表は公式ドキュメントのタスク定義パラメータのページに基づいています。options の値もすべて文字列で書きます。
awslogs を使うときは executionRoleArn が必要です。ロググループを先に作っておく場合は、次のコマンドを使います。
aws logs create-log-group --log-group-name /ecs/web-app
2つのロール:executionRoleArn と taskRoleArn
名前が似ていますが、使う場面が違います。
| 項目 | 誰が使うか | 何のために使うか | 必要になるとき |
|---|---|---|---|
| executionRoleArn(タスク実行ロール) | ECS と Fargate のエージェント | イメージの pull、ログの送信、secrets の取得 | ECR のプライベートリポジトリ、awslogs、secrets のどれかを使うとき |
| taskRoleArn(タスクロール) | コンテナの中のアプリ | アプリが AWS の API(S3 や DynamoDB など)を呼ぶ | アプリが AWS のサービスを使うとき |
タスク実行ロールを作る
信頼ポリシーを ecs-tasks-trust-policy.json として保存します。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": { "Service": "ecs-tasks.amazonaws.com" },
"Action": "sts:AssumeRole"
}
]
}
aws iam create-role \
--role-name ecsTaskExecutionRole \
--assume-role-policy-document file://ecs-tasks-trust-policy.json \
--query Role.Arn
"arn:aws:iam::123456789012:role/ecsTaskExecutionRole"
AWS 公式ドキュメント「Amazon ECS タスク実行 IAM ロール」では、続けて管理ポリシー AmazonECSTaskExecutionRolePolicy を付ける手順が載っています。
aws iam attach-role-policy \
--role-name ecsTaskExecutionRole \
--policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
secrets を使うときに足す権限
secrets を使う場合は、タスク実行ロールに「値を読む権限」を足します。次の JSON を secrets-access.json として保存し、インラインポリシーとして付けます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"secretsmanager:GetSecretValue",
"ssm:GetParameters"
],
"Resource": [
"arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/web/db-AbCdEf",
"arn:aws:ssm:ap-northeast-1:123456789012:parameter/prod/web/api-token"
]
}
]
}
aws iam put-role-policy \
--role-name ecsTaskExecutionRole \
--policy-name secrets-access \
--policy-document file://secrets-access.json
Resource には、valueFrom に書いたシークレットやパラメータだけを並べると、読める範囲を必要な分に絞れます。公式ドキュメントの例には、この2つのアクションに加えて kms:Decrypt と鍵の ARN も含まれています。
完成形のタスク定義 JSON
ここまでの項目をまとめた形です。taskdef-full.json として保存します。
{
"family": "web-app",
"networkMode": "awsvpc",
"requiresCompatibilities": ["FARGATE"],
"cpu": "512",
"memory": "1024",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"taskRoleArn": "arn:aws:iam::123456789012:role/web-app-task-role",
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"containerDefinitions": [
{
"name": "web",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/web:v1.2.0",
"essential": true,
"portMappings": [
{ "containerPort": 8080, "protocol": "tcp" }
],
"environment": [
{ "name": "APP_ENV", "value": "production" },
{ "name": "LOG_LEVEL", "value": "info" }
],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/web/db-AbCdEf:password::"
},
{
"name": "API_TOKEN",
"valueFrom": "arn:aws:ssm:ap-northeast-1:123456789012:parameter/prod/web/api-token"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/web-app",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "web"
}
},
"healthCheck": {
"command": ["CMD-SHELL", "curl -f http://localhost:8080/health || exit 1"],
"interval": 30,
"timeout": 5,
"retries": 3,
"startPeriod": 10
}
}
]
}
healthCheck の command はコンテナの中で実行されるので、イメージに curl が入っていることが前提です。interval は 5〜300 秒、timeout は 2〜60 秒、retries は 1〜10 回、startPeriod は 0〜300 秒の範囲で指定します(公式ドキュメントのタスク定義パラメータより)。ARM 向けのイメージを使うときは、cpuArchitecture を ARM64 にします。
登録して確かめる
aws ecs register-task-definition --cli-input-json file://taskdef-full.json \
--query 'taskDefinition.[taskDefinitionArn,status]'
[
"arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:1",
"ACTIVE"
]
登録した内容を見る(describe-task-definition)
aws ecs describe-task-definition --task-definition web-app
{
"taskDefinition": {
"taskDefinitionArn": "arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:1",
"containerDefinitions": [
{
"name": "web",
"image": "123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/web:v1.2.0",
"cpu": 0,
"portMappings": [
{
"containerPort": 8080,
"protocol": "tcp"
}
],
"essential": true,
"environment": [
{
"name": "APP_ENV",
"value": "production"
},
{
"name": "LOG_LEVEL",
"value": "info"
}
],
"mountPoints": [],
"volumesFrom": [],
"secrets": [
{
"name": "DB_PASSWORD",
"valueFrom": "arn:aws:secretsmanager:ap-northeast-1:123456789012:secret:prod/web/db-AbCdEf:password::"
},
{
"name": "API_TOKEN",
"valueFrom": "arn:aws:ssm:ap-northeast-1:123456789012:parameter/prod/web/api-token"
}
],
"logConfiguration": {
"logDriver": "awslogs",
"options": {
"awslogs-group": "/ecs/web-app",
"awslogs-region": "ap-northeast-1",
"awslogs-stream-prefix": "web"
}
},
"healthCheck": {
…(省略)…
}
}
],
"family": "web-app",
"taskRoleArn": "arn:aws:iam::123456789012:role/web-app-task-role",
"executionRoleArn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole",
"networkMode": "awsvpc",
"revision": 1,
"volumes": [],
"status": "ACTIVE",
"placementConstraints": [],
…(省略)…
"runtimePlatform": {
"cpuArchitecture": "X86_64",
"operatingSystemFamily": "LINUX"
},
"requiresCompatibilities": [
"FARGATE"
],
"cpu": "512",
"memory": "1024"
}
}
secrets は valueFrom の ARN のまま返り、値そのものは出力に現れません。 environment の値はそのまま見えます。
--task-definition の指定のしかたで、取れるリビジョンが変わります。
| 指定 | 取れるもの |
|---|---|
web-app |
その family の、ACTIVE な最新リビジョン |
web-app:1 |
リビジョン 1 |
| 完全な ARN | その ARN のリビジョン |
一部だけ確かめたいときは --query を使います。
aws ecs describe-task-definition --task-definition web-app \
--query 'taskDefinition.containerDefinitions[0].[name,image,logConfiguration.options."awslogs-group"]'
[
"web",
"123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/web:v1.2.0",
"/ecs/web-app"
]
特定の環境変数の値だけを取り出す例です。
aws ecs describe-task-definition --task-definition web-app \
--query 'taskDefinition.containerDefinitions[0].environment[?name==`APP_ENV`].value | [0]' \
--output text
production
describe の出力を再登録するときに削る項目
「今のタスク定義を取り出して、少し変えて登録し直す」はよく使う流れです。ただし、describe-task-definition の出力には ECS が付けた項目が混ざっているので、そのままでは登録できません。
aws ecs describe-task-definition --task-definition web-app \
--query taskDefinition > described.json
aws ecs register-task-definition --cli-input-json file://described.json
Parameter validation failed:
Unknown parameter in input: "taskDefinitionArn", must be one of: family, taskRoleArn, executionRoleArn, networkMode, containerDefinitions, volumes, placementConstraints, requiresCompatibilities, cpu, memory, tags, pidMode, ipcMode, proxyConfiguration, inferenceAccelerators, ephemeralStorage, runtimePlatform, enableFaultInjection
Unknown parameter in input: "revision", must be one of: …(省略)…
Unknown parameter in input: "status", must be one of: …(省略)…
Unknown parameter in input: "compatibilities", must be one of: …(省略)…
削る項目の一覧
AWS CLI 1.46.1 が持っている API の定義で、「describe の出力(taskDefinition)にあって、register の入力にない項目」を突き合わせた結果です。
| 削る項目 | 中身 |
|---|---|
| taskDefinitionArn | 登録時に ECS が付ける ARN |
| revision | リビジョン番号 |
| status | ACTIVE / INACTIVE などの状態 |
| requiresAttributes | タスクを置くために必要な属性の一覧 |
| compatibilities | このタスク定義が使える起動タイプ |
| registeredAt | 登録日時 |
| registeredBy | 登録した人やロール |
| deregisteredAt | 登録解除の日時 |
| deleteRequestedAt | 削除を要求した日時 |
出力に含まれない項目もありますが、この9つをまとめて削る形にしておくと、どのタスク定義でも同じコマンドが使えます。 なお、タグ(tags)は describe の taskDefinition には含まれないので、付け直したい場合は登録時に --tags で指定します。
jq で削って再登録する
jq 'del(.taskDefinitionArn, .revision, .status, .requiresAttributes,
.compatibilities, .registeredAt, .registeredBy,
.deregisteredAt, .deleteRequestedAt)' described.json > cleaned.json
aws ecs register-task-definition --cli-input-json file://cleaned.json \
--query 'taskDefinition.[family,revision]' --output text
web-app 2
リビジョン 2 として登録できました。
イメージのタグだけ変えて新しいリビジョンを作るスクリプト
デプロイのたびに使う「イメージだけ差し替えて登録し直す」処理を、1本にまとめた例です。
#!/usr/bin/env bash
# 使い方: ./new-revision.sh ファミリー名 コンテナ名 新しいイメージURI
set -euo pipefail
FAMILY="$1"
CONTAINER="$2"
IMAGE="$3"
aws ecs describe-task-definition --task-definition "$FAMILY" \
--query taskDefinition --output json \
| jq --arg c "$CONTAINER" --arg img "$IMAGE" '
del(.taskDefinitionArn, .revision, .status, .requiresAttributes,
.compatibilities, .registeredAt, .registeredBy,
.deregisteredAt, .deleteRequestedAt)
| (.containerDefinitions[] | select(.name == $c) | .image) = $img
' > next.json
aws ecs register-task-definition --cli-input-json file://next.json \
--query 'taskDefinition.[taskDefinitionArn,containerDefinitions[0].image]' \
--output text
$ ./new-revision.sh web-app web 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/web:v1.3.0
arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:3 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/web:v1.3.0
リビジョン 3 が v1.3.0 のイメージで登録されました。リビジョン 1 は v1.2.0 のまま残っているので、戻したいときはサービスにリビジョン 1 を指定し直せます。
aws ecs describe-task-definition --task-definition web-app:1 \
--query 'taskDefinition.containerDefinitions[0].image' --output text
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/myapp/web:v1.2.0
リビジョンを一覧・登録解除・削除する
aws ecs list-task-definitions --family-prefix web-app
{
"taskDefinitionArns": [
"arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:1",
"arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:2",
"arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:3"
]
}
使わなくなったリビジョンは、登録解除(deregister)してから削除(delete)する、の2段階で片付けます。
aws ecs deregister-task-definition --task-definition web-app:1 \
--query 'taskDefinition.[taskDefinitionArn,status]'
[
"arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:1",
"INACTIVE"
]
登録解除したリビジョンは既定の一覧から外れ、--status INACTIVE を付けると表示されます。
aws ecs list-task-definitions --family-prefix web-app --status INACTIVE
{
"taskDefinitionArns": [
"arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:1"
]
}
aws ecs delete-task-definitions --task-definitions web-app:1 \
--query '[taskDefinitions[].[taskDefinitionArn,status],failures]'
[
[
[
"arn:aws:ecs:ap-northeast-1:123456789012:task-definition/web-app:1",
"DELETE_IN_PROGRESS"
]
],
[]
]
ACTIVE のまま削除しようとすると、コマンドは終了しますが failures に理由が入ります。
aws ecs delete-task-definitions --task-definitions web-app:2 \
--query '[taskDefinitions[].status,failures]'
[
[],
[
{
"arn": "web-app:2",
"reason": "The specified task definition is still in ACTIVE status. Please deregister the target and try again."
}
]
]
登録時に出るエラー文と直し方
実行して確かめたメッセージ
| 書き方 | 出たメッセージ | 直し方 |
|---|---|---|
| family を書いていない | Parameter validation failed: Missing required parameter in input: "family" |
family を足す |
cpu を数値で書いた("cpu": 256) |
Parameter validation failed: Invalid type for parameter cpu, value: 256, type: <class 'int'>, valid types: <class 'str'> |
"cpu": "256" と引用符で囲む |
| describe の出力をそのまま渡した | Unknown parameter in input: "revision", must be one of: family, taskRoleArn, ... |
前の章の9項目を削る |
| JSON のカンマが抜けている | Error parsing parameter 'cli-input-json': Invalid JSON: Expecting ',' delimiter: line 12 column 7 (char 266) |
メッセージの行と列を見て直す |
file:// を付けずにファイル名だけ渡した |
Error parsing parameter 'cli-input-json': Invalid JSON: Expecting value: line 1 column 1 (char 0) と JSON received: taskdef-min.json |
--cli-input-json file://taskdef-min.json にする |
| ファイル名を間違えた | Unable to load paramfile file://nofile.json: [Errno 2] No such file or directory: 'nofile.json' |
パスを確かめる |
| コンテナの image を書いていない | ClientException ... Container.image should not be null or empty. |
image を足す |
| コンテナの name を書いていない | ClientException ... Container.name should not be null or empty. |
name を足す |
| タスク全体にもコンテナにもメモリを書いていない | ClientException ... Invalid setting for container 'web'. At least one of 'memory' or 'memoryReservation' must be specified. |
タスク全体の memory(Fargate では必須)を足す |
| 無いリビジョンを describe した | ClientException ... DescribeTaskDefinition operation: Unable to describe task definition. |
aws ecs list-task-definitions --family-prefix 名前 で番号を確かめる |
| deregister でリビジョンを省いた | ClientException ... DeregisterTaskDefinition operation: Revision is missing. |
web-app:1 のように番号まで書く |
| 11 個以上をまとめて delete した | InvalidParameterException ... Size of TaskDefinition references list cannot exceed 10 |
10 個以下に分けて実行する |
「Parameter validation failed」と「Error parsing parameter」で始まるものは、AWS に送る前に CLI が手元で止めたものです。JSON の形や型の問題なので、ファイルを見直せば解決します。「An error occurred (ClientException)」は AWS 側で内容を確かめた結果です。
JSON の文法だけを先に確かめたいときは、jq . taskdef-full.json > /dev/null を実行すると、問題があれば行と列が表示されます。
Fargate の要件に関するチェック表
Fargate に固有の要件は、公式ドキュメントの記載をもとに、登録の前に次の表で確かめます。
| 確かめること | 公式ドキュメントの記載 |
|---|---|
| networkMode が awsvpc になっているか | Fargate のタスクには awsvpc ネットワークモードが必要 |
| タスク全体の cpu と memory を書いているか | Fargate ではタスクレベルの cpu と memory が必要。コンテナ単位の値は任意 |
| cpu と memory が有効な組み合わせか | 早見表の組み合わせから選ぶ。合わないと Invalid 'cpu' setting for task. |
| executionRoleArn を書いているか | ECR のプライベートリポジトリからの pull、awslogs、secrets を使うときに必要 |
| ログドライバーが対応しているか | Fargate で使えるのは awslogs・splunk・awsfirelens |
| Fargate で使えない項目を書いていないか | disableNetworking、dnsSearchDomains、dnsServers、dockerSecurityOptions、extraHosts、gpu、ipcMode、links、placementConstraints、privileged、maxSwap、swappiness |
requiresCompatibilities に FARGATE を書いておくと、登録の時点で Fargate の要件に照らして確かめてもらえます。EC2 向けに書いたタスク定義を Fargate に移すときは、最後の行の項目が残っていないかも見ておきます。
よくある質問
Q. cpu と memory は、タスク全体とコンテナのどちらに書けばよいですか? A. Fargate ではタスク全体(JSON の最上位)の cpu と memory が必須です。コンテナ定義の中の cpu・memory は任意で、1つのタスクに複数のコンテナを入れて配分を決めたいときに使います。
Q. タスク定義を「更新」するコマンドはありますか? A. 登録済みのリビジョンを書き換えるコマンドはなく、同じ family で register-task-definition を実行して新しいリビジョンを作ります。以前のリビジョンは残るので、サービスに指定するリビジョンを変えれば戻せます。
Q. secrets に書いた値は、describe-task-definition で見えますか? A. 見えるのは valueFrom の ARN だけで、値そのものは出力に含まれません。environment に書いた値はそのまま見えるので、機密情報は secrets に分けておきます。
Q. シークレットの値を変えたのに、アプリに反映されません。 A. 公式ドキュメントによると、値はコンテナの起動時に渡され、あとから変えても動いているコンテナには反映されません。新しいタスクを起動するか、サービスを新しいデプロイの強制つきで更新してください。
まとめ
- Fargate の土台は family・networkMode(awsvpc)・cpu・memory・containerDefinitions の5つ。cpu と memory は文字列で書く
- cpu と memory は決まった組み合わせから選ぶ。合わないときは
Invalid 'cpu' setting for task.が返る - 機密でない値は environment、機密情報は secrets。secrets の valueFrom は、Secrets Manager なら
ARN:キー名::の形で JSON の1キーを取り出せる - awslogs は awslogs-group・awslogs-region・awslogs-stream-prefix の3つをそろえる
- ECR のプライベートリポジトリ・awslogs・secrets を使うなら executionRoleArn が必要。アプリ自身の権限は taskRoleArn
- describe の出力を再登録するときは、taskDefinitionArn・revision・status など9項目を削る
- リビジョンは登録のたびに増える。片付けは deregister してから delete の2段階
参考・出典
- Amazon ECS デベロッパーガイド「Fargate の Amazon ECS タスク定義パラメータ」 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters.html
- Amazon ECS デベロッパーガイド「Fargate の Amazon ECS タスク定義の違い」 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/fargate-tasks-services.html
- Amazon ECS デベロッパーガイド「タスク定義の無効な CPU またはメモリエラーのトラブルシューティング」 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-cpu-memory-error.html
- Amazon ECS デベロッパーガイド「環境変数を使用して Secrets Manager シークレットを渡す」 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/secrets-envvar-secrets-manager.html
- Amazon ECS デベロッパーガイド「環境変数を使用して Systems Manager パラメータを渡す」 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/secrets-envvar-ssm-paramstore.html
- Amazon ECS デベロッパーガイド「タスク実行 IAM ロール」 https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_execution_IAM_role.html
本記事の内容は、ご自由にお使いください。
ご利用の際は、出典として本ページへのリンクを記載いただけますようお願いします。
(記載例)出典:株式会社RJC「ECSタスク定義JSONの書き方|Fargate必須項目と環境変数secrets」
株式会社RJC ― SI事業・SES事業・AI駆動開発。RJCは一緒に成長を楽しめる会社です。
WE ARE HIRING
RJCで一緒に開発しながら、
成長を楽しみませんか?
RJCは、Web・モバイル・AIを活用した開発プロジェクトで、テックリードやPM・PMOも活躍するシステム開発会社です。会社を知る、待遇を確かめる、話を聞いてみる。気になるところ見てみてください!
- 127日年間休日
- 12時間平均残業時間
- 毎日ガチャ遊びココロも大切にする福利厚生。アマギフなどの賞品ラインナップ!
ほかにも、チケットレストラン、書籍読み放題、2年ごとの慰労報奨(休暇 or 金一封)、11期連続の黒字決算。