nyoely
nyoely

Reputation: 73

Deploying single Codebuild project to multiple ECS containers

I use codebuild & codepipeline successfully for continuous deployment onto ECS for several projects but have came up with a problem. In this project I need to deploy the same build to four different ECS containers.

The default way I use codebuild and codepipeline CD is as shown in aws docs - I create imagedefinitions.json file at the end of the build process. As far as I can see this file can contain the definition of only one ECS container.

You have to provide the name of the container:

post_build:
commands:
  - echo Build completed on `date`
  - echo Pushing the Docker images...
  - docker push $REPOSITORY_URI:latest
  - docker push $REPOSITORY_URI:$IMAGE_TAG
  - echo Writing image definitions file...
  - printf '[{"name":"hello-world","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json

For this task defintion:

{
"taskDefinition": {
"family": "hello-world",
"containerDefinitions": [
  {
    "name": "hello-world",
    "image": "012345678910.dkr.ecr.us-west-2.amazonaws.com/hello-world:6a57b99",
    "cpu": 100,
    "portMappings": [
      {
        "protocol": "tcp",
        "containerPort": 80,
        "hostPort": 80
      }
    ],
    "memory": 128,
    "essential": true
  }
]

It could work if I change the names of all four containers in the different services to the same name. for example that specific image name. But I can't tell if this is a good idea.

Now I wonder if I can use codepipeline to ECS in this project at all or should I deploy in a different way.

Upvotes: 7

Views: 2640

Answers (3)

mtrolle
mtrolle

Reputation: 2284

We are running CodeBuild as an action under CodePipeline.

Here's an example for running two different ECS service tasks on the same ECR image:

phases:
  install: ...
  pre_build: ...
  build: ...
  post_build:
    commands:
    - ...
    - printf '[{"name":"web","imageUri":"%s"}]' $ECR_REPOSITORY_URL:$LATEST_VERSION > web_image_definitions.json
    - printf '[{"name":"worker","imageUri":"%s"}]' $ECR_REPOSITORY_URL:$LATEST_VERSION > worker_image_definitions.json
artifacts:
  files:
    - web_image_definitions.json
    - worker_image_definitions.json

Now in your CodePipeline action for the build action you wanna set Output artifacts to be named e.g. BuildOutput.

Next create two Deploy actions (one for each ECS service) and for the respective deployment actions you wanna ensure to set Input artifacts to BuildOutput and set Image definitions file - optional to respectively web_image_definitions.json and worker_image_definitions.json for each deploy action. AWS console screendump showing input field for image definitions in CodePipeline action editor

Upvotes: 2

Nidhi Shah
Nidhi Shah

Reputation: 2476

You can construct the file to list multiple container-image pairs in the imagedefinitions.json file like below:

[{
  "name": "simple-app",
  "imageUri": "httpd:2.4"
},
{
  "name": "simple-app",
  "imageUri": "mysql"
},
{
  "name": "simple-app-2",
  "imageUri": "java1.8"
}]

Here is an example of how it is done in my buildspec.yml file:

 post_build:
   commands:
     - docker push $IMAGE1_URI:$IMAGE_TAG
     - docker push $IMAGE2_URI:$IMAGE_TAG
     - printf '[{"name":"conatiner1_name","imageUri":"%s"}, {"name":"container2_name","imageUri":"%s"}]' $IMAGE1_URI:$IMAGE_TAG $IMAGE2_URI:$IMAGE_TAG > imagedefinitions.json

More details here: https://docs.aws.amazon.com/codepipeline/latest/userguide/file-reference.html#pipelines-create-image-definitions

Upvotes: 1

mockora
mockora

Reputation: 106

CodeBuild action in codePipeline currently supports only one output artifact. You can zip all the image definition files in to one zip file and add a lambda invoke action to split it in to multiple artifacts and use them in ECS deploy actions.

Upvotes: 1

Related Questions