惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Hacker News: Ask HN
Hacker News: Ask HN
WordPress大学
WordPress大学
H
Help Net Security
小众软件
小众软件
N
Netflix TechBlog - Medium
C
Check Point Blog
量子位
Last Week in AI
Last Week in AI
GbyAI
GbyAI
Martin Fowler
Martin Fowler
M
MIT News - Artificial intelligence
博客园 - 聂微东
Engineering at Meta
Engineering at Meta
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
J
Java Code Geeks
D
DataBreaches.Net
Project Zero
Project Zero
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
Security Latest
Security Latest
Cisco Talos Blog
Cisco Talos Blog
Recorded Future
Recorded Future
I
Intezer
L
Lohrmann on Cybersecurity
Cyberwarzone
Cyberwarzone
博客园_首页
C
Cyber Attacks, Cyber Crime and Cyber Security
L
LangChain Blog
P
Palo Alto Networks Blog
V
V2EX
D
Darknet – Hacking Tools, Hacker News & Cyber Security
T
The Exploit Database - CXSecurity.com
The Hacker News
The Hacker News
Blog — PlanetScale
Blog — PlanetScale
G
GRAHAM CLULEY
T
The Blog of Author Tim Ferriss
C
Cisco Blogs
The Register - Security
The Register - Security
L
LINUX DO - 热门话题
P
Privacy & Cybersecurity Law Blog
Scott Helme
Scott Helme
F
Full Disclosure
博客园 - 司徒正美
Recent Announcements
Recent Announcements
IT之家
IT之家
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
Attack and Defense Labs
Attack and Defense Labs
Cloudbric
Cloudbric
Help Net Security
Help Net Security
The Last Watchdog
The Last Watchdog

DEV Community

Authentication Security Deep Dive: From Brute Force to Salted Hashing (With Java Examples) Why AI Systems Don’t Fail — They Drift Spilling beans for how i learn for exam😁"Reinforcement Learning Cheat Sheet" I Replaced Chrome with Safari for AI Browser Automation. Here's What Broke (and What Finally Worked) How Python Borrows Other People's Work The $40 Architecture: Processing 1 Billion API Requests with 99.99% Uptime Vibe Coding: A Workflow Guide (From Zero to SaaS) Most webhook security guides protect the wrong side. The scary part is delivery. Headless CMS for TanStack Start: Build a Blog with Cosmic EU Age Verification App "Hacked in 2 Minutes" — What Actually Happened Comfy Cloud’s delete function does not actually remove files Running AI Models on GPU Cloud Servers: A Beginner Guide Event-driven media intelligence with AWS Step Functions and Bedrock I scored 500 AI prompts across 8 quality dimensions — here's what broke How to Call Google Gemini API from Next.js (Free Tier, No Backend Needed) The Portal Protocol: Reclaiming Human Connection in the Age of AI How to Fix Your Team's Scattered Knowledge Problem With a Self-Hosted Forum Intro to tc Cloud Functors: A Graph-First Mental Model for the Modern Cloud Designing Multi-Tenant Backends With Both Ownership and Team Access I Built a Neumorphic CSS Library with 77+ Components — Here's What I Learned PostgreSQL Performance Optimization: Why Connection Pooling Is Critical at Scale Cómo construí un SaaS multi-rubro para gestionar expensas en Argentina con FastAPI + Vue 3 🚀 I Built an Ethical Hacking Scanner Tool – Open Source Project I Replaced /usage and /context in Claude Code With a Single Statusline A Pythonic Way to Handle Emails (IMAP/SMTP) with Auto-Discovery and AI-Ready Design I Collected 8.9 Million Polymarket Price Points — Here's What I Found About How Markets Really Move EcoTrack AI — Carbon Footprint Tracker & Dashboard Everyone's Using AI. No One Agrees How. 5 self-hosted ebook managers worth trying in 2026 Building Your First AI Agent with LangChain: From Chatbot to Autonomous Assistant Common SOC 2 Failures (Real World) Stop Vibe-Checking Your AI App: A Practical Guide to Evals How to Use SonarQube and SonarScanner Locally to Level Up Your Code Quality Your Next To-Do App Is Dead — I Replaced Mine with an OpenClaw AI Sign a Nostr event in 60 lines of Python using coincurve — no nostr-sdk, no nbxplorer, no rust toolchain ITGC Audit Explained Like You’re in Big 4 Patch Tuesday abril 2026: Microsoft parcha 163 vulnerabilidades y un zero-day en SharePoint Stop scraping everything: a better way to track competitor price changes Listing on MCPize + the Official MCP Registry while routing payments OUTSIDE the marketplace — how I kept 100% of my x402 revenue Building an AI-Powered Risk Intelligence System Using Serverless Architecture Why We Ripped Function Overloading Out of Our AI Toolchain Testing AI-Generated Code: How to Actually Know If It Works SaaS Churn Is Killing Your Business. Here Is What to Do About It (Without a Support Team) The Speed of AI Is No Longer Linear - And Self-Improving Models Are Why How to Implement RBAC for MCP Tools: A Practical Guide for Engineering Teams From Standard Quote to Persuasive Proposal: AI Automation for Arborists I built a CLI that scaffolds complete multi-tenant SaaS apps Axios CVE-2025–62718: The Silent SSRF Bug That Could Be Hiding in Your Node.js App Right Now The dashboard that ended our friendship Data Pipelines Explained Simply (and How to Build Them with Python) The Hidden Cost of AI Systems Nobody Talks About. undefined vs undeclared, and how typeof behaves Switching from file-based jobs to NATS/Kafka in Rust without changing code io_uring Adventures: Rust Servers That Love Syscalls Why Agentic AI is Killing the Traditional Database The POUR principles of web accessibility for developers and designers Quantum Neural Network 3D — A Deep Dive into Interactive WebGL Visualization How To Install Caveman In Codex On macOS And Windows Automation Pipeline Reliability: Why Your Workflow Breaks When Nobody Is Watching I Built an 'Open World' AI Coding Agent — It Works From ANY Folder From Freelancing to Product: A Tech Service Company's SaaS Transformation China's AI Giants: Adding Tencent Hunyuan & ByteDance Doubao to AI University (74 Providers) On the Vibe Coders and Their Lies clerk: Auto-Summarize Your Claude Code Sessions AI Weekly — 2026/04/10–04/17 | The Model Lockdown Is Here, but the Toolchain Is the Real Battleground AI 週報 — 2026/04/10–2026/04/17 模型封鎖潮來了,但工具鏈才是真戰場 Maybe this is how Open-Source apps are born... 🚀 Fine-Tune LLMs with LoRA and QLoRA: 2026 Guide tRPC v11 + Next.js App Router: End-to-End Type Safety Without the Boilerplate ShadCN UI in 2026: Why I Stopped Installing Component Libraries and Started Owning My Components SaaS Billing in React Server Components: Stripe + Supabase Without a Single `useEffect` Join our DEV Weekend Challenge — $1,000 in Prizes Across TEN winners! Submissions Due April 20 at 6:59 AM UTC. Implementing FSRS Spaced Repetition in Flutter + Supabase — Adding Memory Science to an AI Learning App "I Texted My Localhost From the Train — Claude Code Fixed the Bug Before I Got Home" I Built a Sales Prep AI and It Went Deeper Than Expected Design to Code #2: One JSON, Eleven Outputs Solving the 100M-Row Problem: A Summary Table Pattern for High-Volume Push Notification Logs Flutter Web With Wasm: What Actually Changes For Developers I Built 50 Royalty-Free Soundtracks for My Side Project in a Weekend Using AI Music Generation The Vibe Coding Security Checklist: 7 Things to Check Before You Ship Stop Letting Googlebot Guess Fix Your React App's SEO Right Desconstruindo o Streaming do LinkedIn: Como Criar um Engine de Extração de Vídeo de Alta Performance com HLS e FFmpeg (EDA Part-1) EDA (Exploratory Data Analysis) Explained With Real Life — Why Looking at Your Data Is the Most Important Step in Machine Learning Brand Relationship Management at Scale: Our 4-Touch Outreach System for 200+ Brands Why String.fromEnvironment() Might Return an Empty String in Dart JGuardrails 1.0.0 — Hardening Java LLM Apps Against Jailbreaks, Toxicity, and Prompt Injection Plan and Schedule a Full Week of Threads Content From One Claude Conversation Coding Cat Oran Ep3, Five Tables Changed Everything Updated: BFF Pattern I'm done watching freelancers get buried by 200 proposals. So I'm building the alternative. This is my first post BFS Algorithm in Java Step by Step Tutorial with Examples Tracking LLM Pricing Monthly: An Open Dataset for 22 AI Models How We Measure Content ROI on a Comparison Site: Revenue Attribution Without Perfect Data Introducing Nova AI Ops: The AI-Native Operating System for SRE Teams I built a free desktop video downloader for Windows — Grabbit How Talkie OCR Helps Vision-Impaired & Dyslexic Users Read the World Around Them VRCFaceTracking安装和iPhone面捕配置教程,有bug Even CrowdStrike Can't See Your Agents The Automation Gold Rush: What n8n Workflows and Claude Are Opening Up for Developers Right Now
CI/CD for your Dockerized App with AWS CodeBuild, CodeDeploy and CodePipeline (Part 3/3)
Tanmoy Basak · 2026-05-02 · via DEV Community

This is the final part of a three-part series where we build a production-ready, auto-scaled and continuously deployed Node.js application on AWS.

In Part 1, we dockerized a Node.js app, pushed the image to AWS ECR and deployed it to an EC2 instance. In Part 2, we created an AMI, a launch template, an Application Load Balancer and an Auto Scaling Group so our app scales automatically.

In this part, we wire up a full CI/CD pipeline. Every push to main on GitHub will:

  1. Trigger AWS CodeBuild to build a new Docker image and push it to ECR
  2. Trigger AWS CodeDeploy via AWS CodePipeline to deploy the new image to every running EC2 instance

Make sure your code is hosted in a GitHub repository before continuing.


Prepare the codebase

Before touching AWS, we need to add three files to the repository: a build spec for CodeBuild and a set of deployment scripts for CodeDeploy.

Add buildspec.yml

Create a buildspec.yml file at the root of your repository. CodeBuild reads this file to know how to build and push your Docker image.

# Do not change version. This is the buildspec version, not your file version.
version: 0.2

env:
  variables:
    AWS_REGION: "<aws_region>"         # e.g. "ap-south-1"
    AWS_ACCOUNT_ID: "<aws_account_id>" # find this in your ECR repository URI
    IMAGE_REPO_NAME: "my-app"          # your ECR repository name
    IMAGE_TAG: "latest"
  parameter-store:
    APP_NAME: "/my-app/APP_NAME"       # add any other env variables here

phases:
  pre_build:
    commands:
      - echo Logging in to Amazon ECR...
      - 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:
      - echo Build started on `date`
      - echo Building the Docker image...
      - 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:
      - echo Build completed on `date`
      - echo Pushing the Docker image...
      - docker push $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$IMAGE_REPO_NAME:$IMAGE_TAG

Enter fullscreen mode Exit fullscreen mode

What this does:

  • Defines the AWS account variables and ECR repository details
  • Reads environment variables from Parameter Store (the same ones from Part 1)
  • Logs in to ECR, builds the Docker image and pushes the new image

Add deployment scripts

CodeDeploy needs scripts that run on each EC2 instance during a deployment. Create a folder called aws-scripts in your repository and add the following three files.

aws-scripts/before_install.sh

#!/bin/bash
echo "Before install"

Enter fullscreen mode Exit fullscreen mode

aws-scripts/application_stop.sh

#!/bin/bash
echo "Application stop"

Enter fullscreen mode Exit fullscreen mode

aws-scripts/application_start.sh

This is the important one. It pulls the latest Docker image, refreshes the .env file from Parameter Store, restarts the container and reloads nginx.

#!/bin/bash

cd /home/ubuntu

AWS_ACCOUNT_ID="<aws_account_id>"
AWS_REGION="<aws_region>"
IMAGE_TAG="latest"
APP_NAME="my-app"
PORT="8000"

# Pull latest image from ECR
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

# Refresh .env from Parameter Store
aws ssm get-parameters-by-path \
    --path "/${APP_NAME}" --recursive --with-decrypt \
    | jq -r '.Parameters[] | (.Name | split("/")[-1]) + "=" + (.Value)' \
    | tee /home/ubuntu/.env

# Stop existing containers and clean up
docker stop $(docker ps -q)
docker system prune -f

# Start the updated container
docker run --env-file .env -p $PORT:$PORT -d $AWS_ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/$APP_NAME:$IMAGE_TAG

# Restart nginx
sudo nginx -t
sudo service nginx restart

Enter fullscreen mode Exit fullscreen mode

Add appspec.yml

Create an appspec.yml file at the root of your repository. This tells CodeDeploy which scripts to run at each stage of the deployment.

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

Enter fullscreen mode Exit fullscreen mode

Commit and push all these changes to main before moving on to AWS.


AWS CodeBuild

CodeBuild will run our buildspec.yml every time the pipeline is triggered. It will build the Docker image and push it to ECR.

Create an IAM role for CodeBuild

Search for IAM in the AWS panel and go to Roles. Click Create role.

  • Under Trusted entity type, select AWS service
  • Under Use case, select CodeBuild
  • Add these permission policies: AmazonEC2ContainerRegistryFullAccess, AmazonSSMFullAccess
  • Name the role my-app-code-build-role
  • Click Create role

Create the CodeBuild project

Search for CodeBuild in the AWS panel and click Create project.

Follow these steps:

  • Project name: my-app-code-build, Project type: Default
  • Source: Choose GitHub, connect your GitHub account and select your repository

CodeBuild - project name and source configuration

  • Environment: On-demand, Managed image, EC2, Container
  • Operating system: Ubuntu, Standard runtime
  • Service role: Choose the my-app-code-build-role we just created

CodeBuild - environment and service role configuration

  • Buildspec: Choose Use a buildspec file — this picks up the buildspec.yml from the repository
  • Artifacts: No artifacts — we only need to push to ECR
  • Click Create project

CodeBuild - buildspec and artifacts configuration

You can go to your CodeBuild project and click Start build to verify the build works before setting up the pipeline.


AWS CodeDeploy

CodeDeploy handles getting the latest image from ECR onto each EC2 instance in our Auto Scaling Group.

Prerequisite: The AMI we created in Part 2 already has the CodeDeploy agent installed. If your instances are running, they should have it. You can verify with sudo service codedeploy-agent status on any running instance.

Create an IAM role for CodeDeploy

Go to IAMRoles and click Create role.

  • Under Trusted entity type, select AWS service
  • Under Use case, select CodeDeploy
  • Keep the default AWSCodeDeployRole permission that is pre-selected
  • Name the role my-app-code-deploy-role
  • Click Create role

After creating the role, we need to attach a few more permissions. Click on the role, then Add permissionsAttach policies, and add the following:

  • AmazonEC2ContainerRegistryFullAccess — to pull images from ECR
  • AmazonS3FullAccess — to access pipeline artifacts from S3
  • AutoScalingFullAccess — to interact with the Auto Scaling Group
  • AWSCodePipeline_FullAccess — to work within the pipeline

Create a CodeDeploy application

Search for CodeDeploy in the AWS panel, go to Applications and click Create application.

  • Application name: my-app-code-deployment-application
  • Compute platform: EC2/On-premises

CodeDeploy - create application

Click Create application.

Create a deployment group

Inside the application we just created, click Create deployment group.

  • Deployment group name: my-app-deployment-group
  • Service role: Choose my-app-code-deploy-role

CodeDeploy - deployment group name and service role

  • Environment configuration: Select Amazon EC2 Auto Scaling groups and choose my-app-asg (the Auto Scaling Group from Part 2)
  • Deployment settings: CodeDeployDefault.AllAtOnce

CodeDeploy - environment configuration and deployment settings

  • Load balancer: Uncheck Enable load balancing

CodeDeploy - load balancer unchecked

Click Create deployment group.


AWS CodePipeline

Now we connect everything together. The pipeline will watch for pushes to main, trigger CodeBuild to build and push a new image, then trigger CodeDeploy to roll it out to all instances.

Search for CodePipeline in the AWS panel and click Create pipeline.

Follow these steps:

  • Creation options: Build custom pipeline
  • Pipeline name: my-app-code-pipeline, Execution mode: Queued
  • Service role: Create a new service role — no need to reuse an existing one. Click next.

CodePipeline - pipeline name and service role

  • Source: Choose GitHub (via GitHub App), select your repository and main branch
  • Under Webhook events, select Start your pipeline on push or pull request event. Under Webhook event filters, set Event type to Push, Filter type to Branch and value to main. This ensures only pushes to main fire the pipeline. Click next.

CodePipeline - source stage with GitHub and webhook configuration

  • Build stage: Under Other build providers, choose AWS CodeBuild and select my-app-code-build. No environment variables needed — they come from Parameter Store. Set artifacts to No artifacts. Click next.

CodePipeline - build stage with CodeBuild

  • Test stage: Skip this stage.
  • Deploy stage: Choose AWS CodeDeploy. Select my-app-code-deployment-application as the application and my-app-deployment-group as the deployment group. Click next.

CodePipeline - deploy stage with CodeDeploy

  • Review everything and click Create pipeline.

CodePipeline - review page

CodePipeline - pipeline created and running

Note: If you run into issues with No artifacts in either the build or deploy stage, switch them to SourceArtifact to resolve it.


Test the pipeline

Inside your CodePipeline, click Release change to trigger a manual run and make sure everything is wired up correctly.

Once that succeeds, test the full automated flow:

  1. Push a code change to the main branch on GitHub
  2. Watch CodeBuild pick up the push, build the Docker image and push it to ECR
  3. Watch CodeDeploy roll out the new image to your running EC2 instances
  4. Visit your load balancer DNS (my-app-lb-xxxxxxxx.<aws_region>.elb.amazonaws.com) to see the updated application

Wrapping up

Over this three-part series we went from a simple Node.js app to a fully production-grade deployment on AWS:

  • Part 1: Dockerized the app, pushed it to ECR and deployed it to a single EC2 instance with environment variables managed in Parameter Store
  • Part 2: Created a base AMI, a launch template, an Application Load Balancer and an Auto Scaling Group so the app scales automatically
  • Part 3: Set up a full CI/CD pipeline — every push to main now automatically builds a new Docker image and deploys it to every running instance

You now have an auto-scaled, load-balanced, continuously deployed application running on AWS. 🎉