Answers: <p>For simple use case described I would suggest checking Elastic Beanstalk for Docker, it's not the minimal solution like bare ECS usage, but you can benefit from auto-managed and configured services like ELB, EC2 AutoScale, health monitoring and much more.</p>
  
  <p>High-level summary:</p>
  
  <ol>
  <li>Configure Elastic Beanstalk to use specific tag myimage:tested</li>
  <li>Use Code Pipeline/Build to build, test and promote tag "tested"</li>
  <li>Trigger Elastic Beanstalk deployment, which will pull promoted image myimage:tested to all instances, different deployment strategies available.</li>
  </ol>
  
  <p>This approach based on re-using same tag, alternative approach would be generating tag with build id, for example myimage:tested-42, this will require updating Elastic Beanstalk each time with new tag, but gives more granular control on deployed revision.</p>
  
Answers: CC BY-SA 3.0
Answers: 2017-03-26T18:58:15.370Z
Answers: 2017-03-26T19:33:44.193Z
Answers: 2017-03-26T19:33:44.193Z
Answers: rombob
Answers: <p>I second elastic beanstalk for its simplicity; it is very easy to setup and deploy.  </p>
  
  <p>If you are familiar with docker-compose, another approach would be to define docker-compose.yml and directly deploy on ECS with ecs-cli.</p>
  
Answers: CC BY-SA 3.0
Answers: 2017-04-03T22:02:40.717Z
Answers: 2017-04-03T22:02:40.717Z
Answers: AnthonyWC
Answers: <p>I would keep the ECS container instances (I'm talking about the <em>Docker hosts</em> - I don't like AWS terminology here) and the deployment as two separate things.</p>
  
  <p>Get your ECS stack up and running. You can manage it through CloudFormation and Auto-scaling groups, that's fine. Just think of your cluster as a platform where you will deploy <em>to</em>, not something you need to <em>redeploy</em>.</p>
  
  <p>Then, for CD, the easiest method by far is to update the service definition to use a new task definition and let ECS rolling update the containers for you.</p>
  
  <p>Every time it start a task, ECS will run docker pull image:tag even if it has the image locally to make sure it has the latest version of that image:tag. So the image tag you use really don't matter (there is no need to change the tag on every build).</p>
  
  <p>That means that you can build myimage:latest over and over in order to deploy it easily.</p>
  
  <p>What you need is a task definition where the image = myimage:latest. Create a service with that task definition and every time that ECS start a task (an instance of your service) it will be the most recent "myimage:latest" you have built.</p>
  
  <p>From there, you are missing only one piece in the puzzle, from CodeDeploy, you can call something, perhaps a lambda function, to create a new revision of your task definition and update your service and ECS will automatically create new tasks for that revision and remove the old tasks.</p>
  
  <p>An example:</p>
  
  <p>Let's assume you have created a service called MyService. That you have configured that service to run 2 tasks for the task definition MyTaskDefinition:1 (revision 1). In that task definition, you have one container definition which image is set to "myimage:latest".</p>
  
  <ol>
  <li>Yesterday you have build myimage:latest which had the ID (SHA) 365d8f7bf565.</li>
  <li>Your container instance ABC is running a task named MyTaskDefinition-<strong>1</strong>-containerName-someLongId. when you inspect that container, it's running the image "sha256:365d8f7bf565.........."</li>
  <li>Your other container instance DEF is running another task. It has a similar name (only the ID differ), but it's running the same image.</li>
  <li>You push a change to your repo.</li>
  <li>CodePipeline picks up that change, build and publish the image to ECR.</li>
  <li>That new Docker image is also myimage:latest, but its ID (SHA) is f7ec5e54ac96</li>
  <li>Now you need to add a step to your pipeline to use Lambda functions and the AWS NodeJS SDK to do some calls to your cluster:
  
  <ol>
  <li>Create a new task definition (which will be exactly the same as before). That will be MyTaskDefinition:2</li>
  <li>Update your MyService to use MyTaskDefinition:2 (instead of 1)</li>
  </ol></li>
  <li>ECS will create new tasks. The container names will MyTaskDefinition-<strong>2</strong>-containerName-someLongId. When you inspect those containers, you'll see that they will be running "sha256:f7ec5e54ac96.......". Perhaps you'll have 2 tasks on the container instance ABC, perhaps they will be sprayed out (that depends on your service's configuration)</li>
  <li>After some time ECS will remove the old task MyTaskDefinition-1-containerName-someLongId from ABC and DEF.</li>
  </ol>
  
  <p>Note: you don't actually need to create a new task definition. If you want you could instead retrieve the service's tasks list and manually stop them one by one. You should wait for ECS to restart a task before stoping a new one (that is: stop the first container, wait for ECS to replace it, stop the second container). When ECS restart the container, it will grab the most recent myimage:latest built, as explained before. I just think creating a new task definition is easier and less error prone (no logic required to wait and check, ECS will handle the rolling update for you if you have a new task definition).</p>
  
Answers: CC BY-SA 3.0
Answers: 2017-03-03T05:17:20.027Z
Answers: Amazing - I would call your answer as the missing manual for the CI/CD for docker. Thank you.
Answers: Naveen Vijay
Answers: CC BY-SA 3.0
Answers: 2017-03-03T05:13:37.867Z
Answers: 2017-03-03T05:13:37.867Z
Answers: Alexandre
Body: <p>I am using AWS Code Pipeline, Code Build to create a new Docker container and push it to ECR.</p>
  
  <p>My application is a simple straight-forward single-container based. What would be less friction approach to pull down current running Container and re-launch a new Container from the ECS registry (output of Code Build thru Code Pipeline).</p>
  
  <p>I tried CloudFormation with EC2 user data, custom scripts on one side and CloudFormation with ECS with task definition on the other side (not successful yet). I strongly feel there must be more obvious and simpler approach.</p>
  
Tags: <continuous-integration><containers><continuous-delivery><amazon-ecs>
Title: Simple CI/CD Containers in AWS
UserDisplayName: Naveen Vijay
ThreadText: # Simple CI/CD Containers in AWS
  
  (Asked by: username_0 on 2017-03-03)
  
  I am using AWS Code Pipeline, Code Build to create a new Docker container and push it to ECR.
  
  My application is a simple straight-forward single-container based. What would be less friction approach to pull down current running Container and re-launch a new Container from the ECS registry (output of Code Build thru Code Pipeline).
  
  I tried CloudFormation with EC2 user data, custom scripts on one side and CloudFormation with ECS with task definition on the other side (not successful yet). I strongly feel there must be more obvious and simpler approach.
  
  **Tags:** continuous-integration, containers, continuous-delivery, amazon-ecs
  
  
  ---
  
  ## 3 answers
  
  ### Answer by username_3 on 2017-03-03. Score: 18 | Accepted answer
  
  I would keep the ECS container instances (I'm talking about the *Docker hosts* - I don't like AWS terminology here) and the deployment as two separate things.
  
  Get your ECS stack up and running. You can manage it through CloudFormation and Auto-scaling groups, that's fine. Just think of your cluster as a platform where you will deploy *to*, not something you need to *redeploy*.
  
  Then, for CD, the easiest method by far is to update the service definition to use a new task definition and let ECS rolling update the containers for you.
  
  Every time it start a task, ECS will run docker pull image:tag even if it has the image locally to make sure it has the latest version of that image:tag. So the image tag you use really don't matter (there is no need to change the tag on every build).
  
  That means that you can build myimage:latest over and over in order to deploy it easily.
  
  What you need is a task definition where the image = myimage:latest. Create a service with that task definition and every time that ECS start a task (an instance of your service) it will be the most recent "myimage:latest" you have built.
  
  From there, you are missing only one piece in the puzzle, from CodeDeploy, you can call something, perhaps a lambda function, to create a new revision of your task definition and update your service and ECS will automatically create new tasks for that revision and remove the old tasks.
  
  An example:
  
  Let's assume you have created a service called MyService. That you have configured that service to run 2 tasks for the task definition MyTaskDefinition:1 (revision 1). In that task definition, you have one container definition which image is set to "myimage:latest".
  
  1. Yesterday you have build myimage:latest which had the ID (SHA) 365d8f7bf565.
  2. Your container instance ABC is running a task named MyTaskDefinition-**1**-containerName-someLongId. when you inspect that container, it's running the image "sha256:365d8f7bf565.........."
  3. Your other container instance DEF is running another task. It has a similar name (only the ID differ), but it's running the same image.
  4. You push a change to your repo.
  5. CodePipeline picks up that change, build and publish the image to ECR.
  6. That new Docker image is also myimage:latest, but its ID (SHA) is f7ec5e54ac96
  7. Now you need to add a step to your pipeline to use Lambda functions and the AWS NodeJS SDK to do some calls to your cluster:
     1. Create a new task definition (which will be exactly the same as before). That will be MyTaskDefinition:2
     2. Update your MyService to use MyTaskDefinition:2 (instead of 1)
  8. ECS will create new tasks. The container names will MyTaskDefinition-**2**-containerName-someLongId. When you inspect those containers, you'll see that they will be running "sha256:f7ec5e54ac96.......". Perhaps you'll have 2 tasks on the container instance ABC, perhaps they will be sprayed out (that depends on your service's configuration)
  9. After some time ECS will remove the old task MyTaskDefinition-1-containerName-someLongId from ABC and DEF.
  
  Note: you don't actually need to create a new task definition. If you want you could instead retrieve the service's tasks list and manually stop them one by one. You should wait for ECS to restart a task before stoping a new one (that is: stop the first container, wait for ECS to replace it, stop the second container). When ECS restart the container, it will grab the most recent myimage:latest built, as explained before. I just think creating a new task definition is easier and less error prone (no logic required to wait and check, ECS will handle the rolling update for you if you have a new task definition).
  
  > **Comments:**
  > **username_0**: Amazing - I would call your answer as the missing manual for the CI/CD for docker. Thank you.  
  
  ---
  
  ### Answer by username_1 on 2017-03-26. Score: 3
  
  For simple use case described I would suggest checking Elastic Beanstalk for Docker, it's not the minimal solution like bare ECS usage, but you can benefit from auto-managed and configured services like ELB, EC2 AutoScale, health monitoring and much more.
  
  High-level summary:
  
  1. Configure Elastic Beanstalk to use specific tag myimage:tested
  2. Use Code Pipeline/Build to build, test and promote tag "tested"
  3. Trigger Elastic Beanstalk deployment, which will pull promoted image myimage:tested to all instances, different deployment strategies available.
  
  This approach based on re-using same tag, alternative approach would be generating tag with build id, for example myimage:tested-42, this will require updating Elastic Beanstalk each time with new tag, but gives more granular control on deployed revision.
  
  
  ---
  
  ### Answer by username_2 on 2017-04-03. Score: 0
  
  I second elastic beanstalk for its simplicity; it is very easy to setup and deploy.
  
  If you are familiar with docker-compose, another approach would be to define docker-compose.yml and directly deploy on ECS with ecs-cli.
  
  
  ---
  
  