Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Container & Cloud

Docker

Dockerfile cho .NET

# Build Stage
FROM mcr.microsoft.com/dotnet/sdk:8.0 AS build
WORKDIR /src

# Copy project files
COPY ["src/MyApp/MyApp.csproj", "MyApp/"]
RUN dotnet restore "MyApp/MyApp.csproj"

# Copy source and build
COPY src/MyApp/. MyApp/
WORKDIR "/src/MyApp"
RUN dotnet publish -c Release -o /app/publish

# Runtime Stage
FROM mcr.microsoft.com/dotnet/aspnet:8.0 AS runtime
WORKDIR /app
COPY --from=build /app/publish .

# Non-root user
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
RUN chown -R appuser:appgroup /app
USER appuser

EXPOSE 8080
ENV ASPNETCORE_URLS=http+:8080

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

Docker Commands

# Build image
docker build -t myapp:latest .

# Run container
docker run -d -p 8080:8080 --name myapp myapp:latest

# Run với environment variables
docker run -d -p 8080:8080 \
  -e "ASPNETCORE_ENVIRONMENT=Production" \
  -e "ConnectionStrings__DefaultConnection=..." \
  myapp:latest

# Docker Compose
docker-compose.yml
version: '3.8'
services:
  app:
    build: .
    ports:
      - "8080:8080"
    depends_on:
      - db
      - redis
  db:
    image: mcr.microsoft.com/mssql/server
    environment:
      - ACCEPT_EULA=Y
      - SA_PASSWORD=YourStrong!Passw0rd
  redis:
    image: redis:alpine

Kubernetes

Pod

apiVersion: v1
kind: Pod
metadata:
  name: myapp-pod
  labels:
    app: myapp
spec:
  containers:
  - name: myapp
    image: myapp:latest
    ports:
    - containerPort: 8080
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

Deployment

apiVersion: apps/v1
kind: Deployment
metadata:
  name: myapp-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myapp
  template:
    metadata:
      labels:
        app: myapp
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        ports:
        - containerPort: 8080
        env:
        - name: ASPNETCORE_ENVIRONMENT
          value: "Production"
        livenessProbe:
          httpGet:
            path: /health
            port: 8080
          initialDelaySeconds: 30
          periodSeconds: 10
        readinessProbe:
          httpGet:
            path: /health/ready
            port: 8080
          initialDelaySeconds: 5
          periodSeconds: 5

Service

apiVersion: v1
kind: Service
metadata:
  name: myapp-service
spec:
  selector:
    app: myapp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 8080
  type: LoadBalancer

Cloud Deployment

Azure

# Azure Container Apps
az containerapp create \
  --name myapp \
  --resource-group mygroup \
  --image myregistry.azurecr.io/myapp:latest \
  --cpu 0.25 --memory 0.5Gi \
  --ingress external \
  --target-port 8080

# Azure Kubernetes Service
az aks create \
  --resource-group mygroup \
  --name mycluster \
  --node-count 3 \
  --enable-addons monitoring

AWS

# Amazon ECS
aws ecs create-cluster --cluster-name mycluster

# Amazon EKS
aws eks create-cluster \
  --name mycluster \
  --role-arn arn:aws:iam::123456789:role/EKSRole \
  --resources-vpc-config subnetIds=subnet-12345

Best Practices

12-Factor App

FactorDescription
CodebaseOne codebase tracked in version control
DependenciesExplicitly declare dependencies
ConfigStore config in environment
Backing ServicesTreat backing services as attached resources
Build/Release/RunStrictly separate build and run stages
ProcessesExecute app as one or more stateless processes
Port BindingExport HTTP as a service by port binding
ConcurrencyScale out via process model
DisposabilityFast startup and graceful shutdown
Dev/Prod ParityKeep development, staging, production similar
LogsTreat logs as event streams
Admin ProcessesRun admin/maintenance tasks as one-off processes