22

I want to automate the deployment of my application by having my ECS service launch with the latest Docker image. From what I've read, the way to deploy a new image version is as follows:

  1. Create a new task revision (after updating the image on your Docker repository).
  2. Update the service and specify the new revision.

This seems to work, but I want to do this all through CLI so I can script it. #2 seems easy enough to do through the AWS CLI with update-service, but I don't see a way to do #1 without specifying the entire Task JSON all over again as with register-task-definition (my JSON will include credentials in environment variables, so I want to have that in as few places as possible).

Is this how I should be automating deployment of my ECS Service updates? And if so, is there a "good" way to have the Task Definition launch a new revision (i.e. without duplicating everything)?

Jake Kreider
  • 950
  • 7
  • 12
  • 2
    The trick to this is that `describe-task-definition` will contain your original task definition with _containerDefinitions_ as the key. I've had success with modifying this then running `register-task-definition` to register a new definition. If you're worried about ENV, easiest solution is to use one of the non-bash SDKs. – Luke Peterson Apr 28 '16 at 00:27

3 Answers3

17

Yes, that is the correct approach.

And no, with the current API, you can't register a new revision of an existing task definition without duplicating it.

If you didn't use the CLI to generate the original task definition (or don't want to reuse the original commands that generated it), you could try something like the following through the CLI:

OLD_TASK_DEF=$(aws ecs describe-task-definition --task-definition <task_family_name>)
NEW_CONTAINER_DEFS=$(echo $OLD_TASK_DEF | jq '.taskDefinition.containerDefinitions' | jq '.[0].image="<new_image_name>"')
aws ecs register-task-definition --family <task_family_name> --container-definitions "'$(echo $NEW_CONTAINER_DEFS)'"

Not 100% secure as the last command's --container-defintions argument (which includes "environment" entries) will still be visible through processes like ps. One of the AWS SDKs would give better peace of mind.

Matt Callanan
  • 186
  • 1
  • 4
  • You may also need other sections such as volumes. Just use jq to parse it, then append the options (e.g. --volumes VOLUMES_DEF) to the `register-task-definition` – Ding-Yi Chen Dec 06 '17 at 06:51
5

The answer provided by Matt Callanan did not work for me: I received an error on this part:

--container-definitions "'$(echo $NEW_CONTAINER_DEFS)'"

Resulted in: Error parsing parameter '--container-definitions': Expected: '=', received: ''' for input:

'{ environment: [ { etc etc....

What I did to resolve it was:

TASK_FAMILY=<task familiy name> 
DOCKER_IMAGE=<new_image_name>
LATEST_TASK_DEFINITION=$(aws ecs describe-task-definition --task-definition ${TASK_FAMILY})

echo $LATEST_TASK_DEFINITION \
     | jq '{containerDefinitions: .taskDefinition.containerDefinitions, volumes: .taskDefinition.volumes}' \
     | jq '.containerDefinitions[0].image='\"${DOCKER_IMAGE}\" \
     > /tmp/tmp.json

aws ecs register-task-definition --family ${TASK_FAMILY} --cli-input-json file:///tmp/tmp.json

I take both the containerDefinitions and volumes elements from the original json document, because my containerDefinition uses these volumes (so it's not needed if you don't use volumes).

veuncent
  • 1,599
  • 1
  • 20
  • 17
0
#!/bin/bash
SERVICE_NAME="your service name"
IMAGE_VERSION="v_"${BUILD_NUMBER}
TASK_FAMILY="your task defination name"
CLUSTER="your cluster name"
REGION="your region"


echo "=====================Create a new task definition for this build==========================="
sed -e "s;%BUILD_NUMBER%;${BUILD_NUMBER};g" taskdef.json > ${TASK_FAMILY}-${IMAGE_VERSION}.json

echo "=================Resgistring the task defination==========================================="
aws ecs register-task-definition  --family ${TASK_FAMILY} --cli-input-json  file://${TASK_FAMILY}-${IMAGE_VERSION}.json --region ${REGION}

echo "================Update the service with the new task definition and desired count================"
TASK_REVISION=`aws ecs describe-task-definition --task-definition  ${TASK_FAMILY}  --region ${REGION} | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'`


DESIRED_COUNT=`aws ecs describe-services --cluster ${CLUSTER} --services ${SERVICE_NAME}  --region ${REGION} | jq .services[].desiredCount`
if [ ${DESIRED_COUNT} = "0" ]; then
    DESIRED_COUNT="1"
fi

echo "===============Updating the service=============================================================="
aws ecs update-service --cluster ${CLUSTER} --service ${SERVICE_NAME} --task-definition ${TASK_FAMILY}:${TASK_REVISION} --desired-count ${DESIRED_COUNT} --region ${REGION}


    enter code here
Nikolai Shevchenko
  • 7,083
  • 8
  • 33
  • 42
Santosh Reddy
  • 57
  • 1
  • 9