AWS DevOps & Developer Productivity Blog
Set up a build pipeline with Jenkins and Amazon ECS
FROM python:2-onbuild CMD [ "python", "./application.py" ]
Setup the build environment
Install and configure Jenkins, Docker and Nginx
# yum update -y # yum install -y docker nginx git
# wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo # rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key # yum install jenkins
server { listen 80; server_name _; location / { proxy_pass http://127.0.0.1:8080; } }
# usermod -a -G docker jenkins
# service docker start # service jenkins start # service nginx start # chkconfig docker on # chkconfig jenkins on # chkconfig nginx on


Install and configure Jenkins plugins

Install and configure the Amazon ECS CLI
# sudo -su jenkins > aws configure
Login to Docker Hub
The Jenkins user needs to login to Docker Hub before doing the first build:
# docker login
Create a task definition template
{ "family": "flask-signup", "containerDefinitions": [ { "image": "your-repository/flask-signup:v_%BUILD_NUMBER%", "name": "flask-signup", "cpu": 10, "memory": 256, "essential": true, "portMappings": [ { "containerPort": 5000, "hostPort": 80 } ] } ] }
# sed -e "s;%BUILD_NUMBER%;0;g" flask-signup.json > flask-signup-v_0.json # aws ecs register-task-definition --cli-input-json file://flask-signup-v_0.json { "taskDefinition": { "volumes": [], "taskDefinitionArn": "arn:aws:ecs:us-east-1:123456789012:task-definition/flask-signup:1", "containerDefinitions": [ { "name": "flask-signup", "image": "your-repository/flask-signup:v_0", "cpu": 10, "portMappings": [ { "containerPort": 5000, "hostPort": 80 } ], "memory": 256, "essential": true } ], "family": "flask-signup", "revision": 1 } }
Create the ECS IAM Role, an ELB and your service definition
# aws ecs create-service --cluster default --service-name flask-signup-service --task-definition flask-signup --load-balancers loadBalancerName=elb-flask-signup-1985465812,containerName=flask-signup,containerPort=5000 --role ecs-service-role --desired-count 0 { "service": { "status": "ACTIVE", "taskDefinition": "arn:aws:ecs:us-east-1:123456789012:task-definition/flask-signup:1", "desiredCount": 0, "serviceName": "flask-signup-service", "clusterArn": "arn:aws:ecs:us-east-1:123456789012:cluster/default", "serviceArn": "arn:aws:ecs:us-east-1:123456789012:service/flask-signup-service", "runningCount": 0 } }
Configure the Jenkins build
- Under GitHub Project, add the path of your GitHub repository – e.g. https://github.com/awslabs/py-flask-signup-docker. In addition to the application source code, the repository contains the Dockerfile used to build the image, as explained at the beginning of this walkthrough.
-
Under Source Code Management provide the Repository URL for Git, e.g. https://github.com/awslabs/py-flask-signup-docker.
-
In the Build Triggers section, select Build when a change is pushed to GitHub.
-
In the Build section, add a Docker build and publish step to the job and configure it to publish to your Docker registry repository (e.g. DockerHub) and add a tag to identify the image (e.g. v_$BUILD_NUMBER).

- Add a Execute Shell step and add the ECS CLI commands to start a new task on your ECS cluster.
#!/bin/bash SERVICE_NAME="flask-signup-service" IMAGE_VERSION="v_"${BUILD_NUMBER} TASK_FAMILY="flask-signup" # Create a new task definition for this build sed -e "s;%BUILD_NUMBER%;${BUILD_NUMBER};g" flask-signup.json > flask-signup-v_${BUILD_NUMBER}.json aws ecs register-task-definition --family flask-signup --cli-input-json file://flask-signup-v_${BUILD_NUMBER}.json # Update the service with the new task definition and desired count TASK_REVISION=`aws ecs describe-task-definition --task-definition flask-signup | egrep "revision" | tr "/" " " | awk '{print $2}' | sed 's/"$//'` DESIRED_COUNT=`aws ecs describe-services --services ${SERVICE_NAME} | egrep "desiredCount" | tr "/" " " | awk '{print $2}' | sed 's/,$//'` if [ ${DESIRED_COUNT} = "0" ]; then DESIRED_COUNT="1" fi aws ecs update-service --cluster default --service ${SERVICE_NAME} --task-definition ${TASK_FAMILY}:${TASK_REVISION} --desired-count ${DESIRED_COUNT}

Happy building
# git add * # git commit -m "Kicking off Jenkins build" # git push origin master

Conclusion