AWS

AWS ECR / ECS CLI — Довідник команд

Повний довідник AWS CLI команд для ECR та ECS — аутентифікація, репозиторії, кластери, сервіси, мережа, балансувальник, автомасштабування, логи. Усі важливі команди з прикладами та очікуваним виводом.

AWS ECR / ECS CLI — Довідник команд

Цей довідник охоплює всі важливі команди для роботи з контейнерами в AWS, згруповані за сервісом. Для кожної команди наведено опис параметрів та очікуваний вивід терміналу.

Перед використанням переконайтеся, що AWS CLI налаштований: aws configure або через змінні середовища AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_DEFAULT_REGION. Також потрібний встановлений Docker для команд docker build, docker push.

Docker — локальна робота з образами

docker build

Збирає Docker-образ з Dockerfile у поточній або вказаній директорії.

-t / --tag
string required
Ім'я та тег образу у форматі name:tag. Без тегу Docker автоматично використовує :latest.
.
path required
Шлях до build context — директорії з вихідним кодом та Dockerfile. . означає поточну директорію.
--file / -f
string
Шлях до Dockerfile, якщо він не знаходиться у кореневій директорії build context.
--no-cache
boolean
Збирати образ без використання кешу шарів. Корисно для відлагодження та CI/CD.
docker build — збірка .NET API образу
$ docker build -t my-api:v1.0.0 .
[+] Building 38.5s (12/12) FINISHED
=> [build 1/5] FROM mcr.microsoft.com/dotnet/sdk:8.0
=> [build 3/5] RUN dotnet restore "MyApi.csproj" 10.2s
=> [build 5/5] RUN dotnet publish "MyApi.csproj" -c Release -o /app/publish 18.1s
=> => writing image sha256:a1b2c3d4e5f6... 0.1s
=> => naming to docker.io/library/my-api:v1.0.0 0.0s

docker tag

Додає новий тег до вже існуючого локального образу. Не копіює образ — лише додає псевдонім.

SOURCE_IMAGE:TAG
string required
Ім'я та тег локального образу-джерела, наприклад my-api:v1.0.0.
TARGET_IMAGE:TAG
string required
Нове ім'я та тег. Для ECR — повна адреса у форматі ACCOUNT_ID.dkr.ecr.REGION.amazonaws.com/REPO:TAG.
docker tag — теґування для ECR
$ docker tag my-api:v1.0.0 \
> 123456789012.dkr.ecr.eu-central-1.amazonaws.com/my-api:v1.0.0
(no output — success)
$ docker images | grep my-api
my-api v1.0.0 a1b2c3d4e5f6 2 min ago 204MB
123456789012.dkr.ecr.eu-central-1.amazonaws.com/my-api v1.0.0 a1b2c3d4e5f6 2 min ago 204MB
Обидва рядки у виводі docker images вказують на той самий образ (однаковий sha256). docker tag лише додає псевдонім — місце на диску не подвоюється.

docker push

Завантажує образ у реєстр. Для ECR потрібна попередня аутентифікація через aws ecr get-login-password.

IMAGE:TAG
string required
Повна адреса образу включно з реєстром, репозиторієм та тегом.
docker push — завантаження в ECR
$ docker push 123456789012.dkr.ecr.eu-central-1.amazonaws.com/my-api:v1.0.0
The push refers to repository [123456789012.dkr.ecr.eu-central-1.amazonaws.com/my-api]
3f4a8b9c1d2e: Pushing 45.23 MB/120.5 MB
8c2d1e5f9a3b: Pushed
1a4f7e2c8b6d: Pushed
v1.0.0: digest: sha256:abc123def456... size: 1847

Amazon ECR — Elastic Container Registry

ecr get-login-password

Отримує тимчасовий токен аутентифікації (12 годин) та передає його стандартному docker login через pipe. Це єдиний спосіб аутентифікуватись у ECR — постійних паролів немає.

--region
string required
Регіон ECR. Повинен збігатися з регіоном, вказаним у URI реєстру у наступній команді docker login.
aws ecr get-login-password — аутентифікація
$ aws ecr get-login-password --region eu-central-1 \
> | docker login --username AWS \
> --password-stdin 123456789012.dkr.ecr.eu-central-1.amazonaws.com
Login Succeeded
Токен дійсний 12 годин. У CI/CD pipeline виконуйте get-login-password на початку кожного job, а не один раз при налаштуванні.

ecr create-repository

Створює новий репозиторій у ECR. Потрібно виконати один раз перед першим docker push.

--repository-name
string required
Ім'я репозиторію. Повинне відповідати [a-z0-9._/-]+. Підтримує вкладеність через /: backend/my-api.
--region
string required
Регіон AWS, де буде створено репозиторій.
--image-scanning-configuration
object
Конфігурація сканування. scanOnPush=true вмикає автоматичне сканування CVE при кожному push через Amazon Inspector.
--image-tag-mutability
string
MUTABLE (за замовчуванням) — теги можна перезаписати. IMMUTABLE — теги захищені від перезапису. Рекомендується IMMUTABLE для production.
--encryption-configuration
object
Тип шифрування: AES256 (за замовчуванням, безкоштовно) або KMS (власний ключ AWS KMS, платно).
aws ecr create-repository — відповідь
$ aws ecr create-repository \
> --repository-name my-api \
> --region eu-central-1 \
> --image-scanning-configuration scanOnPush=true \
> --image-tag-mutability IMMUTABLE
{
"repository": {
"repositoryArn": "arn:aws:ecr:eu-central-1:123456789012:repository/my-api",
"registryId": "123456789012",
"repositoryName": "my-api",
"repositoryUri": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/my-api",
"imageTagMutability": "IMMUTABLE",
"imageScanningConfiguration": { "scanOnPush": true }
}
}
Збережіть значення repositoryUri — воно використовується у docker tag, docker push та у полі image Task Definition.

ecr describe-repositories / describe-images

Перегляд списку репозиторіїв або образів у конкретному репозиторії.

--repository-names
list
Список репозиторіїв для describe-repositories. Якщо не вказано — повертає всі репозиторії акаунту.
--repository-name
string required
Ім'я репозиторію для describe-images.
--query
string
JMESPath-вираз для фільтрації відповіді. Наприклад, images[*].{Tag:imageTags[0],Digest:imageDigest}.
ecr describe-repositories / describe-images
$ aws ecr describe-repositories --region eu-central-1 \
> --query "repositories[*].repositoryName" --output table
-----------
| my-api |
| my-auth |
-----------
$ aws ecr describe-images --repository-name my-api --region eu-central-1 \
> --query "imageDetails[*].{Tag:imageTags[0],Pushed:imagePushedAt,Size:imageSizeInBytes}" \
> --output table
------------------------------------------------
| Tag | Pushed | Size |
|---------+--------------------------+----------|
| v1.1.0 | 2024-01-15T12:30:00+00:00| 211054321|
| v1.0.0 | 2024-01-10T09:15:00+00:00| 208832100|
------------------------------------------------

ecr put-lifecycle-policy

Застосовує Lifecycle Policy до репозиторію — правило автоматичного видалення застарілих образів.

--repository-name
string required
Ім'я репозиторію, до якого застосовується policy.
--lifecycle-policy-text
json-string required
JSON-рядок або посилання file://path.json з правилами lifecycle policy. Кожне правило має rulePriority, selection (фільтр образів) та action (expire).
aws ecr put-lifecycle-policy
$ cat lifecycle.json
{
"rules": [
{ "rulePriority": 1, "description": "Видалити untagged після 1 дня",
"selection": { "tagStatus": "untagged", "countType": "sinceImagePushed",
"countUnit": "days", "countNumber": 1 },
"action": { "type": "expire" } },
{ "rulePriority": 2, "description": "Зберігати лише 10 tagged",
"selection": { "tagStatus": "tagged", "tagPrefixList": ["v"],
"countType": "imageCountMoreThan", "countNumber": 10 },
"action": { "type": "expire" } }
]
}
$ aws ecr put-lifecycle-policy \
> --repository-name my-api \
> --lifecycle-policy-text file://lifecycle.json \
> --region eu-central-1
{
"registryId": "123456789012",
"repositoryName": "my-api",
"lifecyclePolicyText": "{\"rules\":[...]}"
}
Перед застосуванням policy перевірте, які образи підпадуть під видалення: ECR Console → my-apiLifecycle policyTest rules — покаже список без реального видалення.

ecr start-image-scan / describe-image-scan-findings

Запускає сканування образу на вразливості CVE або переглядає результати попереднього сканування.

--repository-name
string required
Ім'я репозиторію з образом.
--image-id
object required
Ідентифікатор образу: imageTag=v1.0.0 або imageDigest=sha256:abc123....
ecr start-image-scan / describe-image-scan-findings
$ aws ecr start-image-scan \
> --repository-name my-api --image-id imageTag=v1.0.0 \
> --region eu-central-1
{ "imageScanStatus": { "status": "IN_PROGRESS" } }
$ aws ecr describe-image-scan-findings \
> --repository-name my-api --image-id imageTag=v1.0.0 \
> --region eu-central-1 \
> --query "imageScanFindings.findingSeverityCounts"
{
"CRITICAL": 0,
"HIGH": 1,
"MEDIUM": 3,
"LOW": 12,
"INFORMATIONAL": 5
}

ecr put-image-tag-mutability

Змінює режим захисту тегів для існуючого репозиторію.

--image-tag-mutability
string required
MUTABLE — теги можна перезаписати (за замовчуванням). IMMUTABLE — теги незмінні після першого push; гарантує відтворюваність образів у production.
aws ecr put-image-tag-mutability
$ aws ecr put-image-tag-mutability \
> --repository-name my-api \
> --image-tag-mutability IMMUTABLE \
> --region eu-central-1
{
"repositoryName": "my-api",
"imageTagMutability": "IMMUTABLE"
}

ecr set-repository-policy

Застосовує Resource-based Policy до репозиторію — дозволяє завантажувати образи з інших AWS акаунтів (multi-account архітектура).

--policy-text
json-string required
JSON з IAM-policy. Principal — ARN акаунту або ролі, що має отримати доступ. Action — мінімально: ecr:GetDownloadUrlForLayer, ecr:BatchGetImage, ecr:BatchCheckLayerAvailability.
aws ecr set-repository-policy — cross-account access
$ aws ecr set-repository-policy \
> --repository-name my-api \
> --policy-text '{"Version":"2012-10-17","Statement":[{"Effect":"Allow",
> "Principal":{"AWS":"arn:aws:iam::PROD_ACCOUNT:root"},
> "Action":["ecr:GetDownloadUrlForLayer","ecr:BatchGetImage"]}]}' \
> --region eu-central-1
{ "registryId": "123456789012", "repositoryName": "my-api",
"policyText": "{\"Version\":\"2012-10-17\",...}" }

ecr put-replication-configuration

Налаштовує автоматичну реплікацію образів між регіонами або між акаунтами.

--replication-configuration
object required
Об'єкт з rules — масивом правил реплікації. Кожне правило містить destinations (регіон та registryId) та repositoryFilters (фільтр за префіксом імені).
aws ecr put-replication-configuration
$ aws ecr put-replication-configuration \
> --replication-configuration '{"rules":[{"destinations":[
> {"region":"us-east-1","registryId":"123456789012"}],
> "repositoryFilters":[{"filter":"my-api","filterType":"PREFIX_MATCH"}]}]}' \
> --region eu-central-1
{ "replicationConfiguration": { "rules": [...] } }

ecr batch-delete-image / delete-repository

Видалення образів або цілого репозиторію.

--image-ids
list required
Список образів для batch-delete-image. Кожен елемент: imageTag=v1.0.0 або imageDigest=sha256:....
--force
boolean
Для delete-repository — видаляє репозиторій навіть якщо він містить образи.
ecr batch-delete-image / delete-repository
$ aws ecr batch-delete-image \
> --repository-name my-api \
> --image-ids imageTag=v1.0.0 imageTag=v1.1.0 \
> --region eu-central-1
{ "imageIds": [{ "imageTag": "v1.0.0" }, { "imageTag": "v1.1.0" }], "failures": [] }
$ aws ecr delete-repository \
> --repository-name my-api --force --region eu-central-1
{ "repository": { "repositoryName": "my-api", "repositoryUri": "..." } }

Amazon ECS — Cluster

ecs create-cluster

Створює логічну групу для запуску ECS Tasks та Services.

--cluster-name
string required
Ім'я кластера. Унікальне в межах акаунту та регіону.
--capacity-providers
list
Capacity Providers: FARGATE, FARGATE_SPOT або власні EC2-провайдери. Якщо не вказано — кластер підтримує всі типи.
--settings
list
Налаштування кластера. name=containerInsights,value=enabled вмикає CloudWatch Container Insights — деталізовані метрики CPU, Memory, Network по кожному Task та Service.
aws ecs create-cluster — відповідь
$ aws ecs create-cluster \
> --cluster-name ecs-lab-cluster \
> --capacity-providers FARGATE \
> --settings name=containerInsights,value=enabled \
> --region eu-central-1
{
"cluster": {
"clusterArn": "arn:aws:ecs:eu-central-1:123456789012:cluster/ecs-lab-cluster",
"clusterName": "ecs-lab-cluster",
"status": "ACTIVE",
"registeredContainerInstancesCount": 0,
"settings": [{ "name": "containerInsights", "value": "enabled" }],
"capacityProviders": ["FARGATE"]
}
}

ecs update-cluster-settings

Вмикає або вимикає Container Insights для існуючого кластера.

--cluster
string required
Ім'я або ARN кластера.
--settings
list required
Масив налаштувань. Для Container Insights: name=containerInsights,value=enabled або value=disabled.
aws ecs update-cluster-settings
$ aws ecs update-cluster-settings \
> --cluster ecs-lab-cluster \
> --settings name=containerInsights,value=enabled \
> --region eu-central-1
{ "cluster": { "clusterName": "ecs-lab-cluster", "settings": [{ "name": "containerInsights", "value": "enabled" }] } }

ecs delete-cluster

Видаляє кластер. Перед видаленням усі Services та Tasks повинні бути зупинені.

aws ecs delete-cluster
$ aws ecs delete-cluster --cluster ecs-lab-cluster --region eu-central-1
{ "cluster": { "clusterName": "ecs-lab-cluster", "status": "INACTIVE" } }

Amazon ECS — Task Definition

ecs register-task-definition

Реєструє нову Task Definition або нову revision існуючої сімейства. Приймає параметри напряму або через --cli-input-json file://task-def.json.

--family
string required
Ім'я сімейства Task Definition. Кожен виклик register-task-definition з тим самим family створює нову revision (my-api:1, my-api:2, ...).
--network-mode
string
Мережевий режим: awsvpc (обов'язково для Fargate), bridge, host, none. При awsvpc кожен Task отримує власний ENI та IP.
--requires-compatibilities
list
FARGATE або EC2. Для Fargate — обов'язково.
--cpu
string required
Кількість CPU units у вигляді рядка: "256" (0.25 vCPU), "512", "1024", "2048", "4096", "8192", "16384". Не довільне число — лише значення з таблиці допустимих комбінацій.
--memory
string required
Пам'ять у MB. Значення обмежені залежно від cpu: для "256" — 512, 1024 або 2048; для "512" — 1024–4096 тощо.
--execution-role-arn
string required
ARN IAM Role, яку Fargate використовує для завантаження образу з ECR та запису логів у CloudWatch. Зазвичай ecsTaskExecutionRole з AmazonECSTaskExecutionRolePolicy.
--task-role-arn
string
ARN IAM Role для самого контейнера — надає права викликати інші AWS API (S3, SQS, DynamoDB тощо). Відокремлений від execution-role-arn.
--container-definitions
json-list required
Масив конфігурацій контейнерів. Кожен об'єкт містить: name, image, portMappings, environment, secrets, healthCheck, logConfiguration.
aws ecs register-task-definition
$ aws ecs register-task-definition \
> --cli-input-json file:///tmp/task-def.json \
> --region eu-central-1
{
"taskDefinition": {
"family": "my-api",
"taskDefinitionArn": "arn:aws:ecs:eu-central-1:123456789012:task-definition/my-api:1",
"revision": 1,
"status": "ACTIVE",
"cpu": "256",
"memory": "512"
}
}
Після кожної зміни Task Definition (навіть однієї змінної середовища) AWS створює нову revision. Попередні revisions зберігаються назавжди — ви можете відкотитись на будь-яку з них. my-api:1, my-api:2, my-api:LATEST — всі посилаються на ту саму сімейство.

ecs list-task-definitions / describe-task-definition

Перегляд зареєстрованих Task Definitions.

list-task-definitions / describe-task-definition
$ aws ecs list-task-definitions --family-prefix my-api --region eu-central-1
{
"taskDefinitionArns": [
"arn:aws:ecs:eu-central-1:123456789012:task-definition/my-api:1",
"arn:aws:ecs:eu-central-1:123456789012:task-definition/my-api:2"
]
}
$ aws ecs describe-task-definition --task-definition my-api:2 --region eu-central-1 \
> --query "taskDefinition.{cpu:cpu,memory:memory,image:containerDefinitions[0].image}"
{
"cpu": "256",
"memory": "512",
"image": "123456789012.dkr.ecr.eu-central-1.amazonaws.com/my-api:v1.1.0"
}

Amazon ECS — Service

ecs create-service

Створює ECS Service — оркестратор, що підтримує задану кількість Tasks, виконує rolling updates та інтегрується з ALB.

--cluster
string required
Ім'я кластера, де буде запущено Service.
--service-name
string required
Ім'я Service. Унікальне в межах кластера.
--task-definition
string required
Ім'я Task Definition або конкретна revision: my-api (остання) або my-api:3 (конкретна).
--desired-count
integer required
Бажана кількість паралельно запущених Tasks. Service підтримуватиме саме цю кількість.
--launch-type
string
FARGATE або EC2. При використанні Capacity Providers не вказується.
--network-configuration
object
Конфігурація awsvpc: підмережі, Security Groups, assignPublicIp (ENABLED або DISABLED). Обов'язкова для Fargate.
--load-balancers
list
Прив'язка до Target Group ALB: targetGroupArn, containerName, containerPort. Без цього параметра Service не реєструє Tasks в ALB.
--deployment-configuration
object
Параметри rolling update: minimumHealthyPercent (мінімум здорових Tasks, %) та maximumPercent (максимум Tasks під час деплою, %).
aws ecs create-service
$ aws ecs create-service \
> --cluster ecs-lab-cluster --service-name ecs-lab-service \
> --task-definition ecs-lab-api --desired-count 2 \
> --launch-type FARGATE \
> --network-configuration "awsvpcConfiguration={subnets=[subnet-aaa,subnet-bbb],securityGroups=[sg-zzz],assignPublicIp=ENABLED}" \
> --region eu-central-1
{
"service": {
"serviceArn": "arn:aws:ecs:eu-central-1:123456789012:service/ecs-lab-cluster/ecs-lab-service",
"status": "ACTIVE",
"desiredCount": 2,
"runningCount": 0,
"pendingCount": 2
}
}

ecs update-service

Оновлює конфігурацію існуючого Service. Найчастіше використовується для запуску нової Task Definition (rolling update) або вмикання/вимикання функцій.

--task-definition
string
Нова Task Definition. Після оновлення ECS починає rolling update: запускає нові Tasks з новою конфігурацією і поступово зупиняє старі.
--desired-count
integer
Нова бажана кількість Tasks. 0 — зупиняє всі Tasks (Service залишається, але нічого не запущено).
--enable-execute-command
boolean
Вмикає ECS Exec — можливість підключатись до контейнера через aws ecs execute-command.
--deployment-configuration
object
Оновлює параметри деплою: deploymentCircuitBreaker (автовідкат при збоях), maximumPercent, minimumHealthyPercent.
--force-new-deployment
boolean
Примусово перезапустити всі Tasks навіть якщо Task Definition не змінилась. Корисно для підхоплення нового образу з тегом :latest.
aws ecs update-service — rolling update та circuit breaker
$ aws ecs update-service \
> --cluster ecs-lab-cluster --service-name ecs-lab-service \
> --task-definition ecs-lab-api:2 \
> --deployment-configuration '{"deploymentCircuitBreaker":{"enable":true,"rollback":true},"maximumPercent":200,"minimumHealthyPercent":50}' \
> --region eu-central-1
{
"service": {
"taskDefinition": "arn:aws:ecs:...:task-definition/ecs-lab-api:2",
"deployments": [{ "status": "PRIMARY", "taskDefinition": "...ecs-lab-api:2", "runningCount": 0, "desiredCount": 2 }]
}
}
maximumPercent=200 при desiredCount=2 означає: ECS може запустити до 4 Tasks одночасно під час rolling update (2 старих + 2 нових). minimumHealthyPercent=50 гарантує, що принаймні 1 Task залишається здоровим весь час.

ecs delete-service

Видаляє Service. Рекомендується спочатку встановити --desired-count 0, щоб ECS зупинив Tasks, а потім видалити.

--force
boolean
Видалити Service навіть якщо він має запущені Tasks. Без --force вимагає desiredCount=0.
aws ecs delete-service — правильна послідовність
# 1. Зупинити всі Tasks (встановити desiredCount=0)
$ aws ecs update-service --cluster ecs-lab-cluster --service ecs-lab-service --desired-count 0 --region eu-central-1
(сервіс переходить у runningCount: 0)
# 2. Видалити Service
$ aws ecs delete-service --cluster ecs-lab-cluster --service ecs-lab-service --force --region eu-central-1
{ "service": { "status": "DRAINING", ... } }

Amazon ECS — Tasks

ecs list-tasks / describe-tasks

Перегляд запущених Tasks у кластері.

--cluster
string required
Ім'я або ARN кластера.
--service-name
string
Фільтр для list-tasks — повертає лише Tasks конкретного Service.
--tasks
list required
Список ARN Tasks для describe-tasks.
ecs list-tasks / describe-tasks
$ aws ecs list-tasks --cluster ecs-lab-cluster --region eu-central-1
{
"taskArns": [
"arn:aws:ecs:eu-central-1:123456789012:task/ecs-lab-cluster/abc123",
"arn:aws:ecs:eu-central-1:123456789012:task/ecs-lab-cluster/def456"
]
}
$ aws ecs describe-tasks --cluster ecs-lab-cluster \
> --tasks arn:aws:ecs:eu-central-1:123456789012:task/ecs-lab-cluster/abc123 \
> --region eu-central-1 \
> --query "tasks[0].{status:lastStatus,ip:attachments[0].details[?name=='privateIPv4Address'].value|[0]}"
{ "status": "RUNNING", "ip": "10.0.1.47" }

ecs execute-command

Відкриває інтерактивну сесію всередині запущеного контейнера (аналог docker exec). Потребує: enableExecuteCommand=true у Service, SSM права у Task Role, встановленого session-manager-plugin.

--cluster
string required
Ім'я кластера.
--task
string required
ARN Task, до якого підключаємось.
--container
string
Ім'я контейнера. Якщо Task має лише один контейнер — можна не вказувати.
--interactive
boolean required
Вмикає інтерактивний режим (TTY). Без нього команда виконається та завершиться без prompt.
--command
string required
Команда, яку запустити: /bin/bash, /bin/sh, або будь-яка утиліта всередині образу.
aws ecs execute-command — інтерактивна сесія
$ aws ecs execute-command \
> --cluster ecs-lab-cluster \
> --task arn:aws:ecs:eu-central-1:123456789012:task/ecs-lab-cluster/abc123 \
> --container ecs-lab-api \
> --interactive \
> --command "/bin/bash" \
> --region eu-central-1
Starting session with SessionId: ecs-execute-command-0abc123def456
app@3f4a8b9c1d2e:/app$ env | grep ASPNETCORE
ASPNETCORE_ENVIRONMENT=Production
ASPNETCORE_URLS=http://[::]:8080
app@3f4a8b9c1d2e:/app$ curl localhost:8080/health
Healthy

ecs put-cluster-capacity-providers

Налаштовує Capacity Provider Strategy — розподіл Tasks між FARGATE та FARGATE_SPOT для економії коштів.

--capacity-providers
list required
Список провайдерів: FARGATE FARGATE_SPOT. Обидва вказуються через пробіл.
--default-capacity-provider-strategy
list required
Стратегія розподілу. base — мінімальна кількість Tasks на провайдері. weight — відносна вага. При base=1,weight=1 для FARGATE та weight=3 для FARGATE_SPOT: перший Task завжди на FARGATE, далі 75% на FARGATE_SPOT.
aws ecs put-cluster-capacity-providers
$ aws ecs put-cluster-capacity-providers \
> --cluster ecs-lab-cluster \
> --capacity-providers FARGATE FARGATE_SPOT \
> --default-capacity-provider-strategy \
> "capacityProvider=FARGATE_SPOT,weight=3,base=0" \
> "capacityProvider=FARGATE,weight=1,base=1" \
> --region eu-central-1
{ "cluster": { "clusterName": "ecs-lab-cluster",
"capacityProviders": ["FARGATE", "FARGATE_SPOT"],
"defaultCapacityProviderStrategy": [...] } }
FARGATE_SPOT Tasks можуть бути примусово зупинені AWS з 2-хвилинним попередженням. Використовуйте FARGATE_SPOT лише для stateless, batch або job-сервісів. Production API-сервіси зі станом слід тримати на FARGATE.

IAM Roles для ECS

iam create-role + attach-role-policy — Task Execution Role

Стандартна роль, яку Fargate використовує для завантаження образу з ECR та запису логів у CloudWatch. Потрібна для кожного кластера.

створення ecsTaskExecutionRole
# 1. Trust Policy — дозволяє ECS Tasks приймати роль
$ cat > /tmp/ecs-trust.json << 'EOF'
{ "Version":"2012-10-17", "Statement":[{ "Effect":"Allow",
"Principal":{"Service":"ecs-tasks.amazonaws.com"}, "Action":"sts:AssumeRole" }] }
EOF
# 2. Створити роль
$ aws iam create-role \
> --role-name ecsTaskExecutionRole \
> --assume-role-policy-document file:///tmp/ecs-trust.json
{ "Role": { "RoleName": "ecsTaskExecutionRole", "Arn": "arn:aws:iam::123456789012:role/ecsTaskExecutionRole" } }
# 3. Прикріпити managed policy
$ aws iam attach-role-policy \
> --role-name ecsTaskExecutionRole \
> --policy-arn arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
(no output — success)

iam create-role + put-role-policy — EventBridge Scheduler Role

IAM Role для EventBridge Scheduler, що дозволяє запускати ECS Tasks за розкладом.

створення EventBridgeECSRole для Scheduled Tasks
$ cat > /tmp/eb-trust.json << 'EOF'
{ "Version":"2012-10-17", "Statement":[{ "Effect":"Allow",
"Principal":{"Service":"scheduler.amazonaws.com"}, "Action":"sts:AssumeRole" }] }
EOF
$ aws iam create-role \
> --role-name EventBridgeECSRole \
> --assume-role-policy-document file:///tmp/eb-trust.json
{ "Role": { "RoleName": "EventBridgeECSRole", "Arn": "arn:aws:iam::123456789012:role/EventBridgeECSRole" } }
$ aws iam put-role-policy \
> --role-name EventBridgeECSRole \
> --policy-name ECSRunTaskPolicy \
> --policy-document '{"Version":"2012-10-17","Statement":[
> {"Effect":"Allow","Action":"ecs:RunTask","Resource":"arn:aws:ecs:...:task-definition/cleanup-task:*"},
> {"Effect":"Allow","Action":"iam:PassRole","Resource":"arn:aws:iam::...:role/ecsTaskExecutionRole"}]}'
(no output — success)

EC2 — VPC та Security Groups для ECS

ec2 describe-vpcs / describe-subnets

Знайти ID Default VPC та підмереж перед запуском ECS Service.

ec2 describe-vpcs / describe-subnets
$ aws ec2 describe-vpcs \
> --filters "Name=isDefault,Values=true" \
> --query "Vpcs[0].VpcId" --output text --region eu-central-1
vpc-0a1b2c3d4e5f67890
$ aws ec2 describe-subnets \
> --filters "Name=defaultForAz,Values=true" \
> --query "Subnets[*].{ID:SubnetId,AZ:AvailabilityZone}" \
> --output table --region eu-central-1
----------------------------------------------
| AZ | ID |
|-----------------+-------------------------|
| eu-central-1a | subnet-0a1b2c3d |
| eu-central-1b | subnet-1b2c3d4e |
| eu-central-1c | subnet-2c3d4e5f |
----------------------------------------------

ec2 create-security-group / authorize-security-group-ingress

Створює Security Group та додає правила вхідного трафіку.

--group-name
string required
Ім'я Security Group. Унікальне в межах VPC.
--description
string required
Текстовий опис. Обов'язковий параметр.
--vpc-id
string required
ID VPC, в якому створюється Security Group.
--cidr
string
CIDR блок для правила ingress. 0.0.0.0/0 — весь Інтернет (лише для lab).
--source-group
string
ID іншого Security Group як джерело трафіку. Рекомендований підхід для production: ALB SG → Tasks SG.
ec2 create-security-group + authorize-ingress
$ SG_ID=$(aws ec2 create-security-group \
> --group-name "ecs-lab-sg" \
> --description "ECS Tasks security group" \
> --vpc-id vpc-0a1b2c3d4e5f67890 \
> --query GroupId --output text --region eu-central-1)
sg-0a1b2c3d4e5f67890
# Lab: дозволити 0.0.0.0/0 (лише для тестування без ALB)
$ aws ec2 authorize-security-group-ingress \
> --group-id $SG_ID --protocol tcp --port 8080 \
> --cidr 0.0.0.0/0 --region eu-central-1
(no output — success)
# Production: дозволити лише з ALB Security Group
$ aws ec2 authorize-security-group-ingress \
> --group-id $TASKS_SG_ID --protocol tcp --port 8080 \
> --source-group $ALB_SG_ID --region eu-central-1
(no output — success)

ec2 describe-network-interfaces

Знаходить публічний IP Task через ENI (Elastic Network Interface), прикріплений до Task.

отримання публічного IP Fargate Task
# 1. Знайти ENI, прикріплений до Task
$ ENI_ID=$(aws ecs describe-tasks \
> --cluster ecs-lab-cluster --tasks $TASK_ARN \
> --query "tasks[0].attachments[0].details[?name=='networkInterfaceId'].value" \
> --output text --region eu-central-1)
# 2. Отримати публічний IP ENI
$ aws ec2 describe-network-interfaces \
> --network-interface-ids $ENI_ID \
> --query "NetworkInterfaces[0].Association.PublicIp" \
> --output text --region eu-central-1
3.64.185.42

ELBv2 — Application Load Balancer

elbv2 create-load-balancer

Створює Application Load Balancer (Layer 7). Розміщується у публічних підмережах — він отримує зовнішній трафік і перенаправляє на Tasks.

--name
string required
Ім'я ALB. Унікальне в межах акаунту та регіону. Максимум 32 символи.
--subnets
list required
ID мінімум двох публічних підмереж у різних Availability Zones. ALB вимагає мінімум 2 AZ для відмовостійкості.
--security-groups
list required
Security Group для ALB. Має дозволяти вхідний трафік 80/443 з 0.0.0.0/0.
--scheme
string
internet-facing (публічний, є публічний DNS/IP) або internal (лише з VPC). Для зовнішнього API — internet-facing.
--type
string
application (ALB, Layer 7, HTTP/HTTPS) або network (NLB, Layer 4, TCP/UDP).
aws elbv2 create-load-balancer
$ ALB_ARN=$(aws elbv2 create-load-balancer \
> --name my-api-alb --subnets subnet-aaa subnet-bbb \
> --security-groups sg-alb-id \
> --scheme internet-facing --type application \
> --query "LoadBalancers[0].LoadBalancerArn" --output text \
> --region eu-central-1)
arn:aws:elasticloadbalancing:eu-central-1:123456789012:loadbalancer/app/my-api-alb/1a2b3c4d
$ aws elbv2 describe-load-balancers --names my-api-alb --region eu-central-1 \
> --query "LoadBalancers[0].{State:State.Code,DNS:DNSName}"
{ "State": "active", "DNS": "my-api-alb-123456789.eu-central-1.elb.amazonaws.com" }

elbv2 create-target-group

Створює Target Group — набір IP-адрес (Tasks), на які ALB направляє трафік. Для Fargate завжди --target-type ip.

--name
string required
Ім'я Target Group.
--protocol / --port
string
Протокол та порт для внутрішнього трафіку від ALB до Tasks. Для .NET: HTTP та 8080.
--vpc-id
string required
VPC, в якому знаходяться Tasks.
--target-type
string required
ip — обов'язково для Fargate (awsvpc режим). Tasks реєструються за IP, а не за EC2 інстанс ID.
--health-check-path
string
URL шлях для health check. Для .NET — зазвичай /health. ALB перевіряє кожен Task перед реєстрацією та регулярно після.
aws elbv2 create-target-group
$ TG_ARN=$(aws elbv2 create-target-group \
> --name my-api-tg --protocol HTTP --port 8080 \
> --vpc-id vpc-0a1b2c3d4e5f --target-type ip \
> --health-check-path /health \
> --health-check-interval-seconds 30 \
> --healthy-threshold-count 2 \
> --unhealthy-threshold-count 3 \
> --query "TargetGroups[0].TargetGroupArn" --output text \
> --region eu-central-1)
arn:aws:elasticloadbalancing:eu-central-1:123456789012:targetgroup/my-api-tg/abc123

elbv2 create-listener / modify-listener

Створює Listener — правило, за яким ALB приймає трафік на певному порті і перенаправляє на Target Group.

--protocol / --port
string required
HTTP / 80 або HTTPS / 443. Для HTTPS потрібен ACM сертифікат.
--certificates
list
ARN ACM сертифікату для HTTPS Listener: CertificateArn=arn:aws:acm:....
--default-actions
list required
Дія за замовчуванням: Type=forward,TargetGroupArn=... (направити на TG) або Type=redirect,RedirectConfig={...} (редирект).
create HTTP listener + HTTPS listener + HTTP→HTTPS redirect
# HTTP Listener (порт 80 → Target Group)
$ aws elbv2 create-listener \
> --load-balancer-arn $ALB_ARN --protocol HTTP --port 80 \
> --default-actions Type=forward,TargetGroupArn=$TG_ARN \
> --region eu-central-1
{ "Listeners": [{ "ListenerArn": "arn:...", "Port": 80, "Protocol": "HTTP" }] }
# HTTPS Listener (порт 443 → Target Group через ACM)
$ aws elbv2 create-listener \
> --load-balancer-arn $ALB_ARN --protocol HTTPS --port 443 \
> --certificates CertificateArn=$CERT_ARN \
> --default-actions Type=forward,TargetGroupArn=$TG_ARN \
> --region eu-central-1
{ "Listeners": [{ "Port": 443, "Protocol": "HTTPS" }] }
# Змінити HTTP Listener на redirect → HTTPS
$ HTTP_LISTENER=$(aws elbv2 describe-listeners \
> --load-balancer-arn $ALB_ARN \
> --query "Listeners[?Port==\`80\`].ListenerArn" --output text --region eu-central-1)
$ aws elbv2 modify-listener \
> --listener-arn $HTTP_LISTENER \
> --default-actions 'Type=redirect,RedirectConfig={Protocol=HTTPS,Port=443,StatusCode=HTTP_301}' \
> --region eu-central-1
{ "Listeners": [{ "Protocol": "HTTP", "Port": 80, "DefaultActions": [{"Type": "redirect"}] }] }

Application Auto Scaling — ECS

application-autoscaling register-scalable-target

Реєструє ECS Service як масштабований ресурс. Цей крок — передумова перед додаванням Scaling Policy.

--service-namespace
string required
Простір імен сервісу. Для ECS завжди ecs.
--scalable-dimension
string required
Розмір, що масштабується. Для ECS Service: ecs:service:DesiredCount.
--resource-id
string required
Ідентифікатор ресурсу у форматі service/<cluster-name>/<service-name>.
--min-capacity
integer required
Мінімальна кількість Tasks. Рекомендується 2 для production: захищає від повного простою.
--max-capacity
integer required
Максимальна кількість Tasks. Захищає від неконтрольованих витрат.
aws application-autoscaling register-scalable-target
$ aws application-autoscaling register-scalable-target \
> --service-namespace ecs \
> --scalable-dimension ecs:service:DesiredCount \
> --resource-id service/production/my-api \
> --min-capacity 2 --max-capacity 20 \
> --region eu-central-1
(no output — success)

application-autoscaling put-scaling-policy

Застосовує Scaling Policy до зареєстрованого ресурсу.

--policy-name
string required
Ім'я Policy, унікальне для ресурсу.
--policy-type
string required
TargetTrackingScaling (підтримує ціль метрики), StepScaling (кроки при перевищенні порогу) або SimpleScaling.
--target-tracking-scaling-policy-configuration
json-object
Конфігурація для TargetTrackingScaling: TargetValue (ціль), PredefinedMetricSpecification або CustomizedMetricSpecification, ScaleInCooldown, ScaleOutCooldown.
aws application-autoscaling put-scaling-policy — CPU Target Tracking
$ aws application-autoscaling put-scaling-policy \
> --service-namespace ecs \
> --scalable-dimension ecs:service:DesiredCount \
> --resource-id service/production/my-api \
> --policy-name cpu-target-70 \
> --policy-type TargetTrackingScaling \
> --target-tracking-scaling-policy-configuration '{
> "TargetValue": 70.0,
> "PredefinedMetricSpecification": {
> "PredefinedMetricType": "ECSServiceAverageCPUUtilization"
> },
> "ScaleInCooldown": 300,
> "ScaleOutCooldown": 60
> }' \
> --region eu-central-1
{
"PolicyARN": "arn:aws:autoscaling:eu-central-1:123456789012:scalingPolicy:abc:resource/ecs/service/production/my-api:policyName/cpu-target-70"
}

CloudWatch Logs

logs tail

Виводить та в режимі --follow потокує нові записи з CloudWatch Log Group. Основний спосіб переглядати логи ECS контейнерів у реальному часі.

LOG_GROUP_NAME
string required
Ім'я Log Group. Для ECS — стандартно /ecs/<task-definition-family>.
--follow
boolean
Продовжувати виводити нові записи (live tail). Аналог tail -f.
--format
string
Формат виводу: short (мітка часу + повідомлення), detailed (всі метадані), json. short — найзручніший для читання.
--since
string
Почати з певного моменту: 1h, 30m, 2024-01-15T10:00:00. Без цього параметра — виводить останні записи.
aws logs tail — логи .NET API з ECS
$ aws logs tail /ecs/ecs-lab-api --follow --format short --region eu-central-1
2024-01-15T10:23:45 ecs/ecs-lab-api/abc123 info: Microsoft.Hosting.Lifetime[14]
2024-01-15T10:23:45 ecs/ecs-lab-api/abc123     Now listening on: http://[::]:8080
2024-01-15T10:23:46 ecs/ecs-lab-api/abc123 info: Microsoft.Hosting.Lifetime[0] Application started.
2024-01-15T10:24:01 ecs/ecs-lab-api/abc123 info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
2024-01-15T10:24:01 ecs/ecs-lab-api/abc123     Request starting HTTP/1.1 GET http://10.0.1.47:8080/health - -
2024-01-15T10:24:01 ecs/ecs-lab-api/abc123 info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
2024-01-15T10:24:01 ecs/ecs-lab-api/abc123     Request finished HTTP/1.1 GET /health - 200 - text/plain 1.2ms
Кожен Task пише логи в окремий Log Stream з іменем ecs/<family>/<task-id>. При рестарті Task — новий стрім. Лог Group (/ecs/ecs-lab-api) залишається; aws logs tail агрегує всі стріми.

logs delete-log-group

Видаляє Log Group та всі її Log Streams.

Видалення Log Group є незворотним. Усі збережені логи будуть втрачені. Виконуйте цю команду лише після завершення роботи з лабораторним середовищем.
aws logs delete-log-group
$ aws logs delete-log-group \
> --log-group-name /ecs/ecs-lab-api \
> --region eu-central-1
(no output — success)

ACM — AWS Certificate Manager

acm request-certificate

Запитує безкоштовний SSL/TLS сертифікат. Для ALB у регіоні eu-central-1 — сертифікат має бути в тому самому регіоні.

--domain-name
string required
Основний домен сертифікату: myapp.pp.ua. Сертифікат буде видано саме для цього домену.
--validation-method
string required
DNS (рекомендовано) — потрібно додати CNAME у DNS; автоматично оновлюється при продовженні. EMAIL — лист на адміністративний email домену.
--subject-alternative-names
list
Додаткові домени в одному сертифікаті: *.myapp.pp.ua, api.myapp.pp.ua тощо.
acm request-certificate + describe DNS validation record
$ CERT_ARN=$(aws acm request-certificate \
> --domain-name "myecs.pp.ua" \
> --validation-method DNS \
> --region eu-central-1 \
> --query CertificateArn --output text)
arn:aws:acm:eu-central-1:123456789012:certificate/abc123-def456
# Отримати CNAME запис для DNS валідації
$ aws acm describe-certificate \
> --certificate-arn $CERT_ARN --region eu-central-1 \
> --query "Certificate.DomainValidationOptions[0].ResourceRecord"
{
"Name": "_abc123.myecs.pp.ua.",
"Type": "CNAME",
"Value": "_def456.acm-validations.aws."
}
Додайте цей CNAME запис у DNS-панель вашого домену (pp.ua → DNS Management). Після підтвердження сертифікат перейде у статус ISSUED (~5–10 хвилин). Далі використовуйте $CERT_ARN при створенні HTTPS Listener у elbv2 create-listener.

EventBridge Scheduler

scheduler create-schedule

Створює розклад для запуску ECS Task за cron-виразом через Amazon EventBridge Scheduler.

--name
string required
Ім'я розкладу. Унікальне в межах групи розкладів.
--schedule-expression
string required
Cron або rate вираз: cron(0 2 * * ? *) (щодня о 02:00 UTC) або rate(1 hour). Зверніть увагу: AWS cron має 6 полів (є поле рік).
--flexible-time-window
object required
{"Mode": "OFF"} — точний запуск у вказаний час. {"Mode": "FLEXIBLE", "MaximumWindowInMinutes": 15} — запуск у вікні до 15 хв після вказаного часу.
--target
json-object required
Опис цілі: ARN ECS кластера, IAM Role для запуску, EcsParameters з Task Definition ARN, мережевою конфігурацією.
aws scheduler create-schedule — щоденна задача о 02:00 UTC
$ aws scheduler create-schedule \
> --name "daily-cleanup" \
> --schedule-expression "cron(0 2 * * ? *)" \
> --flexible-time-window '{"Mode": "OFF"}' \
> --target '{
> "Arn": "arn:aws:ecs:eu-central-1:123456789012:cluster/my-cluster",
> "RoleArn": "arn:aws:iam::123456789012:role/EventBridgeECSRole",
> "EcsParameters": {
> "TaskDefinitionArn": "arn:aws:ecs:...:task-definition/cleanup-task:1",
> "LaunchType": "FARGATE",
> "NetworkConfiguration": {"AwsvpcConfiguration":
> {"Subnets":["subnet-xxx"],"SecurityGroups":["sg-xxx"],"AssignPublicIp":"DISABLED"}}
> }
> }' \
> --region eu-central-1
{
"ScheduleArn": "arn:aws:scheduler:eu-central-1:123456789012:schedule/default/daily-cleanup"
}

Швидкий довідник: типові сценарії

Повний цикл деплою нової версії

# 1. Аутентифікація в ECR
aws ecr get-login-password --region eu-central-1 | \
    docker login --username AWS --password-stdin \
    $ACCOUNT_ID.dkr.ecr.eu-central-1.amazonaws.com

# 2. Збірка та push
docker build -t my-api:v1.1.0 .
docker tag my-api:v1.1.0 $REPO_URI:v1.1.0
docker push $REPO_URI:v1.1.0

# 3. Нова revision Task Definition (з новим образом)
aws ecs register-task-definition --cli-input-json file:///tmp/task-def-v1.1.0.json --region eu-central-1

# 4. Rolling update Service
aws ecs update-service \
    --cluster production --service my-api-service \
    --task-definition my-api \
    --region eu-central-1

Діагностика проблем із Task

# Task застряг у PENDING — перевірити причину
aws ecs describe-tasks \
    --cluster my-cluster --tasks $TASK_ARN \
    --query "tasks[0].{status:lastStatus,stopped:stoppedReason,containers:containers[*].{name:name,reason:reason}}" \
    --region eu-central-1

# Переглянути логи контейнера
aws logs tail /ecs/my-api --since 30m --format short --region eu-central-1

# Підключитись до контейнера напряму (якщо увімкнено ECS Exec)
aws ecs execute-command --cluster my-cluster --task $TASK_ARN \
    --container my-api --interactive --command "/bin/bash" --region eu-central-1

Очищення всіх ресурсів після лабораторної роботи

REGION="eu-central-1"

# 1. Зупинити та видалити Service
aws ecs update-service --cluster ecs-lab-cluster --service ecs-lab-service --desired-count 0 --region $REGION
aws ecs delete-service --cluster ecs-lab-cluster --service ecs-lab-service --force --region $REGION

# 2. Видалити кластер
aws ecs delete-cluster --cluster ecs-lab-cluster --region $REGION

# 3. Видалити образи та репозиторій
aws ecr batch-delete-image --repository-name ecs-lab-api --image-ids imageTag=v1.0.0 imageTag=v1.1.0 --region $REGION
aws ecr delete-repository --repository-name ecs-lab-api --force --region $REGION

# 4. Видалити логи
aws logs delete-log-group --log-group-name /ecs/ecs-lab-api --region $REGION

# 5. Видалити Security Group
aws ec2 delete-security-group --group-id $SG_ID --region $REGION
Copyright © 2026