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(...);
}
}