Skip to content

ECS (Elastic Container Service)

Protocol: JSON 1.1 Endpoint: POST / + X-Amz-Target: AmazonEC2ContainerServiceV20141113.<Action>

ECS emulates clusters, task definitions, tasks, and services. In the default configuration tasks run as real Docker containers. Set mock: true (enabled automatically in tests) to run tasks as in-process stubs without Docker.

Supported Operations

Clusters

Operation Description
CreateCluster Create a cluster (idempotent)
DescribeClusters Describe one or more clusters
ListClusters List cluster ARNs
UpdateCluster Update cluster settings
UpdateClusterSettings Update containerInsights and other settings
PutClusterCapacityProviders Associate capacity providers with a cluster
DeleteCluster Delete an empty cluster

Task Definitions

Operation Description
RegisterTaskDefinition Register a new revision of a task definition
DescribeTaskDefinition Describe a task definition by family:revision or ARN
ListTaskDefinitions List task definition ARNs
ListTaskDefinitionFamilies List task definition family names
DeregisterTaskDefinition Mark a revision INACTIVE
DeleteTaskDefinitions Delete one or more task definitions

Tasks

Operation Description
RunTask Launch one or more task instances
StartTask Start a task on specific container instances
StopTask Stop a running task
DescribeTasks Describe one or more tasks
ListTasks List task ARNs (filterable by cluster, family, service, status)
UpdateTaskProtection Set scale-in protection for tasks
GetTaskProtection Get current task protection state

Services

Operation Description
CreateService Create a long-running service
UpdateService Update desired count, task definition, or deployment config
DeleteService Delete a service (supports force)
DescribeServices Describe one or more services (includes deployments, see below)
ListServices List service ARNs in a cluster
ListServicesByNamespace List services filtered by Cloud Map namespace

Service deployments

An ACTIVE service reports exactly one PRIMARY entry in services[].deployments, synthesized from the service's current state rather than tracked as a rollout. This is what AWS's ServicesStable waiter accepts on, so aws ecs wait services-stable, the SDK waiters, and Terraform's aws_ecs_service all converge normally. A deleted (INACTIVE) service reports an empty list.

rolloutState is COMPLETED once runningCount reaches desiredCount, and IN_PROGRESS before that. The deployment id is derived from the service ARN and its task definition, so it is stable across calls and across restarts, and rolls over when the task definition changes. createdAt tracks the deployment rather than the service: it is the service's creation time until a task-definition change starts a new deployment, and moves with it thereafter.

Known differences from AWS:

  • There is never a second ACTIVE deployment draining alongside the PRIMARY one; Floci swaps the task definition in place.
  • deployments is reported for every service. AWS omits it for services that use the CODE_DEPLOY or EXTERNAL deployment controller, but Floci does not yet record deploymentController, and ECS is the AWS default.
  • pendingCount is always 0, matching the top-level service field.
  • forceNewDeployment does not mint a new deployment id.
  • updatedAt equals createdAt. AWS advances it as a rollout progresses; Floci has no intermediate rollout state to report.

Unknown services

A service reference that does not resolve is returned in failures with reason: MISSING and the ARN the service would have had, rather than being dropped from the response. DescribeServices therefore returns partial results instead of erroring, as AWS does, and aws ecs wait services-stable on a nonexistent service fails immediately instead of polling for its full timeout. A reference supplied as an ARN is echoed back unchanged.

Task Sets

Operation Description
CreateTaskSet Create a task set inside a service
UpdateTaskSet Update a task set's scale
DeleteTaskSet Delete a task set
DescribeTaskSets Describe task sets for a service
UpdateServicePrimaryTaskSet Promote a task set to primary

Container Instances

Operation Description
RegisterContainerInstance Register a container instance with a cluster
DeregisterContainerInstance Deregister a container instance
DescribeContainerInstances Describe container instances
ListContainerInstances List container instance ARNs
UpdateContainerAgent Trigger agent update (stub)
UpdateContainerInstancesState Drain or activate container instances

Capacity Providers

Operation Description
CreateCapacityProvider Create a custom capacity provider
UpdateCapacityProvider Update a capacity provider
DeleteCapacityProvider Delete a capacity provider
DescribeCapacityProviders Describe capacity providers (includes FARGATE built-ins)

Service Deployments & Revisions

Operation Description
DescribeServiceDeployments Describe service deployments
ListServiceDeployments List service deployment ARNs
DescribeServiceRevisions Describe service revisions

Tags

Operation Description
TagResource Add tags to a cluster, service, task, or task definition
UntagResource Remove tags from a resource
ListTagsForResource List tags on a resource

Account Settings & Attributes

Operation Description
PutAccountSetting Set an account-level setting for the calling user
PutAccountSettingDefault Set the default account-level setting
DeleteAccountSetting Delete an account setting
ListAccountSettings List account settings
PutAttributes Set custom key-value attributes on resources
DeleteAttributes Remove attributes from resources
ListAttributes List resources with a given attribute

Agent / State Change Stubs

Operation Description
SubmitTaskStateChange Agent callback stub
SubmitContainerStateChange Agent callback stub
SubmitAttachmentStateChanges Agent callback stub
DiscoverPollEndpoint Returns the agent polling endpoint

Configuration

Variable Default Description
FLOCI_SERVICES_ECS_ENABLED true Enable or disable the ECS service
FLOCI_SERVICES_ECS_MOCK false Skip Docker; tasks go straight to RUNNING (useful for CI)
FLOCI_SERVICES_ECS_DOCKER_NETWORK (unset) Docker network for task containers
FLOCI_SERVICES_ECS_DEFAULT_MEMORY_MB 512 Default memory (MB) when the task definition omits it
FLOCI_SERVICES_ECS_DEFAULT_CPU_UNITS 256 Default CPU units when the task definition omits it

EFS volume ownership

A task's efsVolumeConfiguration volumes are backed by shared local Docker volumes (Floci cannot mount a real EFS file system). A Docker named volume is created root:root 0755, so a task whose image runs as a non-root USER cannot write it. To emulate an EFS access point's RootDirectory.CreationInfo and PosixUser, configure floci.storage.efs.* (all opt-in; the default is a plain named volume, so existing behaviour is unchanged):

Key (floci.storage.efs.) Env AWS equivalent Description
owner-uid FLOCI_STORAGE_EFS_OWNER_UID CreationInfo.OwnerUid Owner uid of the volume root (set together with owner-gid)
owner-gid FLOCI_STORAGE_EFS_OWNER_GID CreationInfo.OwnerGid Owner gid of the volume root (set together with owner-uid)
root-permissions FLOCI_STORAGE_EFS_ROOT_PERMISSIONS CreationInfo.Permissions 3-4 octal digits, e.g. 0777, or 2775 for the setgid bit
mount-user FLOCI_STORAGE_EFS_MOUNT_USER PosixUser {Uid,Gid} Run mounting containers as uid[:gid]
mount-group-add FLOCI_STORAGE_EFS_MOUNT_GROUP_ADD PosixUser supplementary Supplementary gid added to mounting containers
init-image FLOCI_STORAGE_EFS_INIT_IMAGE Image for the one-off chown/chmod of the volume root (default busybox:stable)

owner-uid and owner-gid must be set together (a partial CreationInfo is not valid on AWS). The volume root is initialised once per volume; express the setgid bit through a 4-digit root-permissions (e.g. 2775) so subdirectories inherit the owner gid.

Mock mode

Set FLOCI_SERVICES_ECS_MOCK=true to run without Docker. In this mode tasks skip container launch and immediately transition to RUNNING, then to STOPPED when stopped. This is the recommended mode for unit/integration tests and CI pipelines where Docker-in-Docker is unavailable.

# docker-compose.yml — CI / test environment
services:
  floci:
    image: floci/floci:latest
    environment:
      FLOCI_SERVICES_ECS_MOCK: "true"
# docker-compose.yml — local development (real containers)
services:
  floci:
    image: floci/floci:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      FLOCI_SERVICES_ECS_MOCK: "false"
      FLOCI_SERVICES_ECS_DOCKER_NETWORK: my_network

Docker socket requirement

When mock: false (the default), ECS launches real Docker containers and requires the Docker socket. Mount it and set the network so containers can reach each other. For private registry authentication and other Docker settings see Docker Configuration.

services:
  floci:
    image: floci/floci:latest
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      FLOCI_SERVICES_ECS_DOCKER_NETWORK: aws-local_default

Examples

export AWS_ENDPOINT_URL=http://localhost:4566
export AWS_DEFAULT_REGION=us-east-1
export AWS_ACCESS_KEY_ID=test
export AWS_SECRET_ACCESS_KEY=test

# Create a cluster
aws ecs create-cluster --cluster-name my-cluster \
  --endpoint-url $AWS_ENDPOINT_URL

# Register a task definition
aws ecs register-task-definition \
  --family my-task \
  --container-definitions '[
    {
      "name": "app",
      "image": "nginx:latest",
      "cpu": 256,
      "memory": 512,
      "essential": true,
      "portMappings": [{"containerPort": 80, "protocol": "tcp"}]
    }
  ]' \
  --requires-compatibilities FARGATE \
  --cpu 256 --memory 512 \
  --network-mode awsvpc \
  --endpoint-url $AWS_ENDPOINT_URL

# Run a task
aws ecs run-task \
  --cluster my-cluster \
  --task-definition my-task \
  --launch-type FARGATE \
  --endpoint-url $AWS_ENDPOINT_URL

# Create a service
aws ecs create-service \
  --cluster my-cluster \
  --service-name my-service \
  --task-definition my-task \
  --desired-count 1 \
  --launch-type FARGATE \
  --endpoint-url $AWS_ENDPOINT_URL

# List running tasks
aws ecs list-tasks --cluster my-cluster \
  --endpoint-url $AWS_ENDPOINT_URL

# Stop a task
aws ecs stop-task \
  --cluster my-cluster \
  --task <task-arn> \
  --endpoint-url $AWS_ENDPOINT_URL

# Delete a service
aws ecs delete-service \
  --cluster my-cluster \
  --service my-service \
  --force \
  --endpoint-url $AWS_ENDPOINT_URL

Java SDK Example

EcsClient ecs = EcsClient.builder()
    .endpointOverride(URI.create("http://localhost:4566"))
    .region(Region.US_EAST_1)
    .credentialsProvider(StaticCredentialsProvider.create(
        AwsBasicCredentials.create("test", "test")))
    .build();

// Create cluster
ecs.createCluster(r -> r.clusterName("my-cluster"));

// Register task definition
ecs.registerTaskDefinition(r -> r
    .family("my-task")
    .containerDefinitions(c -> c
        .name("app")
        .image("nginx:latest")
        .cpu(256)
        .memory(512)
        .essential(true))
    .requiresCompatibilities(Compatibility.FARGATE)
    .cpu("256")
    .memory("512")
    .networkMode(NetworkMode.AWSVPC));

// Run a task
RunTaskResponse response = ecs.runTask(r -> r
    .cluster("my-cluster")
    .taskDefinition("my-task")
    .launchType(LaunchType.FARGATE)
    .count(1));

String taskArn = response.tasks().get(0).taskArn();