Showing posts with label AWS. Show all posts
Showing posts with label AWS. Show all posts

Thursday, February 12, 2026

Docker - Exclude Dev Tools (Docker Optimization)

Do not include development-only tools and packages in the final production container image.

You only keep what is needed to run the app — not what is needed to build or test it.

This reduces image size, vulnerabilities, and startup time, which is very important in AWS environments.

“Removing dev dependencies ensures the production Docker image only contains runtime components, resulting in smaller image size, faster AWS deployments, reduced vulnerabilities, and lower CI/CD and ECR costs.”

How to Achieve: Multi stage docker build 
Create docker file in such a way that makes multi stage build (build then run) 





What Are Dev Dependencies?

These are packages/tools used during:

  • Local development
  • Unit testing
  • Debugging
  • Building/compiling
  • Linting/formatting

But not needed at runtime.

Examples:

TechnologyDev Dependencies
.NETSDK, test frameworks, analyzers
Node.jseslint, nodemon, jest
Pythonpytest, black
Javamaven, gradle

Why Remove Them?
1. Smaller Image

Dev tools are heavy.

Example:

  • With SDK + test tools → 1.2 GB
  • Runtime only → 200 MB

Smaller image = faster pull from ECR.


2. Faster Startup on AWS

Impacts:

  • ECS task start
  • EKS pod start
  • Lambda container cold start


3. Better Security

Dev packages increase CVEs.

Removing them:

  • Reduces attack surface
  • Better ECR / Trivy scan results

4. Lower AWS Cost
  • Less ECR storage
  • Less data transfer
  • Faster CI/CD = lower CodeBuild minutes

How to Remove Dev Dependencies

.NET Example
Wrong (Includes SDK)

FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /app
COPY . .
RUN dotnet publish -c Release
ENTRYPOINT ["dotnet", "MyApp.dll"]

SDK stays in final image → huge size.

Correct (Multi-Stage)

# Build Stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src
COPY . .
RUN dotnet publish -c Release -o /out

# Runtime Stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0
WORKDIR /app
COPY --from=build /out .
ENTRYPOINT ["dotnet", "MyApp.dll"]

Now:

  • SDK removed
  • Only runtime DLLs remain


Node.js Example
RUN npm install --production

or

RUN npm ci --omit=dev

AWS Impact Example

Without removing dev deps:

  • Image size: 600 MB
  • ECS startup: 25 sec
  • Vulnerabilities: 120

With removal:

  • Image size: 150 MB
  • ECS startup: 6–8 sec
  • Vulnerabilities: 30


Simple Analogy

It’s like shipping a car:

  • Dev deps = factory tools, welding machines
  • Runtime deps = engine, wheels, fuel

Customer only needs the car, not the factory.

Docker - Layer Caching

Layer Caching in Docker means Docker reuses previously built image layers instead of rebuilding everything from scratch.

In AWS + .NET context, this is very important for CI/CD speed, cost, and developer productivity.

“Docker layer caching improves AWS CI/CD performance by reusing unchanged build steps. In .NET, copying the .csproj and running dotnet restore before copying source code prevents unnecessary dependency restores, reducing build time, ECR push size, and deployment latency.”




First Understand Docker Layers

Every Dockerfile instruction creates a layer:

FROM ...
WORKDIR ...
COPY ...
RUN ...

Docker stores each layer as a snapshot.

If nothing changes in that step → Docker reuses the cached layer.


Why It Matters on AWS

Layer caching helps in:

AWS ServiceBenefit
CodeBuildFaster builds
ECRSmaller push size
ECS/EKSFaster deployments
Lambda ContainersReduced cold start
CI/CD PipelinesMinutes saved per build

Example Without Layer Optimization (.NET)
FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /app
COPY . .
RUN dotnet restore
RUN dotnet publish -c Release -o out

Problem:

  • Any small code change invalidates COPY . .
  • Docker reruns restore + publish
  • Slow builds (2–5 minutes)


Optimized Version Using Layer Caching
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /app

# Copy only project files first
COPY *.csproj .
RUN dotnet restore

# Then copy rest of source
COPY . .
RUN dotnet publish -c Release -o out
Why This Works

  • .csproj changes rarely
  • Source code changes frequently

Docker cache logic:

StepChanges Often?Cache Used?
COPY *.csprojRareYes
RUN dotnet restoreRareYes
COPY . .OftenNo
RUN publishOftenNo

So NuGet restore is skipped most builds, saving time.


AWS CI/CD Impact Example

Without caching:

  • Build time = 6 minutes
  • Every commit full rebuild

With caching:

  • Build time = 1.5–2 minutes
  • Only changed layers rebuilt

In CodeBuild or GitHub Actions, this saves hours per week.


ECR Push Optimization

Docker only pushes changed layers.

If only app code changed:

  • Push size maybe 20–30 MB
  • Instead of 300–500 MB

Less network → faster deploy → lower cost.


Real-World Analogy

Think of it like Excel recalculation:

  • Change one cell → not entire sheet recalculated
  • Docker only rebuilds changed steps


Best Practices for Layer Caching (.NET + AWS)

1. Order Matters

Stable steps first, changing steps later.

2. Separate Restore
COPY *.csproj .
RUN dotnet restore
3. Use .dockerignore

Exclude:

  • bin/
  • obj/
  • .git/
  • logs/

Reduces invalid cache triggers.

4. Multi-Stage Build

Keeps final image small and cache efficient.

AWS - Linux Alpine images

Using Alpine Linux as the operating system layer of your Docker image instead of a full Linux distro like Ubuntu or Debian.

It is not AWS-specific — but it is very popular on AWS because of performance and cost benefits.

“Alpine base images on AWS reduce container size, improve startup time, lower ECR costs, and reduce vulnerabilities, but require compatibility testing due to musl vs glibc differences.”


What is Alpine Linux?

Alpine Linux is a very small, security-focused Linux distribution.

Typical sizes:

Base ImageApprox Size
Ubuntu70–120 MB
Debian60–100 MB
Alpine5–15 MB

So your container becomes much smaller.


Example in Dockerfile (.NET)

Normal:

FROM mcr.microsoft.com/dotnet/aspnet:8.0

Alpine:

FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine


Sample Alpine Docker file


FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine

WORKDIR /app

COPY --from=build /app/out .

ENTRYPOINT ["dotnet", "MyApp.dll"]


Difference:

  • Same .NET runtime
  • Smaller OS layer


Why It Matters on AWS

1. Faster Image Pull (ECR → ECS/EKS/Lambda)

Smaller image = faster download.

Example:

  • Ubuntu image: 400 MB → 15–20 sec pull
  • Alpine image: 90 MB → 3–5 sec pull

This directly impacts:

  • Lambda cold start
  • ECS task startup
  • Auto-scaling speed


2. Lower Storage Cost (ECR)

AWS ECR charges for storage.

Smaller image:

  • Less GB stored
  • Lower monthly cost


3. Better Security

Alpine includes:

  • Fewer packages
  • Smaller attack surface
  • Fewer CVEs

Security scans (ECR / Trivy) usually show less vulnerabilities.


4. Faster CI/CD Pipelines

In CodeBuild / GitHub Actions:

  • Faster build
  • Faster push/pull
  • Less network usage


Where You Use It on AWS
AWS ServiceBenefit
ECS FargateFaster container start
EKS (Kubernetes)Faster pod scheduling
Lambda ContainerReduced cold start
CodeBuildFaster pipelines
ECRLower storage cost

Important Caveat (Very Important)

Alpine uses musl libc instead of glibc.

Some libraries or native dependencies may fail, especially:

  • Image processing libs
  • Oracle drivers
  • Some older .NET native packages
  • Python scientific libs

If your app depends on native binaries, test carefully.


When NOT to Use Alpine

Avoid Alpine if:

  • You need heavy native libraries
  • You see runtime crashes related to libc
  • Vendor software requires glibc
  • You need full debugging tools

In such cases use:

  • -slim images
  • Debian slim
  • Ubuntu minimal



Tuesday, February 10, 2026

AWS - Multi-Stage Docker Build

Multi stage sample docker file

# Build stage

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build

WORKDIR /app

COPY . .

RUN dotnet publish -c Release -o out

# Runtime stage

FROM mcr.microsoft.com/dotnet/aspnet:8.0

WORKDIR /app

COPY --from=build /app/out .

ENTRYPOINT ["dotnet", "MyApp.dll"]


This Dockerfile uses Multi-Stage Build:

  • Stage 1 → Build the app
  • Stage 2 → Run the app

The RUN command executes during image build time, not when the container starts.




Stage 1 – Build Stage

FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
  • Pulls Microsoft .NET SDK image
  • SDK contains compiler, NuGet, build tools
  • Named this stage build


WORKDIR /app

  • Sets working directory inside container to /app
  • All next commands run from here


COPY . .

  • Copies your entire project folder from local machine → container /app
  • Includes .csproj, source code, etc.


RUN dotnet publish -c Release -o out

This is the key line 

RUN executes a command while building the image.

Think of it as:

“Open a temporary container, run this command, save the result as a new image layer.”

What happens internally

  1. Docker creates a temporary container from sdk:8.0
  2. Runs:
    • dotnet publish -c Release -o out
  3. .NET does:

    • Restore NuGet packages
    • Compile code
    • Optimize for Release
    • Output DLLs + dependencies into /app/out
  4. Docker commits the result as a new image layer
  5. Temporary container is deleted

So RUN is build-time execution, not runtime.

Result now inside image:

/app/out/MyApp.dll
/app/out/*.json
/app/out/*.deps.json


Stage 2 – Runtime Stage

FROM mcr.microsoft.com/dotnet/aspnet:8.0
  • Starts a fresh lightweight image
  • No SDK, only runtime
  • Much smaller


WORKDIR /app

Sets working directory again.


COPY --from=build /app/out .
  • Copies only compiled output from build stage
  • Not source code
  • Not SDK
  • Only /app/out/app

This is why image becomes small.


ENTRYPOINT ["dotnet", "MyApp.dll"]

This runs when container starts, not during build.

Difference:

InstructionWhen it runs
RUNDuring docker build
ENTRYPOINTDuring docker run

Lifecycle Summary
When you run:

docker build -t myapp .

Docker executes:

  1. Pull SDK image
  2. Copy code
  3. RUN dotnet publish → compile app
  4. Start new runtime image
  5. Copy compiled files
  6. Create final image


When you run:

docker run myapp

Only this runs:

dotnet MyApp.dll

No compiling happens here.


Simple Analogy

  • RUN = “Bake the cake in the kitchen”
  • ENTRYPOINT = “Serve the cake to the customer”

RUN prepares the app.
ENTRYPOINT executes the app.


Why This Is Efficient

Without multi-stage:

  • Image ~1–2 GB
  • Includes compiler

With multi-stage:

  • Image ~150–250 MB
  • Only runtime files
  • Faster deploys
  • More secure

So RUN = build-time command that produces artifacts saved into the image layer.

Friday, January 30, 2026

AWS - Private link, VPC Interface Endpoint, VPC Gateway Endpoint, Direct Connect & VPC Peering

Private link, VPC Interface Endpoint, VPC Gateway Endpoint, Direct Connect & VPC Peering





1️⃣ VPC Endpoint (Big Picture)

A VPC Endpoint lets your VPC privately access AWS services without using the Internet, NAT Gateway, or IGW.

There are two types:

  • 🧩 Interface Endpoint
  • 🚪 Gateway Endpoint

👉 AWS PrivateLink is the technology behind Interface Endpoints.


2️⃣ Interface Endpoint (Powered by AWS PrivateLink)

🔹 What it is

  • Creates Elastic Network Interfaces (ENIs) in your subnet
  • You access services using private IPs
  • Uses AWS PrivateLink

🔹 Supported services

  • Most AWS services: SSM, EC2 API, CloudWatch, ECR, Secrets Manager
  • Your own services (via NLB)
  • SaaS / third-party services

🔹 Key points

  • Works across VPCs and accounts
  • Uses Security Groups
  • Charged per hour + per GB

🎨 Diagram

🟦 VPC A (Consumer) ┌──────────────────────────┐ │ EC2 🖥️ │ │ │ HTTPS (443) │ │ ▼ │ │ 🧩 Interface Endpoint │ ← ENI + Private IP │ │ │ └────┼─────────────────────┘ │ AWS PrivateLink 🔒 ▼ ┌──────────────────────────┐ │ 🟩 AWS Service / NLB │ │ (SSM / ECR / SaaS) │ └──────────────────────────┘

🧠 When to use

✅ Private access to AWS services
✅ Expose your service to other VPCs safely
✅ No CIDR overlap issues


3️⃣ Gateway Endpoint

🔹 What it is

  • Adds routes in your route table
  • No ENIs, no Security Groups
  • Only supports:

    • 🪣 S3
    • 📦 DynamoDB
🔹 Key points

  • Free
  • Scales automatically
  • Traffic stays inside AWS network

🎨 Diagram

🟦 VPC ┌────────────────────────────┐ │ EC2 🖥️ │ │ │ │ │ ▼ Route Table │ │ 🚪 Gateway Endpoint │ │ │ │ └───┼────────────────────────┘ ▼ 🪣 Amazon S3 📦 DynamoDB

🧠 When to use

✅ Access S3/DynamoDB privately
✅ Cheapest & simplest option


4️⃣ AWS PrivateLink (Concept)

🔹 What it really is

PrivateLink = Secure service exposure using Interface Endpoints

Think of it as:

“I want to expose my service privately without opening my VPC.”

🎨 Diagram

🟦 VPC A (Client) 🟪 VPC B (Provider) ┌─────────────┐ ┌────────────────┐ │ EC2 │ │ NLB │ │ │ │ │ + Service 🧩 │ │ ▼ │ └──────▲─────────┘ │ Interface │ │ │ Endpoint 🧩 │──PrivateLink───┘ └─────────────┘

🧠 When to use

✅ SaaS-like architecture
✅ Cross-account secure access
✅ No VPC peering / no CIDR worries


5️⃣ VPC Peering

🔹 What it is

  • 1-to-1 private connection between two VPCs
  • Uses private IPs
  • No transitive routing

🔹 Key points

  • Simple, but doesn’t scale well
  • CIDR must not overlap
  • No Security Group referencing across VPCs

🎨 Diagram

🟦 VPC A 🟨 VPC B ┌──────────┐ ┌──────────┐ │ EC2 🖥️ │────────────│ EC2 🖥️ │ └──────────┘ Peering 🔗 └──────────┘

🧠 When to use

✅ Small number of VPCs
✅ Full network-level access


6️⃣ AWS Direct Connect

🔹 What it is

  • Dedicated physical connection
  • From on-premises → AWS
  • Bypasses public internet

🔹 Key points

  • Very low latency
  • High bandwidth (1–100 Gbps)
  • Costly but stable

🎨 Diagram

🏢 On-Prem Data Center ┌───────────────────┐ │ Servers 🖥️ │ └─────────┬─────────┘ │ Dedicated Fiber 🔵 ▼ ┌────────────────────────┐ │ AWS Direct Connect ⚡ │ └─────────┬──────────────┘ ▼ 🟦 AWS VPC (Private Subnets)

🧠 When to use

✅ Hybrid cloud
✅ Predictable latency & bandwidth
✅ Enterprise workloads


7️⃣ One-Look Comparison Table
FeatureInterface EndpointGateway EndpointPrivateLinkVPC PeeringDirect Connect
Internet needed
ENI used
Route table change
Security Groups
Cross-account⚠️
CIDR overlap OK
Typical useAWS servicesS3/DDBSaaS / APIsVPC-to-VPCOn-prem

8️⃣ Simple Memory Trick 🧠
  • 🧩 Interface Endpoint“ENI + Private IP”
  • 🚪 Gateway Endpoint“Route table only”
  • 🔒 PrivateLink“Secure service publishing”
  • 🔗 VPC Peering“Flat VPC connection”
  • Direct Connect“Private fiber to AWS”

Tuesday, October 28, 2025

Architecture - .NET Project Architecture Design Framework

🧭 Step 1: Understand the Business and Technical Requirements

🧩 Step 2: Choose the Right .NET Application Type

🧱 Step 3: Select an Architecture Style

🧠 Step 4: Define Solution Structure (Clean Architecture Example)

⚙️ Step 5: Choose Technologies

🧰 Step 6: CI/CD with AWS DevOps

🔒 Step 7: Security & Compliance

🧪 Step 8: Testing, Quality & Observability

📘 Step 9: Documentation & Governance

🔁 Step 10: Iterate and Improve


🧭 Step 1: Understand the Business and Technical Requirements

Before starting, gather and document:

  • Functional and non-functional requirements.
  • User personas, traffic expectations, and performance needs.
  • Compliance, security, and availability goals.
  • Integration needs with internal systems or third-party APIs.

🎯 Output: A clear understanding of system goals and constraints.


🧩 Step 2: Choose the Right .NET Application Type

Application TypeFramework / Tech StackUse Case
Web API / MicroserviceASP.NET Core Web APIBackend REST APIs, integrations
Web App (UI)ASP.NET Core MVC / Razor Pages / BlazorFull-stack web apps
Background ProcessingWorker Service / AWS LambdaJobs, scheduling, event processing
Desktop AppWPF / WinUI / MAUIDesktop or cross-platform apps
Cloud-Native AppASP.NET Core + Containers (Docker, ECS, EKS)Scalable distributed systems

🎯 Output: Application type and high-level stack selection.


🧱 Step 3: Select an Architecture Style

ArchitectureDescriptionUse When
Layered (N-tier)Simple separation into UI, business, and data layers.Small to medium monoliths.
Clean / Hexagonal / OnionDomain-focused, testable, decoupled.Modern enterprise solutions.
MicroservicesIndependent, API-based services.Large, distributed applications.
Modular MonolithMonolith organized into modules.Mid-sized apps; future-ready.
Event-drivenUses AWS SQS/SNS/EventBridge for async comms.Real-time or decoupled systems.

💡 Recommendation: Start with Clean Architecture for modularity and maintainability.


🧠 Step 4: Define Solution Structure (Clean Architecture Example)

src/
├── Presentation (API/UI)
│ └── Controllers, Views
├── Application
│ └── Business logic, CQRS, DTOs, Validation
├── Domain
│ └── Entities, Value Objects, Domain Events, Interfaces
├── Infrastructure
│ └── EF Core, AWS SDK integrations, Logging, External Services
└── Tests
└── Unit, Integration, and API tests

Dependency flow: Presentation → Application → Domain → Infrastructure (implementing domain interfaces)


⚙️ Step 5: Choose Technologies


Backend 
Framework: .NET 8 (LTS)

API: ASP.NET Core Web API / Minimal API

ORM: Entity Framework Core / Dapper

Authentication: JWT, Cognito, or OAuth2

Validation: FluentValidation

Mapping: AutoMapper

Frontend (optional):
React, Angular, Blazor, or Razor Pages

Communicate via REST/gRPC

Database
Amazon RDS (SQL Server, PostgreSQL)

DynamoDB (NoSQL)

EF Core Migrations for schema evolution

Caching
Amazon ElastiCache (Redis)

Messaging / Events
AWS SQS, SNS, EventBridge, or Kinesis Streams

File Storage
Amazon S3

Logging & Monitoring
ILogger (built-in), Serilog, Amazon CloudWatch, X-Ray





🧰 Step 6: CI/CD with AWS DevOps

  • Version control: Git (GitHub / CodeCommit)
  • CI/CD: AWS CodePipeline, CodeBuild, GitHub Actions or Harness
  • Stages:
    • Build and test
    • Static analysis (SonarQube / Checkmarx)
    • Deploy to dev/test/prod
  • Infrastructure as Code (IaC): AWS CloudFormation / Terraform
  • Container orchestration: ECS or EKS (Kubernetes)


🔒 Step 7: Security & Compliance

  • Use AWS Identity and Access Management (IAM) for roles and permissions.

  • Secure secrets via AWS Secrets Manager or Parameter Store.

  • Enable HTTPS using AWS Certificate Manager.

  • Apply OWASP Top 10 principles and encryption at rest (KMS).


🧪 Step 8: Testing, Quality & Observability

  • Testing: Unit, Integration, API, and Performance tests.

  • Static Code Analysis: SonarQube / Checkmarx.

  • Observability: CloudWatch, X-Ray, Serilog.

  • Metrics: Track latency, throughput, and error rates.


📘 Step 9: Documentation & Governance

  • Document APIs using Swagger/OpenAPI.

  • Maintain Architecture Decision Records (ADRs).

  • Use consistent Git branching and code review practices.

  • Reassess architecture periodically for improvements.


🔁 Step 10: Iterate and Improve

  • Start with MVP, evolve as usage grows.

  • Review scaling patterns regularly.

  • Encourage feedback and innovation from the team.


🧱 Clean Architecture Overview

+---------------------------+
| Presentation |
| (Controllers / API Layer) |
+------------+--------------+
+---------------------------+
| Application |
| (Use Cases, CQRS, DTOs) |
+------------+--------------+
+---------------------------+
| Domain |
| (Entities, Interfaces) |
+------------+--------------+
+---------------------------+
| Infrastructure |
| (EF Core, AWS SDK, etc.) |
+---------------------------+

✅ Summary Principles

PrincipleDescription
SOLIDMaintainable and scalable design
KISS & DRYSimplicity and no duplication
Dependency InversionDepend on abstractions
Separation of ConcernsIsolated business logic
TestabilityUnit and integration ready
Scalability & ResilienceAWS-native scaling and fault tolerance

Outcome: A scalable, testable, and secure .NET 8 application leveraging AWS-native services for CI/CD, observability, and automation.

CI/CD - Safe DB Changes/Migrations

Safe DB Migrations means updating your database schema without breaking the running application and without downtime . In real systems (A...