0

I have a Github repo with source code for an API. I want to deploy this API in AWS ECS. I also want to create an AWS CodePipeline such that, every time I deploy into my Github API repo, the CodePipeline fetches the new commit, builds an ECR image, and deploys my ECS service using the new ECR image. I am using aws-cdk-lib for my infrastructure.

The pipeline is modeled as follows:

GitHubSourceStage --> EcrCodeBuildStage --> EcsDeploymentStage

 export class MyEcsPipelineConstruct extends Construct {

    constructor(scope: Construct, id: string, props: MyApiEcsServiceProps) {
        super(scope, id, props);

        const pipeline = new codepipeline.Pipeline(this, 'PipelineId', {
            pipelineName: 'PipelineName',
            crossAccountKeys: false,
            stages: [
                {
                    stageName: 'GitHubSourceStage',
                    actions: [ new GitHubSourceAction({...}) ],  // Gets Github Source Code
                },
                {
                    stageName: 'EcrCodeBuildStage',
                    actions: [new CodeBuildAction({...})],   // Builds and pushes ECR image
                },
                {
                    stageName: 'EcsDeploymentStage',
                    actions: [ new EcsDeployAction({...}) ],
                },
            ],
        });
    }
}

I managed to meet the above requirements. The problem that I have is a chicken and egg problem.

The ECR repository is empty upon initial creation of my infrastructure, it doesn't have any images. It will only get an image after the pipeline runs EcrCodeBuildStage stage for the first time.

When I initially deploy this stack, the deployment gets stuck. This is because the deployment tries to create the ECS service by pulling an empty ECR repo. This is how the stack looks:

export class MyApiEcsStack extends Stack {
    readonly vpc: Vpc;
    readonly ecsCluster: Cluster;
    readonly ecrRepository: Repository;
    readonly fargateService: ApplicationLoadBalancedFargateService;
    readonly fargateTaskDefinition: FargateTaskDefinition;

    constructor(scope: App, id: string, props: MyApiEcsServiceProps) {
        super(scope, id, props);

        this.vpc = new ec2.Vpc(...);

        this.ecsCluster = new ecs.Cluster(...);

        this.ecrRepository = new ecr.Repository(...);

        this.fargateTaskDefinition = new ecs.FargateTaskDefinition(...);

        this.fargateService = new ApplicationLoadBalancedFargateService(...);

        new MyEcsPipelineConstruct(...);
    }
}

1 Answer 1

1

Here is my plan to cheat the chicken and egg problem.

  1. Create an ECR repository before running the CDK script.
  2. Build the Docker image for the service locally and push it to the repository.
  3. Import the existing repository in the CDK script instead of creating a new one. When deploying the ECS service, the repository would contain the first image.

As a side note, I want to mention that the same problem happens with an AWS CodeCommit repository. Should one create the repository in the CDK script or import an existing repository and only set necessary permissions in the script?

The problem happens once when we start a new project. Though, we have to do this for every project.

I stick to the following plan when I start working on a new project.

  1. Create a GitHub repository for the project and write a readme file with a short explanation, including a building plan.
  2. Write a minimum working version with Docker build files and Docker Composer setup to run the application locally.
  3. Create an ECR repository and push the application images to the repository. Then, other developers can run the application locally without building it. Or even integrate it with their applications by using the image from the ECR repository in their docker-compose setup.
  4. Setup the application environment in the cloud and write and test the CDK deployment scripts.

Sometimes I join the project in the last stage and set up the cloud environment for the application done by other people. For example, they might have some dockerized applications integrated with other applications. My task would be to develop deployment for the application garden.

Please let me know if you see any issues with the plan.

Sign up to request clarification or add additional context in comments.

1 Comment

I love this idea. It is not ideal to first have to do manual work when setting up my infrastructure. But this solution does solve my problem

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.