> For AI agents: the site index is available at https://www.juniortree.com/llms.txt; this page is available as Markdown at https://www.juniortree.com/blog/first-try-traefik.md.
> 初次体验Traefik，通过标签动态配置反向代理，无需端口暴露，自动化TLS，适合容器化环境，高效便捷

## Page metadata

- **Published:** 2025-11-13
- **Updated:** 2025-11-13
- **Tags:** 云原生, web
- **Source URL:** https://www.juniortree.com/blog/first-try-traefik

# Traefik 初体验

## 初印象

>  Traefik 是一个开源的、云原生的 HTTP 反向代理和负载均衡器，专为微服务架构和容器化环境设计。其核心特点是动态配置和自动化服务发现

这话很多人都说烂了，我第一次知道 Traefik 是在 Halo 上的文档[^1]上看到的，使用 Traefik 的反向代理和别的不太一样，它是使用 `lable` 来定义的，我当时觉得很新奇，因为从 compose 里面，并没有使用 `ports` 来定义暴露服务端口：

```yaml
networks:
  traefik:
    external: true
  halo:

services:
  halo:
    image: registry.fit2cloud.com/halo/halo:2.21
    restart: on-failure:3
    volumes:
      - ./halo2:/root/.halo2
    networks:
      - traefik
      - halo
    command:
      # 外部访问地址，请根据实际需要修改
      - --halo.external-url=https://yourdomain.com
    labels:
      traefik.enable: "true"
      traefik.docker.network: traefik
      traefik.http.routers.halo.rule: Host(`yourdomain.com`)
      traefik.http.routers.halo.tls: "true"
      traefik.http.routers.halo.tls.certresolver: myresolver
      traefik.http.services.halo.loadbalancer.server.port: 8090
```

## 体验

不想按照官网的文档来介绍 Traefik，个人感觉写得有点云里雾里，让我们来尝试实际部署一个 Docker 服务，这里我使用的范例服务是：[云函数部署 \| Twikoo 文档](https://twikoo.js.org/backend.html#%E7%A7%81%E6%9C%89%E9%83%A8%E7%BD%B2)

### 创建 Treafik

我们将在一个专用的 `docker-compose.yml` 文件中定义 Traefik 服务，并让它连接到一个专用的 Docker 网络

首先得创建一个 Docker 网络，这是为了 Traefik 能发现外部的 `docker-compose` 服务：

```bash
docker network create web
```

现在，创建 Traefik 的 `docker-compose.yml` (和它的静态配置文件 `traefik.yml`)

```bash
/opt/traefik/
├── docker-compose.yml
├── traefik.yml
└── letsencrypt/
    └── acme.json  (这个文件 Traefik 会自动创建)
```

之后创建  `docker-compose` 文件，请不要急着启动容器：

```yml
services:
  traefik:
    image: traefik:v3.6 # 使用明确的版本号
    container_name: traefik
    restart: always
    ports:
      - "80:80"   # HTTP 端口
      - "443:443" # HTTPS 端口

    volumes:
      # 挂载 Docker Socket，以便 Traefik 可以监听 Docker 事件
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml:ro"
      - "./letsencrypt/acme.json:/letsencrypt/acme.json"

    networks:
      - web

networks:
  web:
    external: true
```

之后再创建 `traefik.yml`：

```yaml
# --- 日志 ---
log:
  level: INFO # (DEBUG, INFO, WARN, ERROR)

# --- 入口点 (EntryPoints) ---
entryPoints:
  web:
    address: ":80"
    # 注意：不在 entryPoint 级别配置全局重定向，以允许 HTTP 挑战
    # HTTP 到 HTTPS 重定向将在路由级别通过中间件配置
  websecure:
    address: ":443"
    # (可选) 在这里全局设置 TLS
    # http:
    #   tls: {}

# --- 证书解析器 (Let's Encrypt) ---
certificatesResolvers:
  mycfresolver:
    acme:
      # Let's Encrypt 生产环境（默认）
      # 测试环境使用: caServer: https://acme-staging-v02.api.letsencrypt.org/directory

      # 存储类型和路径（与 docker-compose.yaml 中的挂载路径一致）
      storage: /letsencrypt/acme.json

      # 使用 HTTP 挑战（需要端口 80 可访问）
      httpChallenge:
        entryPoint: web

      # 邮箱（用于 Let's Encrypt 通知，请替换为您的邮箱）
      email: test@example.com

# --- Docker Provider 配置 ---
providers:
  docker:
    exposedByDefault: false # 最佳实践: 只有带 'traefik.enable=true' 的容器才会被暴露
    network: web          # 关键: 只监听 'web' 网络上的容器
```

这里的 `/letsencrypt/acme.json` 是用来控制证书的，有点坑，需要在容器启动前进行创建，并且需要给对应的权限：

```bash
touch ./letsencrypt/acme.json
chmod 600 ./letsencrypt/acme.json
```

此时可以启动容器了：

```bash
docker compose up -d
```

### 创建 Web 服务

我们也使用 `docker-compose.yml` 来创建 Twikoo 服务

```yaml
services:
  twikoo:
    image: imaegoo/twikoo
    container_name: twikoo
    restart: unless-stopped
    # 移除直接端口映射，通过 Traefik 访问
    environment:
      TWIKOO_THROTTLE: 1000
      TWIKOO_IP_HEADERS: '["headers.cf-connecting-ip"]'
    volumes:
      - ./data:/app/data
    networks:
      - web
    labels:
      # 启用 Traefik
      - "traefik.enable=true"
      # # 路由规则：访问`twikoo.example.com`，也就是这个服务对应外部的域名
      - "traefik.http.routers.twikoo.rule=Host(`twikoo.example.com`)"
      # 使用 HTTPS 入口点
      - "traefik.http.routers.twikoo.entrypoints=websecure"
      # 配置 TLS 证书（使用 Let's Encrypt）
      - "traefik.http.routers.twikoo.tls.certresolver=mycfresolver"
      # 指定后端服务端口
      - "traefik.http.services.twikoo.loadbalancer.server.port=8080"

networks:
  web:
    external: true
```

这里面比较重要的配置在 `labels` 里面，需要自定义，业务逻辑可以用这张图表示：

![](https://s3.juniortree.com/pic/2025/11/bceffbe5a4f2500df6834221f3f4f21e.webp)

里面非常有意思的是，Twikoo 的 8080 端口从未暴露在宿主机，只有 Traefik 的网络可以访问它，不用担心因为 Docker Networks 修改本地机器的 iptables，从而导致 ufw 不能正确阻断端口的问题[^2]

## 总结

俺又心动了，尤其是对于我这种几乎所有服务都跑在容器上的人来说，Traefik 不用让我再次反反复复去折腾各种配置文件，只需要在 `labels` 中对服务进行声明即可，这非常地高效，而且它和 Caddy 一样给出了自动化 TLS 的功能

[^1]: [Halo 文档](https://docs.halo.run/getting-started/install/docker-compose#traefik)

[^2]: [GitHub - chaifeng/ufw-docker: To fix the Docker and UFW security flaw without disabling iptables](https://github.com/chaifeng/ufw-docker)
