12 KiB
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+ |
|
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
- Multi-stage builds - Separate build and runtime
- Non-root user - Security best practice
- Alpine images - Smaller image size
- .dockerignore - Exclude unnecessary files
- 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
- Detailed Examples - Full configurations
- Project Rules - Docker naming conventions
- Observability - Container monitoring
- Error Handling - Health checks