Traefik เป็น Application Proxy / Reverse Proxy ที่ออกแบบมาสำหรับระบบ Cloud Native สามารถค้นหา service จาก Docker, Kubernetes และ provider อื่น ๆ แล้วสร้าง routing แบบ dynamic ได้ เหมาะกับ Microservices, Container Platform และระบบที่มี service เพิ่ม/ลดบ่อย

Workshop นี้จะสร้าง Traefik หน้า Web Service หลายตัวด้วย Docker Compose เพื่อศึกษาเส้นทาง

Client
  |
  v
Traefik :80
  |
  +-- Host: app.localhost ----> web
  |
  +-- Host: api.localhost ----> api

#1. สิ่งที่จะได้เรียนรู้

เมื่อจบ Workshop จะสามารถ:

  • อธิบาย EntryPoint, Router, Middleware และ Service ของ Traefik
  • ติดตั้ง Traefik ด้วย Docker Compose
  • ใช้ Docker Provider และ Docker Labels
  • ทำ Host-based Routing
  • ทำ Path-based Routing
  • เปิด Dashboard สำหรับการทดลองในเครื่อง
  • ทดลอง Load Balancing
  • เข้าใจแนวทางต่อยอด HTTPS/TLS

หมายเหตุด้านความปลอดภัย: ตัวอย่าง Dashboard แบบ api.insecure=true เหมาะกับ local lab เท่านั้น ไม่ควรเปิดใช้บน production หรือ public Internet


#2. Architecture

                    +------------------+
                    |      Client      |
                    +--------+---------+
                             |
                         HTTP :80
                             |
                    +--------v---------+
                    |     Traefik      |
                    |  Reverse Proxy   |
                    +---+----------+---+
                        |          |
          app.localhost |          | api.localhost
                        |          |
                 +------v---+  +---v------+
                 |   Web    |  |   API    |
                 |  Nginx   |  |  Nginx   |
                 +----------+  +----------+

องค์ประกอบสำคัญ:

  • EntryPoint — จุดที่ Traefik รับ connection เช่น :80 และ :443
  • Router — ตรวจสอบ rule เช่น Host() หรือ PathPrefix()
  • Middleware — ประมวลผล request ก่อน/หลัง routing เช่น redirect, authentication และ headers
  • Service — backend ที่ Traefik ส่ง request ไป
  • Provider — แหล่ง configuration เช่น Docker หรือ Kubernetes

#3. Prerequisites

ตรวจสอบ Docker:

docker --version
docker compose version

สร้างโครงการ:

mkdir traefik-workshop
cd traefik-workshop

โครงสร้างเริ่มต้น:

traefik-workshop/
├── compose.yaml
├── web/
│   └── index.html
└── api/
    └── index.html

สร้าง directory:

mkdir web api

#4. สร้าง Web Services

ไฟล์ web/index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Web Service</title>
</head>
<body>
    <h1>Web Service</h1>
    <p>Request routed by Traefik</p>
</body>
</html>

ไฟล์ api/index.html

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>API Service</title>
</head>
<body>
    <h1>API Service</h1>
    <p>Hello from API Service</p>
</body>
</html>

#5. สร้าง Docker Compose

สร้าง compose.yaml

services:

  traefik:
    image: traefik:v3
    container_name: traefik
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"

    ports:
      - "80:80"
      - "8080:8080"

    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro

    networks:
      - proxy

  web:
    image: nginx:alpine
    volumes:
      - ./web:/usr/share/nginx/html:ro

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.web.rule=Host(`app.localhost`)"
      - "traefik.http.routers.web.entrypoints=web"

    networks:
      - proxy

  api:
    image: nginx:alpine
    volumes:
      - ./api:/usr/share/nginx/html:ro

    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.rule=Host(`api.localhost`)"
      - "traefik.http.routers.api.entrypoints=web"

    networks:
      - proxy

networks:
  proxy:

จุดสำคัญคือ

--providers.docker=true

ทำให้ Traefik อ่าน configuration จาก Docker Provider ส่วน

--providers.docker.exposedbydefault=false

กำหนดให้ container ไม่ถูก expose ผ่าน Traefik โดยอัตโนมัติ ต้องประกาศ

traefik.enable=true

ก่อน ซึ่งเป็นแนวทางที่ปลอดภัยกว่าการ expose ทุก service


#6. เริ่มระบบ

docker compose up -d

ตรวจสอบ container:

docker compose ps

ดู log:

docker compose logs -f traefik

ทดสอบ:

curl http://app.localhost
curl http://api.localhost

หรือเปิด Browser:

http://app.localhost
http://api.localhost

บนระบบที่ .localhost ไม่ resolve ตามที่คาด สามารถเพิ่มรายการใน hosts file ได้ เช่น:

127.0.0.1 app.localhost
127.0.0.1 api.localhost

#7. Traefik Dashboard

ใน local lab นี้ Dashboard เปิดที่:

http://localhost:8080/dashboard/

Dashboard ช่วยดู:

  • HTTP Routers
  • HTTP Services
  • HTTP Middlewares
  • EntryPoints
  • สถานะ configuration

แต่การใช้

--api.insecure=true

ไม่ควรใช้กับ production


#8. Host-based Routing ทำงานอย่างไร

Router ของ Web:

- "traefik.http.routers.web.rule=Host(`app.localhost`)"

Router ของ API:

- "traefik.http.routers.api.rule=Host(`api.localhost`)"

เมื่อ request เป็น:

GET / HTTP/1.1
Host: app.localhost

Traefik เลือก Web Router แล้วส่งต่อไปยัง web

แต่เมื่อเป็น:

GET / HTTP/1.1
Host: api.localhost

จะถูกส่งไป api

Flow:

Request
   |
   v
EntryPoint :80
   |
   v
Router Rule
   |
   +-- Host(app.localhost) --> web
   |
   +-- Host(api.localhost) --> api

#9. ทดลอง Path-based Routing

อีกแนวทางคือใช้ domain เดียวแล้วแยกตาม path เช่น:

example.localhost/
example.localhost/api

ตัวอย่าง rule:

labels:
  - "traefik.enable=true"
  - "traefik.http.routers.api.rule=Host(`example.localhost`) && PathPrefix(`/api`)"

หาก backend ไม่ต้องการ prefix /api สามารถใช้ Middleware StripPrefix

labels:
  - "traefik.enable=true"

  - "traefik.http.routers.api.rule=Host(`example.localhost`) && PathPrefix(`/api`)"
  - "traefik.http.routers.api.middlewares=api-strip"

  - "traefik.http.middlewares.api-strip.stripprefix.prefixes=/api"

Request:

http://example.localhost/api/users

สามารถถูกแปลงก่อนส่ง backend เป็น:

/users

#10. ทดลอง Load Balancing

เปลี่ยน web ให้ตอบข้อมูล hostname ของ container จะช่วยให้สังเกต replica ได้ง่ายกว่า static HTML จากนั้น scale service:

docker compose up -d --scale web=3

Traefik จะค้นพบ backend instances ผ่าน Docker Provider และสามารถกระจาย request ไปยัง service instances ที่ค้นพบได้

แนวคิด:

                   Traefik
                      |
          +-----------+-----------+
          |           |           |
          v           v           v
        web-1       web-2       web-3

สำหรับการสาธิตให้เห็น replica ที่ตอบจริง ควรใช้ application endpoint ที่คืนค่า hostname/container ID แทน Nginx static page เดียวกันทุก replica


#11. เพิ่ม Middleware สำหรับ Security Headers

ตัวอย่าง:

labels:
  - "traefik.http.middlewares.secure-headers.headers.contenttypenosniff=true"
  - "traefik.http.middlewares.secure-headers.headers.framedeny=true"

ผูก Middleware กับ Router:

- "traefik.http.routers.web.middlewares=secure-headers"

ทดสอบ header:

curl -I http://app.localhost

Middleware ยังสามารถใช้กับงานอื่น เช่น:

Request
   |
   v
Router
   |
   v
Middleware
   |
   +-- Redirect
   +-- Authentication
   +-- Headers
   +-- Rate Limit
   +-- Strip Prefix
   |
   v
Service

#12. แนวทาง HTTPS

Production architecture โดยทั่วไป:

Internet
   |
 HTTPS :443
   |
   v
Traefik
   |
 TLS termination
   |
   v
Application

สร้าง EntryPoint:

command:
  - "--entrypoints.web.address=:80"
  - "--entrypoints.websecure.address=:443"

เปิด port:

ports:
  - "80:80"
  - "443:443"

จากนั้นจึงเพิ่ม TLS certificate resolver เช่น ACME/Let's Encrypt และกำหนด router ให้ใช้ websecure

การออก certificate จริงต้องใช้ domain/DNS และ network configuration ที่เหมาะสม จึงควรแยกเป็น production workshop อีกชุดหนึ่ง


#13. คำสั่งที่ใช้บ่อย

เริ่มระบบ:

docker compose up -d

ดูสถานะ:

docker compose ps

ดู Traefik logs:

docker compose logs -f traefik

ดู configuration ของ container:

docker inspect traefik

หยุดระบบ:

docker compose down

ลบและสร้างใหม่:

docker compose down
docker compose up -d

#14. Troubleshooting

#Port 80 ถูกใช้งานแล้ว

ตรวจสอบ:

sudo lsof -i :80

หรือเปลี่ยน mapping สำหรับ local lab:

ports:
  - "8000:80"

แล้วทดสอบ:

http://app.localhost:8000

#ได้ 404 จาก Traefik

ตรวจสอบ:

docker compose logs traefik

และตรวจสอบ labels:

docker inspect <container-name>

ควรเช็ก:

  • traefik.enable=true
  • Host rule ถูกต้อง
  • container อยู่ network ที่ Traefik เข้าถึงได้
  • backend service ทำงานอยู่

#Dashboard เข้าไม่ได้

ตรวจสอบว่า local lab มี:

--api.insecure=true

และ

ports:
  - "8080:8080"

#15. Production Checklist

ก่อนนำ Traefik ไป production ควรพิจารณา:

  • ใช้ HTTPS/TLS
  • ไม่เปิด insecure dashboard สู่ Internet
  • ป้องกัน Dashboard ด้วย authentication/authorization
  • จำกัดสิทธิ์และความเสี่ยงจาก Docker socket
  • ใช้ exposedByDefault=false
  • เปิด access logs ตามความเหมาะสม
  • เพิ่ม metrics และ monitoring
  • กำหนด security headers
  • วางแผน certificate renewal
  • แยก Docker networks ตาม security boundary
  • กำหนด resource limits และ health checks

#16. แบบฝึกหัด

#Exercise 1 — เพิ่ม Admin Service

สร้าง:

admin.localhost

แล้ว route ไปยัง Nginx container ตัวใหม่

#Exercise 2 — Path Routing

สร้าง routing:

shop.localhost/
shop.localhost/api

โดย /api ส่งไป API Service

#Exercise 3 — Middleware

เพิ่ม Middleware เพื่อจัดการ /api prefix ก่อนส่ง request ไป backend

#Exercise 4 — Load Balancing

เพิ่ม Web replicas เป็น 3 instances และสร้าง endpoint ที่แสดง hostname เพื่อสังเกตการกระจาย request

#Exercise 5 — HTTPS

นำ workshop ไปติดตั้งบน VM ที่มี public domain แล้วเพิ่ม TLS ด้วย ACME/Let's Encrypt


#17. สรุป

Traefik ช่วยลดภาระการเขียน Reverse Proxy configuration แบบ static โดยใช้ข้อมูลจาก infrastructure provider เช่น Docker เพื่อสร้าง routing แบบ dynamic

ภาพรวม request lifecycle:

Client
  |
  v
EntryPoint
  |
  v
Router
  |
  v
Middleware
  |
  v
Service
  |
  v
Container / Pod

ความสามารถเหล่านี้ทำให้ Traefikเหมาะกับ Docker Compose, Microservices และ Kubernetes และเป็นจุดเริ่มต้นที่ดีสำหรับศึกษา Cloud-native traffic management

#เอกสารอ้างอิง