Files
pos-system/microservices/.agent/skills/docker-traefik/SKILL.md
Ho Ngoc Hai 76d75c753b Migrate
2026-05-23 18:37:02 +07:00

12 KiB

name, description, compatibility, metadata
name description compatibility metadata
docker-traefik Docker containerization và Traefik reverse proxy. Use for Dockerfile, docker-compose, routing rules, SSL termination, và load balancing. Docker 24+, Docker Compose v2+, Traefik v3+
author version
Velik Ho 1.0

Docker & Traefik Patterns / Mẫu Docker & Traefik

Docker containerization và Traefik reverse proxy cho GoodGo microservices.

When to Use This Skill / Khi Nào Sử Dụng

Use this skill when:

  • Creating Dockerfiles for .NET services / Tạo Dockerfiles cho services .NET
  • Configuring docker-compose for local dev / Cấu hình docker-compose cho dev local
  • Setting up Traefik routing / Cài đặt Traefik routing
  • Configuring SSL/TLS termination / Cấu hình SSL/TLS termination
  • Implementing load balancing / Triển khai load balancing
  • Managing service discovery / Quản lý service discovery

Core Concepts / Khái Niệm Cốt Lõi

Architecture Overview / Tổng Quan Kiến Trúc

Internet
    │
    ▼
┌─────────────────────────────────────────────────────┐
│                   Traefik (Gateway)                  │
│   - SSL Termination   - Rate Limiting               │
│   - Load Balancing    - Path Routing                │
└───────┬────────────────────────────────┬────────────┘
        │                                │
        ▼                                ▼
┌───────────────┐              ┌───────────────┐
│ iam-service   │              │ storage-svc   │
│ :8080         │              │ :8080         │
└───────────────┘              └───────────────┘

Traefik Concepts / Các Khái Niệm Traefik

Concept Description Example
EntryPoints Network ports web:80, websecure:443
Routers Match requests to services PathPrefix(\/api/v1/iam`)`
Services Backend targets loadbalancer.server.port=8080
Middlewares Request/Response modifiers stripprefix, ratelimit

Docker Best Practices / Best Practices Docker

  1. Multi-stage builds - Separate build and runtime
  2. Non-root user - Security best practice
  3. Alpine images - Smaller image size
  4. .dockerignore - Exclude unnecessary files
  5. Layer caching - Optimize build time

Key Patterns / Mẫu Chính

Dockerfile for .NET Service

# ===================================
# EN: Build stage / VI: Stage build
# ===================================
FROM mcr.microsoft.com/dotnet/sdk:8.0-alpine AS build
WORKDIR /src

# EN: Copy solution and restore dependencies
# VI: Copy solution và restore dependencies
COPY *.slnx ./
COPY src/MyService.API/*.csproj src/MyService.API/
COPY src/MyService.Domain/*.csproj src/MyService.Domain/
COPY src/MyService.Infrastructure/*.csproj src/MyService.Infrastructure/
RUN dotnet restore

# EN: Copy source code and build
# VI: Copy source code và build
COPY src/ src/
RUN dotnet publish src/MyService.API -c Release -o /app --no-restore

# ===================================
# EN: Runtime stage / VI: Stage runtime
# ===================================
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine AS runtime
WORKDIR /app

# EN: Install additional packages if needed
# VI: Cài đặt packages bổ sung nếu cần
RUN apk add --no-cache icu-libs

# EN: Create non-root user for security
# VI: Tạo user không phải root để bảo mật
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser

# EN: Copy published files
# VI: Copy files đã publish
COPY --from=build --chown=appuser:appgroup /app .

# EN: Configure environment
# VI: Cấu hình môi trường
ENV ASPNETCORE_URLS=http://+:8080
ENV ASPNETCORE_ENVIRONMENT=Production
ENV DOTNET_RUNNING_IN_CONTAINER=true

EXPOSE 8080

HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
    CMD wget --no-verbose --tries=1 --spider http://localhost:8080/health/live || exit 1

ENTRYPOINT ["dotnet", "MyService.API.dll"]

Docker Compose với Traefik

# docker-compose.yml
version: "3.8"

services:
  # ===================================
  # Traefik - API Gateway
  # ===================================
  traefik:
    image: traefik:v3.0
    container_name: traefik
    command:
      # EN: Enable API and Dashboard
      # VI: Bật API và Dashboard
      - "--api.dashboard=true"
      - "--api.insecure=true"
      
      # EN: Docker provider configuration
      # VI: Cấu hình Docker provider
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--providers.docker.network=goodgo-network"
      
      # EN: Entrypoints
      # VI: Các điểm vào
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      
      # EN: Access logs
      # VI: Logs truy cập
      - "--accesslog=true"
      - "--accesslog.format=json"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # Dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - goodgo-network
    labels:
      # EN: Enable Traefik dashboard
      # VI: Bật Traefik dashboard
      - "traefik.enable=true"
      - "traefik.http.routers.dashboard.rule=Host(`traefik.localhost`)"
      - "traefik.http.routers.dashboard.service=api@internal"

  # ===================================
  # IAM Service
  # ===================================
  iam-service-net:
    build:
      context: ../..
      dockerfile: services/iam-service-net/Dockerfile
    container_name: iam-service-net
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ConnectionStrings__DefaultConnection=${IAM_DATABASE_URL}
    labels:
      - "traefik.enable=true"
      # EN: Router configuration / VI: Cấu hình router
      - "traefik.http.routers.iam-service-net.rule=PathPrefix(`/api/v1/iam`)"
      - "traefik.http.routers.iam-service-net.entrypoints=web"
      # EN: Service configuration / VI: Cấu hình service
      - "traefik.http.services.iam-service-net.loadbalancer.server.port=8080"
      # EN: Health check / VI: Kiểm tra sức khỏe
      - "traefik.http.services.iam-service-net.loadbalancer.healthcheck.path=/health/live"
      - "traefik.http.services.iam-service-net.loadbalancer.healthcheck.interval=10s"
    networks:
      - goodgo-network
    depends_on:
      - postgres

  # ===================================
  # Storage Service
  # ===================================
  storage-service-net:
    build:
      context: ../..
      dockerfile: services/storage-service-net/Dockerfile
    container_name: storage-service-net
    environment:
      - ASPNETCORE_ENVIRONMENT=Development
      - ConnectionStrings__DefaultConnection=${STORAGE_DATABASE_URL}
      - MinIO__Endpoint=${MINIO_ENDPOINT}
      - MinIO__AccessKey=${MINIO_ACCESS_KEY}
      - MinIO__SecretKey=${MINIO_SECRET_KEY}
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.storage-service-net.rule=PathPrefix(`/api/v1/storage`)"
      - "traefik.http.routers.storage-service-net.entrypoints=web"
      - "traefik.http.services.storage-service-net.loadbalancer.server.port=8080"
    networks:
      - goodgo-network
    depends_on:
      - postgres
      - minio

  # ===================================
  # PostgreSQL
  # ===================================
  postgres:
    image: postgres:15-alpine
    container_name: postgres
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=postgres
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - goodgo-network

  # ===================================
  # MinIO (S3-compatible storage)
  # ===================================
  minio:
    image: minio/minio:latest
    container_name: minio
    command: server /data --console-address ":9001"
    environment:
      - MINIO_ROOT_USER=minioadmin
      - MINIO_ROOT_PASSWORD=minioadmin
    volumes:
      - minio_data:/data
    ports:
      - "9000:9000"
      - "9001:9001"
    networks:
      - goodgo-network

networks:
  goodgo-network:
    driver: bridge

volumes:
  postgres_data:
  minio_data:

Traefik Middlewares

# EN: Strip path prefix middleware
# VI: Middleware bỏ prefix path
services:
  iam-service-net:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.iam-service-net.rule=PathPrefix(`/api/v1/iam`)"
      - "traefik.http.routers.iam-service-net.entrypoints=web"
      # EN: Apply middleware to strip prefix
      # VI: Áp dụng middleware để bỏ prefix
      - "traefik.http.routers.iam-service-net.middlewares=iam-stripprefix"
      - "traefik.http.middlewares.iam-stripprefix.stripprefix.prefixes=/api/v1/iam"
      - "traefik.http.services.iam-service-net.loadbalancer.server.port=8080"

Rate Limiting Middleware

services:
  api-service:
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=PathPrefix(`/api`)"
      # EN: Rate limiting middleware
      # VI: Middleware giới hạn rate
      - "traefik.http.routers.api.middlewares=api-ratelimit"
      - "traefik.http.middlewares.api-ratelimit.ratelimit.average=100"
      - "traefik.http.middlewares.api-ratelimit.ratelimit.burst=50"
      - "traefik.http.middlewares.api-ratelimit.ratelimit.period=1m"

Common Mistakes / Lỗi Thường Gặp

1. Running as Root

# ❌ BAD: Running as root
FROM mcr.microsoft.com/dotnet/aspnet:8.0
COPY --from=build /app .
ENTRYPOINT ["dotnet", "MyService.dll"]

# ✅ GOOD: Non-root user
FROM mcr.microsoft.com/dotnet/aspnet:8.0-alpine
RUN adduser -D appuser
USER appuser
COPY --from=build --chown=appuser /app .
ENTRYPOINT ["dotnet", "MyService.dll"]

2. No Health Checks

# ❌ BAD: No health check
services:
  my-service:
    build: .
    labels:
      - "traefik.enable=true"

# ✅ GOOD: With health check
services:
  my-service:
    build: .
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.my-service.loadbalancer.healthcheck.path=/health/live"
      - "traefik.http.services.my-service.loadbalancer.healthcheck.interval=10s"

3. Exposing Internal Ports

# ❌ BAD: Exposing all ports
services:
  my-service:
    ports:
      - "8080:8080"  # Direct access bypasses Traefik

# ✅ GOOD: Only expose through Traefik
services:
  my-service:
    # No ports exposed directly
    labels:
      - "traefik.enable=true"
      - "traefik.http.services.my-service.loadbalancer.server.port=8080"

Quick Reference / Tham Chiếu Nhanh

Docker Commands

# EN: Build and start / VI: Build và start
docker-compose -f deployments/local/docker-compose.yml up -d --build

# EN: View logs / VI: Xem logs
docker-compose logs -f iam-service-net

# EN: Restart service / VI: Restart service
docker-compose restart iam-service-net

# EN: Stop all / VI: Dừng tất cả
docker-compose down

# EN: Clean rebuild / VI: Rebuild sạch
docker-compose down -v && docker-compose up -d --build

Traefik Router Rules

Rule Example Description
Host Host(`api.example.com`) Match by hostname
PathPrefix PathPrefix(`/api`) Match by path prefix
Path Path(`/api/health`) Match exact path
Method Method(`GET`, `POST`) Match by HTTP method
Headers Headers(`X-Custom`, `value`) Match by header

Common Labels

# EN: Basic routing / VI: Routing cơ bản
- "traefik.enable=true"
- "traefik.http.routers.{name}.rule=PathPrefix(`/path`)"
- "traefik.http.routers.{name}.entrypoints=web"
- "traefik.http.services.{name}.loadbalancer.server.port=8080"

# EN: With HTTPS / VI: Với HTTPS
- "traefik.http.routers.{name}-secure.rule=PathPrefix(`/path`)"
- "traefik.http.routers.{name}-secure.entrypoints=websecure"
- "traefik.http.routers.{name}-secure.tls=true"

Resources / Tài Nguyên