Build a Production-Ready AWS CI/CD Pipeline for Dockerized Node.js Apps
These articles are AI-generated summaries. Please check the original sources for full details.
CI/CD for your Dockerized App with AWS CodeBuild, CodeDeploy and CodePipeline (Part 3/3)
This guide completes a series on building a production-ready, auto-scaled Node.js application on AWS. Every push to the GitHub main branch triggers a full automated workflow from image build to multi-instance deployment.
Why This Matters
While local Docker builds are straightforward, scaling deployments across an Auto Scaling Group requires orchestrating image updates and environment variable synchronization. This pipeline replaces manual SSH-based updates with a managed AWS CodePipeline that ensures consistency across all running instances without downtime. Achieving this requires precise IAM role configurations and script-driven lifecycle hooks to handle container restarts and Nginx reloads automatically.
Key Insights
- AWS CodeBuild uses a buildspec.yml version 0.2 to automate Docker image creation and ECR pushes upon code changes.
- The CodeDeploy agent must be running on EC2 instances to execute lifecycle hooks defined in appspec.yml.
- Environment variables are centrally managed via AWS Parameter Store and injected during the application_start.sh phase via AWS CLI commands.
- CodePipeline synchronizes GitHub commits with CodeBuild and CodeDeploy to achieve hands-off production releases.
- The application_start.sh script manages container lifecycle by stopping old instances, pruning the system, and pulling the latest ECR image.
Working Examples
CodeBuild buildspec.yml for building and pushing Docker images to ECR.
version: 0.2
env:
variables:
AWS_REGION: "<aws_region>"
AWS_ACCOUNT_ID: "<aws_account_id>"
IMAGE_REPO_NAME: "my-app"
IMAGE_TAG: "latest"
parameter-store:
APP_NAME: "/my-app/APP_NAME"
phases:
pre_build:
commands:
- aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
build:
commands:
- docker build -t $IMAGE_REPO_NAME:$IMAGE_TAG .
- docker tag $IMAGE_REPO_NAME:$IMAGE_TAG $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
post_build:
commands:
- docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG
Deployment script application_start.sh to refresh environment and restart containers.
#!/bin/bash
cd /home/ubuntu
AWS_ACCOUNT_ID="<aws_account_id>"
AWS_REGION="<aws_region>"
IMAGE_TAG="latest"
APP_NAME="my-app"
PORT="8000"
aws ecr get-login-password --region $AWS_REGION | docker login --username AWS --password-stdin $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com
docker pull $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$APP_NAME:$IMAGE_TAG
aws ssm get-parameters-by-path --path "/${APP_NAME}" --recursive --with-decrypt | jq -r '.Parameters[] | (.Name | split("/")[-1]) + "=" + (.Value)' | tee /home/ubuntu/.env
docker stop $(docker ps -q)
docker system prune -f
docker run --env-file .env -p $PORT:$PORT -d $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$APP_NAME:$IMAGE_TAG
sudo service nginx restart
CodeDeploy appspec.yml defining deployment lifecycle hooks.
version: 0.0
os: linux
files:
- source: /
destination: /home/ubuntu/my-app
overwrite: true
hooks:
ApplicationStart:
- location: aws-scripts/application_start.sh
timeout: 3000
runas: ubuntu
file_exists_behavior: OVERWRITE
Practical Applications
- Implementation of high-availability Node.js environments where GitHub pushes automatically update all instances in an Auto Scaling Group.
- Pitfall: Failing to attach AmazonEC2ContainerRegistryFullAccess to the CodeDeploy IAM role, which prevents EC2 instances from pulling new images.
- Pitfall: Ignoring CodeDeploy agent status on the base AMI, causing the pipeline to hang during the deployment phase.
References:
Continue reading
Next article
Secure Cross-Cloud AI Orchestration using Pilot Protocol Zero-Trust Tunnels
Related Content
Provisioning AWS Networking with Terraform: A Hands-on Infrastructure as Code Guide
Learn to build a production-ready AWS VPC using Terraform to automate networking with public and private subnets, supporting up to 65,536 addresses.
Solving the Misleading 'User is not authorized' Error in AWS CodeBuild
Fix the OAuthProviderException in AWS CodeBuild by correcting service role permissions for CodeConnections.
Solved: Automating AWS EC2 Snapshots with Lambda & CloudWatch Events
This guide details automating AWS EC2 snapshot creation using Lambda and CloudWatch Events, reducing manual overhead and ensuring data backup.