Amazon ECS/Fargate

How to use Codefresh to deploy Docker containers to ECS/Fargate

Codefresh can deploy to any ECS or Fargate cluster created in Amazon.

Deploying to Amazon ECS

Deploying to Amazon ECS

Prerequisites

  1. Configure an ECS (or Fargate) Cluster with at least one running instance.
  2. Configure an ECS Service and Task Definition with a reference to the image that you are going to build and push. See the official amazon docs for more details.
  3. Connect your ECR to Codefresh so that it can be used by name in Codefresh pipelines.
  4. Verify you have AWS Credentials (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY), with the following privileges:

JSON

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1479146904000",
      "Effect": "Allow",
      "Action": [
        "ecs:DescribeServices",
        "ecs:DescribeTaskDefinition",
        "ecs:DescribeTasks",
        "ecs:ListClusters",
        "ecs:ListServices",
        "ecs:ListTasks",
        "ecs:RegisterTaskDefinition",
        "ecs:UpdateService"
      ],
      "Resource": [
        "*"
      ]
    }
  ]
}

Create a CI/CD pipeline for ECS/Fargate

Here is the whole pipeline:

codefresh.yml

version: '1.0'
stages:
  - "clone"
  - "build"
  - "deploy"
steps:
  main_clone:
    type: "git-clone"
    description: "Cloning main repository..."
    repo: "${{CF_REPO_OWNER}}/${{CF_REPO_NAME}}"
    revision: "${{CF_BRANCH}}"
    stage: "clone"
    git: github
  BuildingDockerImage:
    stage: "build"
    title: Building Docker Image
    type: build
    image_name: ${{IMAGE}}
    tag: '${{CF_SHORT_REVISION}}'
    dockerfile: Dockerfile.multistage
  Push:
    title: "Pushing image to ECR"
    stage: "deploy"
    type: "push"
    tag: '${{CF_BRANCH_TAG_NORMALIZED}}-${{CF_SHORT_REVISION}}'
    registry: "ecr"
    candidate: "${{BuildingDockerImage}}"
  DeployToFargate:
    stage: "deploy"
    image: codefreshplugins/cf-deploy-ecs
    commands:
      - cfecs-update ${{REGION}} ${{ECS_CLUSTER_NAME}} ${{ECS_SERVICE_NAME}} --image-name ${{IMAGE_PREFIX}}/${{IMAGE}} --image-tag '${{CF_BRANCH_TAG_NORMALIZED}}-${{CF_SHORT_REVISION}}'
    environment:
      - AWS_ACCESS_KEY_ID=${{AWS_ACCESS_KEY_ID}}
      - AWS_SECRET_ACCESS_KEY=${{AWS_SECRET_ACCESS_KEY}}

This pipeline does the following:

  1. Clones the source code with a Git clone step
  2. Uses a build step to create a Docker image
  3. Uses a push step to push the docker image to ECR. The registry was previously connected in Codefresh with the ecr identifier.
  4. Runs codefreshplugins/cf-deploy-ecs to perform the actual deployment

The pipeline needs environment variables that hold all the required parameters

ECS environment variables

ECS environment variables

Note that the --image-name and --image-tag pair should comprise the full name of the image that was pushed to the registry (including the registry name) in order to be correctly referred by the corresponding Task Definition.

Deployment Flow

The codefreshplugins/cf-deploy-ecs step performs the following:

  1. Gets the ECS service by specified aws-region, ecs-cluster, and service-names.
  2. Creates a new revision from the current task definition of the service. If --image-name and --image-tag are provided, it replaces the image tag.
  3. Runs the update-service command with the new task definition revision.
  4. Waits for the deployment to complete.
    • Deployment is successfully completed if runningCount == desiredCount for PRIMARY deployment - see aws ecs describe-service
    • The cfecs-update command exits with a timeout error if after –timeout (default = 900s) runningCount does not equal desiredCount
    • The cfecs-update exits with an error if –max-failed (default = 2) or more ECS tasks were stopped with error for the task definition that you are deploying. ECS continuously retries failed tasks.

You can also find the same step in the form of a Codefresh plugin.