Kyle Pericak

"It works in my environment."

Wed 15 January 2020

CodePipeline: Continuous Delivery to AWS ECR

Posted by Kyle Pericak in cloud   

This post is linked to from the AWS: Deep Dive Project


Workflow

  1. Commit code to AWS CodeCommit
  2. CloudWatch rule triggers CodePipeline
  3. CodePipeline uses CodeBuild to build the Docker image
  4. CodePipeline pushes the image to ECR

Deploy Code to CodeCommit

  1. Open CodeCommit.
  2. Create a repository
  3. Go to your IAM page and edit your user.
    1. Look for "HTTPS Git credentials for AWS CodeCommit"
    2. click Generate Credentials
    3. Save your credentials.
  4. Grab the HTTPS URL for your repository and git clone it. Use your new credentials.
  5. Commit your code (including a Dockerfile) to the CodeCommit repository.

Write buildspec.yml

AWS CodeBuild will look for a buildspec.yml file to dictate its actions. This is where we define how the image will be built. Put it in your CodeCommit project's root directory.

Here's mine. This will build a docker image and tag it with a timestamp, then push it to ECR as the timestamp and latest. The variables are defined inside the build as Environment Variables.

# buildspec.yml
version: 0.2

phases:
  install:
    runtime-versions:
      docker: 18
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - $(aws ecr get-login --no-include-email --region ca-central-1)
      - IMAGE_TAG=$(date +%Y.%m.%d.%I.%M)
  build:
    commands:
      - echo Build started on `date`
      - echo "Building the Docker image."
      - docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      - docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:latest
  post_build:
    commands:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/$IMAGE_REPO_NAME:latest

Define the Pipeline

Cloud Build Role

Bad Practice Alert: These steps don't apply the principal of least privilege. You should lock down your role to be allowed to do only the minimum that it needs to do.

  1. In the IAM page, create a new role.
  2. It will be used by CodeBuild.
  3. Assing the following policies (again, more than it needs)
    • CloudWatchLogsFullAccess
    • AWSCodeBuildAdminAccess
    • AmazonS3FullAccess
    • AmazonEC2ContainerRegistryFullAccess
    • AWSCodeCommitFullAccess
  4. Name: Assign a name, such as CloudBuild-Admin

Define CloudBuild project

  1. Navigate to the CloudBuild Console
  2. Create build project
  3. No build badge
  4. Source provider: CodeCommit
  5. Choose your repository
  6. Choose your branch
  7. Managed Image
  8. Operating System: Ubuntu
  9. Runtime: Standard
  10. Image: aws/codebuild/standard:3.0
  11. Image version: latest
  12. Environment type: Linux
  13. Privileged: true
  14. Service Role: Existing service role. Use the one you just made.
  15. Allow CodeBuild to modify this role: False (we gave it admin)
  16. Additional Configuration - Environment variables (click Add to get more) - IMAGE_REPO_NAME: (your image name) - AWS_ACCOUNT_ID: (your numeric AWS account iD) - AWS_DEFAULT_REGION: ca-central-1
  17. Buildspec: Use a buildspec file
  18. Artifacts: No artifacts
  19. Logs: Give a group and stream name for CloudWatch
  20. Create Build Project

Now test the build by clicking "Start build". It should create your image. You'll need to disable artifacts.

Once the build works and your image is pushed successfully to ECR, you can move on to setting up a pipeline so this happens automatically.

Create Pipeline Role

Bad Practice Alert: These steps don't apply the principal of least privilege. You should lock down your role to be allowed to do only the minimum that it needs to do.

  1. In the IAM page, create a new role.
  2. It will be used by CodeBuild.
  3. Assing the following policies (again, more than it needs)
    • CloudWatchLogsFullAccess
    • AWSCodeBuildAdminAccess
    • AmazonS3FullAccess
    • AmazonEC2ContainerRegistryFullAccess
    • AWSCodeCommitFullAccess
  4. Name: Assign a name, such as CloudBuild-Admin

Define the pipeline

  1. Open the CodePipeline console
  2. Click Create Pipeline
  3. Name the pipeline
  4. Service Role: New service role
  5. Role Name: Pick a name
  6. Allow AWS CodePipeline to create a role
  7. Next
  8. Source Provider: AWS CodeCommit
  9. Repository Name: Select the repository name
  10. Branch name: master
  11. Change detection: Amazon CloudWatch Events
  12. Next
  13. Build Provider: AWS CodeBuild
  14. Region: Canada (Central)
  15. Project Name: Create Project
    1. Project Name: Choose a name
    2. Description: Add a description
    3. Environment image: Managed Image
    4. Operating System: Ubuntu
    5. Runtimes: Standard
    6. Image: aws/codebuild/standard:3.0
    7. Image version: Always use the latest
    8. Environment type: Linux
    9. Privileged: True
    10. Service Role: New service role
    11. Role Name: default name is fine
    12. Advanced Configuration - Environment variables (click Add to get more)
      • IMAGE_REPO_NAME: (your image name)
      • AWS_ACCOUNT_ID: (your numeric AWS account iD)
      • AWS_DEFAULT_REGION: ca-central-1
    13. Build specifications: Use a buildspec file
    14. Buildspec name: Leave it blank so it uses buildspec.yml
    15. CloudWatch logs: True
    16. Group name: pick a name
    17. Stream name: pick a name
    18. S3 logs: false
    19. Continue to CodePipeline
  16. Next
  17. Skip deploy stage, pushing to ECR is enough
  18. Create pipeline

This will re-run the build that you tested before. It should pass again.


Javascript appears to be disabled. Comments can't load.