This commit is contained in:
Ho Ngoc Hai
2026-05-23 18:37:02 +07:00
parent f15d91ee29
commit 76d75c753b
3993 changed files with 403 additions and 0 deletions

View File

@@ -0,0 +1,401 @@
---
name: docker-traefik
description: Docker containerization và Traefik reverse proxy. Use for Dockerfile, docker-compose, routing rules, SSL termination, và load balancing.
compatibility: "Docker 24+, Docker Compose v2+, Traefik v3+"
metadata:
author: Velik Ho
version: "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
```dockerfile
# ===================================
# 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
```yaml
# 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
```yaml
# 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
```yaml
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
```dockerfile
# ❌ 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
```yaml
# ❌ 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
```yaml
# ❌ 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
```bash
# 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
```yaml
# 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](./references/REFERENCE.md) - Full configurations
- [Project Rules](../project-rules/SKILL.md) - Docker naming conventions
- [Observability](../observability/SKILL.md) - Container monitoring
- [Error Handling](../error-handling-patterns/SKILL.md) - Health checks