What is the right approach to make my Amazon ECS tasks update their Docker images, once said images have been updated in the corresponding registry?
Using AWS cli I tried aws ecs update-service as suggested above. Did not pick up latest docker from ECR. In the end, I rerun my Ansible playbook that created the ECS cluster. The version of the task definition is bumped when ecs_taskdefinition runs. Then all is good. The new docker image is picked up.
Truthfully not sure if the task version change forces the redeploy, or if the playbook using the ecs_service causes the task to reload.
If anyone is interested, I'll get permission to publish a sanitized version of my playbook.
Ran into same issue. After spending hours, have concluded these simplified steps for automated deployment of updated image:
1.ECS task definition changes: For a better understanding, let's assume you have created a task definition with below details (note: these numbers would change accordingly as per your task definition):
launch_type = EC2
desired_count = 1
Then you need to make the following changes:
deployment_minimum_healthy_percent = 0 //this does the trick, if not set to zero the force deployment wont happen as ECS won't allow to stop the current running task
deployment_maximum_percent = 200 //for allowing rolling update
2.Tag your image as <your-image-name>:latest . The latest key takes care of getting pulled by the respective ECS task.
sudo docker build -t imageX:master . //build your image with some tag
sudo -s eval $(aws ecr get-login --no-include-email --region us-east-1) //login to ECR
sudo docker tag imageX:master <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/<your-image-name>:latest //tag your image with latest tag
3.Push to the image to ECR
sudo docker push <your_account_id>.dkr.ecr.us-east-1.amazonaws.com/<your-image-name>:latest
4.apply force-deployment
sudo aws ecs update-service --cluster <your-cluster-name> --service <your-service-name> --force-new-deployment --region us-east-1
Note: I have written all the commands assuming the region to be us-east-1. Just replace it with your respective region while implementing.
There are two ways to do this.
First, use AWS CodeDeploy. You can config Blue/Green deployment sections in ECS service definition. This includes a CodeDeployRoleForECS, another TargetGroup for switch, and a test Listener (optional). AWS ECS will create CodeDeploy application and deployment group and link these CodeDeploy resources with your ECS Cluster/Service and your ELB/TargetGroups for you. Then you can use CodeDeploy to initiate a deployment, in which you need to enter an AppSpec that specifies using what task/container to update what service. Here is where you specify your new task/container. Then, you will see new instances are spin up in the new TargetGroup and the old TargetGroup is disconnected to the ELB, and soon the old instances registered to the old TargetGroup will be terminated.
This sounds very complicated. Actually, since/if you have enabled auto scaling on your ECS service, a simple way to do it is to just force a new deployment using console or cli, like a gentleman here pointed out:
aws ecs update-service --cluster <cluster name> --service <service name> --force-new-deployment
In this way you can still use the "rolling update" deployment type, and ECS will simply spin up new instances and drain the old ones with no downtime of your service if everything is OK. The bad side is you lose fine control on the deployment and you cannot roll back to previous version if there is an error and this will break the ongoing service. But this is a really simple way to go.
BTW, don't forget to set proper numbers for Minimum healthy percent and Maximum percent, like 100 and 200.
AWS CodePipeline.
You can set ECR as a source, and ECS as a target to deploy to.
The following commands worked for me
docker build -t <repo> .
docker push <repo>
ecs-cli compose stop
ecs-cli compose start
Following worked for me in case the docker image tag is same:
Following api works as well:
aws ecs update-service --cluster <cluster_name> --service <service_name> --force-new-deployment