This article is part 4 of a 4 part guide to running Docker containers on AWS ECS. ECS stands for Elastic Container Service. It is a managed container service that runs docker containers. Although AWS also offers container management with Kubernetes, (EKS) it also has its proprietary solution (ECS).
The other parts of the guide already covered in separate articles are:
- Creating the ECS Cluster – Part 1
- Provision an Image Registry (ECR) and push docker images to the registry – Part 2
- Deploying Containers to the cluster using Task and Service Definitions – Part 3
Part 4 of this guide will cover, “Creating a Pipeline to Update the tasks/containers running on the ECS Cluster,”. The container update happens any time we push a change to the CodeCommit repository.
For this demonstration, we will create a pipeline to update the service and task running on the ECS cluster using CodePipeline. We assume the project source code is on a CodeCommit repository. However, CodePipeline can pick code from various version control tools including:
- GitHub Enterprise Edition.
- An AWS Account.
- Created a User on the account with Permissions to provision resources on the account.
- Created a CodeCommit Repository and uploaded your source code there.
- Already created the ECS cluster and have services and tasks running there.
- Provisioned an ECR registry and uploaded a docker image to the registry.
- A CloudWatch log group or S3 bucket to store your build project logs.
Create a Build Project
Using CodeBuild we are going to create a Build Project that will build a docker image from a docker file pushed to our code commit repository. It will then push the docker image to the ECR Registry.
On the CodeBuild console, click create build project.
ECS CodeBuild Project Configurations:
Next on project configurations, enter your project name and description. Also, you can add tags for your build project.
For source, choose CodeCommit. Assuming you have your project code pushed to a Codecommit Repository.
Next under Environment Configurations, choose the environment you would want your build project to be executed. Since our image is a Linux image, we chose a Linux environment.
For the role, select new service role. N/B: Ensure that the role has the AmazonEC2ContainerRegistryFullAccess policy attached to it. Otherwise, CodeBuild will not work.
ECS CodeBuild BuildSpec.yml:
Under BuildSpec, click Switch to Editor and paste the following code on your buildspec.yml. Ensure that for the docker tag and docker push commands, you replace this with your ECR registry push commands. Also, the docker build image name should be replaced with your respective docker image name.
version: 0.2 phases: install: runtime-versions: docker: 19 commands: - curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip" - unzip awscliv2.zip - ./aws/install pre_build: commands: - echo logging to ecr - $(aws ecr get-login --no-include-email --region eu-central-1) build: commands: - echo starting build on 'date' - cd ./ - docker build -t hello-world . - docker tag hello-world:latest 429758582529.dkr.ecr.eu-central-1.amazonaws.com/hello-world:latest post_build: commands: - echo build completed on 'date' - echo pushing to repo - docker push 429758582529.dkr.ecr.eu-central-1.amazonaws.com/hello-world:latest - echo Writing definitions file... - printf '["name":"Hello_World","imageUri":"%s"]' 429758582529.dkr.ecr.eu-central-1.amazonaws.com/hello-world:latest > HelloWorldtaskdefinition.json artifacts: files: HelloWorldtaskdefinition.json
Since we are pushing a docker image to an ECR registry, there is no need to have artifacts. Hence under artifacts select none. For logs, we will have them pushed to a CloudWatch log group that you had created earlier.
Finally, click create build project.
Create a Pipeline to Deploy to ECS Cluster
After creating a CodeBuild project, Next we will create a pipeline to deploy the docker image to update ECS cluster service and tasks.
On the CodePipeline Console, click create pipeline.
Then, under pipeline settings enter your pipeline name. For Service Role choose New Service Role. Under Advanced Settings choose Default Location for artifact store and default AWS managed key for the encryption key. Then click next.
ECS CodePipeline Add Source Stage:
On the add source stage, select CodeCommit as your source. Then choose your repository and repository branch for your code. Under Change detection options choose CloudWatch Events. This way CloudWatch will actively monitor changes on the repository and anytime it detects a change it auto-starts the pipeline. Click next.
ECS CodePipeline Add Build Stage:
For Add a Build Stage, select your build provider as CodeBuild. Then select a region where you created the Build Project and select the build project name. Use the Build project we created in the “Create a Build Project” section of this article. For Build Type, select single build then click next.
ECS CodePipeline Add Deploy Stage:
Next, we have to add a deploy stage to our pipeline. On the Add Deploy Stage, choose our deploy provider to be Amazon ECS. For the region, select the region where you created your ECS cluster. Then under cluster name, select the name of your ECS cluster. Choose the service name of the ECS service you would like to update on the ECS cluster.
When we created our build project on our buildspec.yml we had created an image definitions file. For this case, it was HelloWorldtaskdefinition.json. Paste the name of that file under the image definitions file section of the deploy stage. Finally, for the deployment timeout, enter the time in minutes that we should wait for the deployment before it times out.
On the review section, review your pipeline settings and if ok with all configurations click create pipeline.
You now have a pipeline that updates an ECS Service and Tasks anytime a change is pushed to the CodeCommit repository. By default, the update is a rolling update. i.e. ECS will deploy a new Task running alongside the older Task. When the new task reaches a steady-state, then a switch is made to the new Task and the old Task is terminated.