Home > OS >  Deploy ecs service with two containers using github actions
Deploy ecs service with two containers using github actions

Time:01-23

I have a dotnet webapi and nginx defined across two containers which are both used by one task definition to provide one service. It all works fine in both ECS and Docker Desktop.

My problem is how to deploy it using github actions. I have plenty of other single container dotnet services which are working fine and which I deploy using github actions. The relevant part of the action yml file for those is as follows...

   - name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ env.ECS_TASK_NAME }} 
      run: |
        # Build a docker container and
        # push it to ECR so that it can
        # be deployed to ECS.
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
        echo "image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

    - name: Fill in the new image ID in the Amazon ECS task definition
      id: task-def
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.CONTAINER_NAME }}
        image: ${{ steps.build-image.outputs.image }}

It all works great - builds, populates the task definition and deploys. I have read in the github doco that I can simply repeat the amazon-ecs-render-task-definition section to add a second container, something like this...

   - name: Fill in the new dotnet image ID in the Amazon ECS task definition
      id: task-def-dotnet
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.CONTAINER_NAME }}
        image: ${{ steps.build-image.outputs.image }} #              <-- what goes here?

    - name: Fill in the new nginx image ID in the Amazon ECS task definition
      id: task-def-nginx
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.CONTAINER_NAME }}
        image: ${{ steps.build-image.outputs.image }} #              <-- what goes here?

What I cannot work out is how to run the docker compose command in the build-image step so that I can create and capture the two output image files and then feed them in at the right spots where the ${{ steps.build-image.outputs.image }} parameters are.

I'm pretty sure I can replace the...

docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .

...with something like...

docker compose -p ${{ env.ECS_TASK_NAME }} create

...but can't find how to identify the multiple outputs or specify them later.

Any help would be very much appreciated.

CodePudding user response:

You did not shared any information about your nginx container/image.

You need to build nginx same as dot-net image. Then You need to render task-definition with nginx image and on latest step deploy latest generated task-definition to your cluster.

   - name: Build, tag, and push image to Amazon ECR
      id: build-images
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ env.ECS_TASK_NAME }} 
      run: |
        docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG .
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG
        echo "dotnet_image=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT
        
        docker build -f Dockerfile.nginx -t $ECR_REGISTRY/$ECR_NGINX_REPOSITORY:$IMAGE_TAG .
        docker push $ECR_REGISTRY/$ECR_NGINX_REPOSITORY:$IMAGE_TAG
        echo "nginx_image=$ECR_REGISTRY/$ECR_NGINX_REPOSITORY:$IMAGE_TAG" >> $GITHUB_OUTPUT

   - name: Fill in the new dotnet image ID in the Amazon ECS task definition
      id: task-def-dotnet
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.DOTNET_CONTAINER_NAME }}
        image: ${{ steps.build-images.outputs.dotnet_image }}

    - name: Fill in the new nginx image ID in the Amazon ECS task definition
      id: task-def-nginx
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ steps.task-def-dotnet.outputs.task-definition }}
        container-name: ${{ env.NGINX_CONTAINER_NAME }}
        image: ${{ steps.build-images.outputs.nginx_image }}

    - name: Deploy to Amazon ECS service
      uses: aws-actions/amazon-ecs-deploy-task-definition@v1
      with:
        task-definition: ${{ steps.task-def-nginx.outputs.task-definition }}
        service: ${{ env.ECS_SERVICE }}
        cluster: ${{ env.ECS_CLUSTER }}

CodePudding user response:

So I eventually found that I could use the same docker compose command that I used with Docker Desktop in the script and capture both images generated by it.

I then discovered how to link the multiple calls of the amazon-ecs-render-task-definition together and access their outputs for the next step, as below....

   - name: Build, tag, and push image to Amazon ECR
      id: build-image
      env:
        ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }}
        IMAGE_TAG: ${{ env.ECS_TASK_NAME }} 
        IMAGE_DOTNET: ${{ env.IMAGE_NAME_DOTNET }} 
        IMAGE_NGINX: ${{ env.IMAGE_NAME_NGINX }} 
      run: |
        docker compose -p $IMAGE_TAG create
        docker tag $IMAGE_DOTNET:latest $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_DOTNET
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_DOTNET
        echo "imagedotnet=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_DOTNET" >> $GITHUB_OUTPUT
        docker tag $IMAGE_NGINX:latest $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_NGINX
        docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_NGINX
        echo "imagenginx=$ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_NGINX" >> $GITHUB_OUTPUT

    - name: Fill in the new dotnet image ID in the Amazon ECS task definition
      id: task-def-dotnet
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ env.ECS_TASK_DEFINITION }}
        container-name: ${{ env.CONTAINER_NAME_DOTNET }}
        image: ${{ steps.build-image.outputs.imagedotnet }}

    - name: Fill in the new nginx image ID in the Amazon ECS task definition
      id: task-def-nginx
      uses: aws-actions/amazon-ecs-render-task-definition@v1
      with:
        task-definition: ${{ steps.task-def-dotnet.outputs.task-definition }}
        container-name: ${{ env.CONTAINER_NAME_NGINX }}
        image: ${{ steps.build-image.outputs.imagenginx }}
  • Related