Search code examples
amazon-web-servicesamazon-ecs

I can't deploy a new container to my ECS cluster because of ports in use


The task definition my Service uses is pulling the "latest" tagged version of my image.

When I update my service though and "force new deployment" i look at the events and see this:

service MYSERVICE was unable to place a task because no container instance met all of its requirements. The closest matching container-instance .... is already using a port required by your task

I then went to my cluster and stopped all tasks.

Then went back to my Service and updated with force new deploy again. This seems to have worked

Will I have to stop all tasks and update the service each time I want to deploy a new image? Or is there a "right" way to do this?

EDIT: So if I stop one task the service will automatically replace it. So I can update my service and "force new deploy" then stop one task at a time to get a sort of a rolling update. Not sure if there is a feature to automate that beyond my own scripting

Just to follow up, as stated in the answers I just needed to use dynamic port mapping.

Initially, when I first started I didn't have a load balancer so I was hitting the EC2 instances directly to access the running containers. Of course in order to do this I had to expose a static port on the EC2 host.

I added a load balancer but kept that static port mapping not understanding how dynamic port mapping worked. All I had to do was change my task definition to set the host port to "0". Now I have no static port mappings on the hosts, the NLB does the routing for me and deploys work as expected


Solution

  • When using ECS (or any other orchestrator) it is encouraged that you use Dynamic Port Mapping.

    Basically ECS will assign a random unassigned port to your container. ECS then offers ways to retrieve that port number, using the agent instrospection API or the docker client itself. However I wouldn't try to retrieve the port, I would instead rely on an Application Load Balancer (ALB) which allows you to use a single endpoint to access any targeted containers independently of its dynamically assigned port. When updating your service the ALB will seamlessly transition to the newest version of the container without any disruption.

    Finally, inside the container the local port will remain the same so you don't have to handle things differently.