Self-hosted service
fabfuel/ecs-deploy avatar
fabfuel/ecs-deploy

ecs-deploy: a CLI for Amazon ECS deploys, scaling and rollbacks

Powerful CLI tool to simplify Amazon ECS deployments, rollbacks & scaling

906 stars152 forksPythonNOASSERTION

At a glance

What is it?
ecs-deploy is a Python command line tool that wraps boto3 so that the awkward parts of Amazon ECS become short commands, covering redeploys, new image tags, per container overrides, scaling, one-off tasks, scheduled tasks and task definition revisions. It installs from PyPI or Homebrew, runs as a Docker image, and the CLI is driven by click.
Who is it for?
Adopt ecs-deploy if you run Amazon ECS and find that the raw API calls for a redeploy, a tag bump or a scale operation are longer than they should be, because the tool collapses them into one-liners and handles the task definition revision for you. Do not adopt it if you want a pipeline definition tool, since it deploys to existing services rather than describing infrastructure.
Can I use it commercially?
Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
Is it still maintained?
Yes. The repository last received commits 67 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What the tool actually wraps

ecs-deploy is described as simplifying deployments on Amazon ECS by providing a convenience CLI tool for complex actions which are executed often. The emphasis is on the actions that recur, which is the right filter for a helper like this.

The key features list is short and specific. It supports complex task definitions, with multiple containers and a task role. It can easily redeploy the current task definition, including the docker pull of eventually updated images. It can deploy new versions or tags for all containers or just a single container in the task definition. It scales up or down by adjusting the desired count of running tasks. It adds or adjusts container environment variables. It runs one-off tasks from the command line. And it automatically monitors deployments in New Relic.

The implementation is a Python package built on boto3, the official AWS Python library, and the requirements file pins the dependencies it needs: click for the command line, click-log for logging, botocore and boto3 for AWS, requests for the HTTP calls, and dictdiffer for computing what changed between two task definitions.

That last dependency is the one that explains the tool's behaviour. Comparing the current and the new task definition, and applying only the differences, is how a deploy avoids clobbering settings you did not intend to change.

Five commands and what each one does

There are five actions, and the short version is the whole interface.

The deploy action redeploys a service, either without any modifications or with a new image, environment variable, docker label and/or command definition.

The scale action scales a service up or down and changes the number of running tasks.

The run action runs a one-off task based on an existing task definition, with the option to override command, environment variables, docker labels and/or CPU and memory.

The update action updates a task definition by creating a new revision, to set a new image, environment variable, docker label and/or command definition.

The cron action updates a task definition and updates an events rule, the scheduled task, to use the new task definition.

The short examples in the README make the shape clear.

bash
$ ecs deploy my-cluster my-service --tag 1.2.3

bash

bash
$ ecs scale my-cluster my-service 4

bash

bash
$ ecs cron my-cluster my-task my-rule

bash

Every action takes the cluster name and the service or task name as positional arguments, and the flags modify what gets deployed. For details the README points you at the per action help, for example ecs deploy --help, ecs scale --help and ecs run --help, which is the standard click behaviour and means the tool is self-documenting.

Deploying one container or five, and forcing a redeploy

The deploy action has several distinct modes, and they are where the time saving comes from.

A plain redeploy duplicates the current task definition and causes the service to redeploy all running tasks, pulling the most recent image versions. That is the everyday case, for when you rebuilt an image under the same tag.

When the image tag points to a new digest and you want ECS to resolve it again, the force-new-deployment flag asks ECS to start a new deployment even when the service is already using the requested task definition.

bash
$ ecs deploy my-cluster my-service --force-new-deployment

bash

Changing the tag for all images in all containers is a single flag.

bash
$ ecs deploy my-cluster my-service -t 1.2.3

bash

Changing one container's image names the container.

bash
$ ecs deploy my-cluster my-service --image webserver nginx:1.11.8

bash

And the image option can be passed several times to change several containers at once, with each pair naming the container and its image.

bash
$ ecs deploy my-cluster my-service -i webserver nginx:1.9 -i application my-app:1.2.3

bash

There is also a task parameter for deploying any task definition independently of which one the service is currently using, and the documentation lists the accepted forms for its value.

Credentials, IAM and the Docker caveat

Because the tool is built on boto3, credential configuration is the standard AWS one. The README points at the boto3 configuration documentation and gives the simplest option, running aws configure. Alternatively you can pass the credentials through the access-key-id and secret-access-key options, or select a profile with the profile option.

For a deploy script running as a role or user without full AWS access, the README lists the ECS permissions needed: ecs:ListServices, ecs:UpdateService, ecs:ListTasks, ecs:RegisterTaskDefinition, ecs:DescribeServices, ecs:DescribeTasks, ecs:ListTaskDefinitions and ecs:DeregisterTaskDefinition. If you use custom IAM permissions you also need the iam:PassRole policy set for each IAM role.

The README notes that not every permission is required for every action, so you can tighten the list based on what you actually use. There is also the pre-specified AmazonECS_FullAccess policy as the blunt alternative.

The Docker route has one sharp edge. Running the tool as a container means the configuration described above does not apply, and you have to provide credentials and the AWS region as command attributes or environment variables instead.

bash
docker run fabfuel/ecs-deploy:1.10.2 ecs deploy my-cluster my-service --region eu-central-1 --access-key-id ABC --secret-access-key ABC

bash

That is a deliberate consequence of not mounting your local AWS config into the container, and it is the sort of thing that surprises people on their first Docker run.

Installing it three ways

The package is on PyPI, so the simplest install is a pip install of ecs-deploy.

bash
$ pip install ecs-deploy

bash

Homebrew users have a formula, so brew install ecs-deploy also works.

And the Docker image on Docker Hub has every version starting from 1.7.1 available. The tags are named so you can pick a specific version, with master and latest pointing at the latest stable version and develop at the newest development version. The README walks through running a specific stable version from that set.

bash
docker run fabfuel/ecs-deploy:1.10.2

bash

The Dockerfile for the project is short. It is based on python:3.13-alpine, copies the source in, installs the requirements and then the package itself, and sets the default command to ecs.

bash
FROM python:3.13-alpine

ADD . /usr/src/app
WORKDIR /usr/src/app

RUN ["python", "-m", "pip", "install", "-r", "requirements.txt"]
RUN ["python", "-m", "pip", "install", "."]

CMD ["ecs"]

bash

The Python package registers a console script named ecs, so the installed command is ecs and not ecs-deploy, which is worth knowing before you go looking for the wrong binary.

Maintenance state, versioning and the licence question

The release history is the part of this project that needs attention, because it stops well before the code does.

The listed releases are 1.14.0 for multi-account usage from 2022-11-03, 1.13.0 for task-wide CPU and memory limits and Docker Hub images from 2022-04-20, and 1.12.0 for environment via files, Docker tags and lots of flags from 2021-08-15.

So the newest tagged release is from late 2022, while the repository is not archived and the last push was on 2026-08-17, on the develop branch rather than master. The classification of a release as the newest stable and the development branch as the newest development version suggests that the tagged releases are what most people get from PyPI, and the work since then lives on the branch.

That gap has a practical consequence. If you install from PyPI you get 1.14.0 from 2022, and if you want the recent changes you need the develop branch or a Docker develop tag. Neither is wrong, but you should know which one you have, because the Python versions listed in the setup metadata include 3.12 and 3.13, which are much newer than the release date of 1.14.0 would suggest.

The licence field on the repository records a custom type that GitHub cannot classify, and the tree contains a LICENSE.rst file. The packaging metadata in setup.py declares the licence as BSD-3-Clause and names Fabian Fuelling as the author, so read LICENSE.rst for the authoritative terms rather than relying on the classifier.

Editorial conclusion

Adopt ecs-deploy if you run Amazon ECS and find that the raw API calls for a redeploy, a tag bump or a scale operation are longer than they should be, because the tool collapses them into one-liners and handles the task definition revision for you. Do not adopt it if you want a pipeline definition tool, since it deploys to existing services rather than describing infrastructure. Verify first that your IAM principal has the listed ECS permissions plus iam:PassRole for each task role, that your Python is 3.10 or newer, that the AWS region and credentials are available since the Docker image deliberately does not read the local configuration file, and that the version you install matches the release you tested, since the newest tagged release is 1.14.0 while the default branch is develop.

Frequently asked questions

How do I install ecs-deploy?

Run pip install ecs-deploy from PyPI, or brew install ecs-deploy with Homebrew. Every version from 1.7.1 onwards is also on Docker Hub as fabfuel/ecs-deploy, where the master and latest tags point at the latest stable build and develop at the newest development build.

Which AWS IAM permissions does ecs-deploy need?

The documented minimal set is ecs:ListServices, ecs:UpdateService, ecs:ListTasks, ecs:RegisterTaskDefinition, ecs:DescribeServices, ecs:DescribeTasks, ecs:ListTaskDefinitions and ecs:DeregisterTaskDefinition, plus iam:PassRole for each IAM role. Not every permission is needed for every action, and AmazonECS_FullAccess is offered as a simpler alternative.

How do I deploy a new image tag to just one container?

Use the image option with the container name and the image, for example ecs deploy my-cluster my-service --image webserver nginx:1.11.8. The option can be passed several times to change several containers, and the short tag option changes all images in all containers.

Why does ecs-deploy not find my AWS credentials when run in Docker?

Because running it as a container means the local configuration does not apply. You have to provide the region and credentials as command attributes or environment variables, for example docker run fabfuel/ecs-deploy:1.10.2 ecs deploy my-cluster my-service --region eu-central-1 --access-key-id ABC --secret-access-key ABC.

Official sources

  1. fabfuel/ecs-deploy on GitHub
  2. Issues
  3. README
  4. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/fabfuel-ecs-deploy.svg)](https://hysenlabs.com/projects/fabfuel-ecs-deploy)

Was this useful?