Skip to content

Instantly share code, notes, and snippets.

@apoorvmote
Last active February 24, 2021 06:45
Show Gist options
  • Save apoorvmote/f69b1308c845aa09068d36dbf935a8ee to your computer and use it in GitHub Desktop.
Save apoorvmote/f69b1308c845aa09068d36dbf935a8ee to your computer and use it in GitHub Desktop.
version: 0.2
phases:
pre_build:
commands:
- echo Logging in to Amazon ECR...
- aws --version
- $(aws ecr get-login --region $AWS_DEFAULT_REGION --no-include-email)
- docker login -u $docker_username -p $docker_password
- REPOSITORY_URI=1234567890.dkr.ecr.us-east-1.amazonaws.com/next-starter
- COMMIT_HASH=prod-$(echo $CODEBUILD_RESOLVED_SOURCE_VERSION | cut -c 1-7)
- IMAGE_TAG=${COMMIT_HASH:=latest}
build:
commands:
- echo Build started on `date`
- echo Building the Docker image...
- docker build -t $REPOSITORY_URI:latest .
- docker tag $REPOSITORY_URI:latest $REPOSITORY_URI:$IMAGE_TAG
post_build:
commands:
- echo Build completed on `date`
- echo Pushing the Docker images...
- docker push $REPOSITORY_URI:$IMAGE_TAG
- echo Writing image definitions file...
- printf '[{"name":"web","imageUri":"%s"}]' $REPOSITORY_URI:$IMAGE_TAG > imagedefinitions.json
artifacts:
files: imagedefinitions.json
const containerBuildProject = new PipelineProject(this, 'containerBuild', {
buildSpec: BuildSpec.fromSourceFilename('buildspec.yml'),
environment: {
buildImage: LinuxBuildImage.STANDARD_5_0,
computeType: ComputeType.SMALL,
privileged: true
},
environmentVariables: {
'docker_username': {
value: dockerUsername
},
'docker_password': {
value: dockerPassword
}
}
})
ecrRepo.grantPullPush(containerBuildProject.grantPrincipal)
FROM node:14.15.1-alpine3.12
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json /usr/src/app
COPY package-lock.json /usr/src/app
RUN npm install --production
COPY . /usr/src/app
RUN npm run build
EXPOSE 80
CMD [ "npm", "start" ]
const ecrRepo = new Repository(this, 'nextJSRepo', {
repositoryName: 'next-starter',
removalPolicy: RemovalPolicy.DESTROY,
imageScanOnPush: true,
lifecycleRules: [
{
tagPrefixList: ['prod'],
maxImageCount: 5
},
{
maxImageAge: Duration.days(30)
}
]
})
new CfnOutput(this, 'repoUrl', {
value: ecrRepo.repositoryUri
})
const vpc = new Vpc(this, 'fargateVpc', {
maxAzs: 2
})
const cluster = new Cluster(this, 'fargateCluster', {
clusterName: 'fargateCluster',
containerInsights: true,
vpc
})
const domainZone = HostedZone.fromHostedZoneAttributes(this, 'hostedZoneWithAttributes', {
zoneName: website_domain,
hostedZoneId
})
const fargateService = new ApplicationLoadBalancedFargateService(this, 'fargateService', {
cluster,
assignPublicIp: true,
cpu: 256,
desiredCount: 1,
memoryLimitMiB: 512,
redirectHTTP: true,
protocol: ApplicationProtocol.HTTPS,
domainName: website_domain,
domainZone,
taskImageOptions: {
// image from docker hub
// image: ContainerImage.fromRegistry('apoorvmote/next:prod-v1'),
// image from public ecr registry
// image: ContainerImage.fromRegistry('public.ecr.aws/abc123xyz/next:prod-v1'),
// image from private ecr registry
image: ContainerImage.fromEcrRepository(ecrRepo, 'prod-v1'),
}
})
const scalableTarget = fargateService.service.autoScaleTaskCount({
minCapacity: 1,
maxCapacity: 20
})
scalableTarget.scaleOnCpuUtilization('cpuScaling', {
targetUtilizationPercent: 70
})
const vpc = new Vpc(this, 'fargateVpc', {
maxAzs: 2
})
const securityGroup = new SecurityGroup(this, 'fargateSecurity', {
vpc,
securityGroupName: 'fargateSecurity'
})
securityGroup.addIngressRule(Peer.anyIpv4(), Port.tcp(80))
const cluster = new Cluster(this, 'nextJSCluster', {
clusterName: 'exampleCluster',
containerInsights: true,
vpc
})
const taskDefinition = new FargateTaskDefinition(this, 'nextJSTaskDefinition', {
memoryLimitMiB: 512,
cpu: 256
})
const container = taskDefinition.addContainer('nextJSContainer', {
image: ContainerImage.fromRegistry('public.ecr.aws/abc123xyz/next:prod-v1'),
})
container.addPortMappings({
containerPort: 80,
hostPort: 80
})
new FargateService(this, 'nextJSService', {
taskDefinition,
cluster,
desiredCount: 1,
serviceName: 'exampleService',
assignPublicIp: true,
securityGroups:[securityGroup]
})
const gitOutput = new Artifact('nextJSLatestMaster')
const buildOutput = new Artifact('ContainerBuildOutput')
new Pipeline(this, 'containerPipeline', {
artifactBucket,
pipelineName: 'examplePipeline',
stages: [
{
stageName: 'SourceCode',
actions: [
new CodeCommitSourceAction({
actionName: 'readCode',
output: gitOutput,
repository: nextRepo,
branch: 'main'
})
]
},
{
stageName: 'build',
actions: [
new CodeBuildAction({
actionName: 'buildContainer',
input: gitOutput,
outputs: [buildOutput],
project: containerBuildProject
})
]
},
{
stageName: 'deploy',
actions: [
new EcsDeployAction({
actionName: 'deployContainer',
service: fargateService.service,
input: buildOutput,
deploymentTimeout: Duration.minutes(30)
})
]
}
]
})
# https://taskfile.dev
version: '3'
vars:
PRIVATE_VERSION: prod-v1
tasks:
private:
deps: [privateLogin, privateBuild]
cmds:
- docker push 1234567890.dkr.ecr.us-east-1.amazonaws.com/next-starter:{{$.PRIVATE_VERSION}}
- docker image rm next-starter:latest
privateLogin:
cmds:
- aws ecr get-login-password --region us-east-1 | docker login --username AWS --password-stdin 1234567890.dkr.ecr.us-east-1.amazonaws.com
privateBuild:
cmds:
- docker build -t next-starter .
- docker tag next-starter:latest 1234567890.dkr.ecr.us-east-1.amazonaws.com/next-starter:{{$.PRIVATE_VERSION}}
# https://taskfile.dev
version: '3'
vars:
PUBLIC_VERSION: prod-v1
tasks:
public:
deps: [publicLogin, publicBuild]
cmds:
- docker push public.ecr.aws/<your username>/next:{{$.PUBLIC_VERSION}}
- docker image rm next:latest
publicLogin:
cmds:
- aws ecr-public get-login-password --region us-east-1 | docker login --username AWS --password-stdin public.ecr.aws/<your username>
publicBuild:
cmds:
- docker build -t next .
- docker tag next:latest public.ecr.aws/<your username>/next:{{$.PUBLIC_VERSION}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment