ECS Exec: open a shell in a running container
How to set up ECS Exec on Fargate and EC2, run commands in a live container and fix the errors that usually get in the way.
Sometimes logs aren’t enough and you need to look inside a running container: check a config file, test DNS from inside the VPC or see what a process is doing. On Fargate there is no host to SSH into. ECS Exec is the answer, and it works the same way on EC2.
ECS Exec uses AWS Systems Manager under the hood. ECS injects a small SSM agent into your task, and the AWS CLI opens an encrypted session to it. There are no open ports, no SSH keys and no bastion hosts, and access is controlled by IAM.
What you need
On your machine:
- a recent AWS CLI v2,
- the Session Manager plugin for the AWS CLI.
On the task:
- a task role (not the task execution role) that allows the SSM channel actions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ssmmessages:CreateControlChannel",
"ssmmessages:CreateDataChannel",
"ssmmessages:OpenControlChannel",
"ssmmessages:OpenDataChannel"
],
"Resource": "*"
}
]
} - outbound HTTPS (port 443) to the
ssmmessagesendpoint, through a NAT gateway or acom.amazonaws.<region>.ssmmessagesVPC endpoint in private subnets, - on Fargate, platform version 1.4.0 or later.
For the person connecting: IAM permission for ecs:ExecuteCommand on the cluster and task.
The ECS IAM policy generator writes the task role with these permissions, as JSON or Terraform.
Turn it on
ECS Exec is a setting on the task, and it’s fixed when the task starts. For a service, enable it and roll the tasks:
aws ecs update-service \
--cluster production \
--service api \
--enable-execute-command \
--force-new-deployment Without --force-new-deployment, only tasks started later get it. For a one-off task, pass --enable-execute-command to aws ecs run-task.
We also recommend setting "initProcessEnabled": true under linuxParameters in the container definition. It runs a small init process that cleans up the agent’s child processes after sessions end.
Connect
aws ecs execute-command \
--cluster production \
--task 0f9a1c2e3b4d4e5f8a7b6c5d4e3f2a1b \
--container api \
--interactive \
--command "/bin/sh" --container can be left out when the task has a single container. The command doesn’t have to be a shell; --command "cat /etc/resolv.conf" runs once and returns.
When it doesn’t work
“The execute command failed because execute command was not enabled when the task was run or the execute command agent isn’t running.”
Check both halves:
aws ecs describe-tasks --cluster production --tasks <task-id> \
--query 'tasks[0].{exec: enableExecuteCommand, agents: containers[].managedAgents}' If exec is false, the task started before you enabled ECS Exec, so roll the service. If the ExecuteCommandAgent status isn’t RUNNING, the agent couldn’t start or couldn’t reach SSM. That’s usually a missing task role permission or no route to the ssmmessages endpoint.
TargetNotConnectedException
The agent isn’t connected. Same causes as above: task role permissions, security group egress on 443, or a missing VPC endpoint or NAT route in private subnets.
SessionManagerPlugin is not found
Install the Session Manager plugin on the machine you’re connecting from.
AccessDeniedException
Your own role lacks ecs:ExecuteCommand, or an explicit deny (often from an SCP or permission boundary) blocks it.
The session opens and closes immediately
The container has no /bin/sh. Distroless and scratch images don’t ship a shell. Run a specific binary instead, or add a debug image variant.
AWS publishes amazon-ecs-exec-checker, a script that checks most of the above for a given task and tells you which one is wrong. Run it first.
Locking it down
A shell in production is powerful, so treat it like one:
- Audit sessions. The cluster’s
executeCommandConfigurationcan send session output to CloudWatch Logs or S3, and encrypt the session with your own KMS key. - Scope who can connect. Grant
ecs:ExecuteCommandon specific clusters, and use condition keys such asecs:container-nameor resource tags to limit which containers people can enter. - Enable it where you need it. There is no reason to turn it on for every service by default.
ECS Exec takes a few minutes to set up once and saves hours the first time something only fails in production.