Featured image of post 从公网访问个人网站(二)——Traefik反向代理配置

从公网访问个人网站(二)——Traefik反向代理配置

使用Traefik配置反向代理以便从公网访问自己的服务器或网站

缘起

之前我一直使用Nginx作为反向代理来访问我的私人服务器上的网站。当时Nginx是直接安装在电脑上的,没有容器化,这导致我之后想把这些服务迁移到其他电脑上时还得重新配置Nginx、重新配置SSL证书等。

所以我决定将反向代理服务也容器化,以方便以后的管理和迁移。我在网上看到了许多在Docker中使用Traefik的例子,因此决定从Nginx迁移到Traefik。

前置条件

Traefik简介

Traefik是一个现代化的反向代理和负载均衡器,它可以自动发现和配置后端服务。Traefik支持Docker、Kubernetes、Consul等多种后端服务,并且可以自动获取SSL证书。Traefik的配置非常灵活,可以通过标签、文件或API等方式进行配置。

安装并配置Traefik

整体架构

Traefik可以使用标签配置,可以使用API配置,也可以使用文件配置。由于我之前在使用Nginx时是用文件配置的,每个服务一个配置文件,我觉得这样非常清晰,也便于管理,因此在使用Traefik时也使用文件来配置。

Traefik容器本身是独立的,跟其他Docker容器一样,使用docker-compose.yml文件来管理。我们在Docker里新建一个网络traefik-net,包括Traefik在内的所有容器都使用这个网络,在这个网络内,我们使用Traefik进行反向代理。

这篇文章中,我们将以部署一个Whoami服务为例来介绍Traefik的使用。Whoami是一个简单的HTTP服务器,它会返回请求的IP地址、请求头等信息,非常适合用来测试反向代理。

项目目录结构

traefik项目

基于上述架构设计,我们在之前存放所有docker项目的目录下新建一个traefik目录,用于存放Traefik项目的相关文件。目录结构如下:

1
2
3
4
5
6
7
8
9
traefik/
  ├── docker-compose.yml
  ├── .env
  ├── traefik.yml
  ├── acme.json
  └── dynamic/
      ├── app1.yml
      ├── app2.yml
      └── app3.yml

其中:

  • docker-compose.yml:Traefik的Docker Compose配置文件。
  • .env:环境变量文件,用于存放Traefik项目使用的环境变量。
  • traefik.yml:Traefik的主配置文件。
  • acme.json:用于存储SSL证书的文件。
  • dynamic:存放动态配置文件的目录,每个服务一个配置文件。

whoami项目

由于我们以一个简单的Whoami服务为例,所以这里我们除了创建一个Traefik项目,还需要创建一个Whoami项目。Whoami项目就很简单,同样放在之前存放所有docker项目的目录下,里面只含有一个docker-compose.yml文件。

1
2
whoami/
  └── docker-compose.yml

Traefik安装配置及测试流程

1. 在Docker中创建traefik-net网络

首先我们在Docker中创建一个名为traefik-net(也可以用其他名字,但之后的配置中要与这个名字一致)的公用网络:

1
docker network create traefik-net

2. 创建上述traefik项目目录

在之前存放所有docker项目的目录下创建一个traefik目录,并在该目录下创建上述的文件和子目录。

docker-compose.yml

docker-compose.yml如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
version: "3.8"

services:
  traefik:
    image: traefik:v3.4.0
    container_name: traefik
    command:
      - "--configFile=/etc/traefik/traefik.yml"
      - "--entryPoints.web.address=:80"
      - "--entryPoints.websecure.address=:443"
      - "--providers.docker=true"
      - "--providers.docker.network=traefik-net"
      - "--providers.docker.exposedByDefault=false"
      - "--providers.file.directory=/etc/traefik/dynamic"
      - "--providers.file.watch=true"
      - "[email protected]"
      - "--certificatesResolvers.le.acme.storage=/letsencrypt/acme.json"
      - "--certificatesResolvers.le.acme.httpChallenge.entryPoint=web"
      - "--api.dashboard=true"
      - "--log.level=INFO"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"    # comment out if you don’t need the dashboard
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml:ro"
      - "./dynamic:/etc/traefik/dynamic:ro"
      - "./acme.json:/letsencrypt/acme.json"
    environment:
      - CF_API_KEY=${CF_API_KEY}
      - CF_API_EMAIL=${CF_API_EMAIL}
    networks:
      - traefik-net
    restart: unless-stopped

networks:
  traefik-net:
    external: true

其中指定了使用的网络是之前创建的traefik-net,并且将Traefik的配置文件traefik.yml、动态配置文件夹dynamic/和存储SSL证书的文件acme.json挂载到容器中。

.env

.env中存储了CloudFlare的API密钥和电子邮件地址,用于自动获取SSL证书。你需要将以下内容替换为你自己的Cloudflare API密钥和电子邮件地址。理论上只提供密钥应该就够了,但我没试。如果你使用的DNS服务商不是Cloudflare(比如你使用阿里云),则需要将相关的API密钥和电子邮件地址替换为你使用的DNS服务商的API密钥和电子邮件地址,具体可参见Traefik的文档

1
2
CF_API_KEY=your_cloudflare_api_key
CF_API_EMAIL=your_cloudflare_email
traefik.yml

traefik.yml是Traefik的主配置文件,内容如下:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
entryPoints:
  web:
    address: ":80"
  websecure:
    address: ":443"

providers:
  file:
    directory: /etc/traefik/dynamic
    watch: true

api:
  dashboard: true
  insecure: false

certificatesResolvers:
  le:
    acme:
      email: [email protected]
      storage: /letsencrypt/acme.json
      dnsChallenge:
        provider: cloudflare
        resolvers:
          - "1.1.1.1:53"
          - "1.0.0.1:53"

#log:
#  level: "DEBUG"

其中我们指定了两个入口点:web(HTTP)和websecure(HTTPS),并且指定了动态配置文件的目录为/etc/traefik/dynamic。我们还启用了Traefik的API仪表盘,并配置了ACME证书解析器为Cloudflare DNS Challenge。如果你使用的是其他DNS服务商,可以将provider: cloudflare替换为你使用的DNS服务商的名称,并根据其文档配置相应的API密钥和电子邮件地址。

acme.json

acme.json是用于存储SSL证书的文件。你需要先创建这个文件(空文件即可),并设置其权限为600,以确保Traefik可以写入证书信息:

1
2
touch acme.json
chmod 600 acme.json
dynamic目录

dynamic目录下,我们可以为每个服务创建一个配置文件。下面是一个非常简单的Whoami服务对应的配置文件,在这篇文章中就以部署一个Whoami服务为例来介绍Traefik的使用。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
http:
  routers:
    whoami-router:
      entryPoints:
        - websecure
      rule: "Host(`whoami.example.com`)"
      tls:
        certResolver: le
      service: whoami-service

  services:
    whoami-service:
      loadBalancer:
        servers:
          - url: "http://whoami:80"

3. 创建上述whoami项目目录

在之前存放所有docker项目的目录下创建一个whoami目录,并在该目录下创建docker-compose.yml文件,内容也很简单:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
version: '3.8'
services:
  whoami:
    image: traefik/whoami:v1.11.0
    container_name: whoami
    restart: always
    networks:
      traefik-net:
        aliases:
          - whoami

networks:
  traefik-net:
    external: true

这个docker-compose.yml文件定义了一个Whoami服务,使用Traefik官方提供的Whoami镜像,并将其连接到之前创建的traefik-net网络。

4. 启动Whoami和Traefik服务

  1. 如果你之前在这台电脑上部署了Nginx服务,需要首先停止Nginx服务,以免与Traefik的端口冲突:

    1
    
    sudo systemctl stop nginx
    

    为了避免电脑重启之后Nginx再次启动,你可以禁用Nginx服务:

    1
    
    sudo systemctl disable nginx
    
  2. 进入whoami目录,使用以下命令启动Whoami服务:

    1
    
    docker-compose up -d
    
  3. 进入traefik目录,使用以下命令启动Traefik服务:

    1
    
    docker-compose up -d
    
  4. 检查Traefik和Whoami服务是否正常运行:

    1
    
    docker ps
    

    你应该能看到Traefik和Whoami服务的容器正在运行。

5. 测试Traefik反向代理

首先确保你在DNS服务商处已经将你的域名(例如whoami.example.com)解析到你的服务器IP地址上。

然后,你可以通过访问https://whoami.example.com来测试Traefik的反向代理功能。你需要将whoami.example.com替换为你自己的域名,并确保DNS解析已经正确配置。

如果一切正常,你就可以访问whoami服务了,你应该能看到一个包含请求信息的页面,类似于下面的内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Hostname: 5ded297e3bf3
IP: 127.0.0.1
IP: ::1
IP: 192.168.144.2
RemoteAddr: 192.168.144.4:33354
GET / HTTP/1.1
Host: whoami.example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Accept-Encoding: gzip, br
Accept-Language: en
Cdn-Loop: cloudflare; loops=1
Cf-Connecting-Ip: 2600:1700:37a0:70e0:b8c8:f187:aaa1:1d07
Cf-Ipcountry: US
Cf-Ray: 948a2cd22a1958ee-ORD
Cf-Visitor: {"scheme":"https"}
Priority: u=0, i
Sec-Ch-Ua: "Chromium";v="136", "Google Chrome";v="136", "Not.A/Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "macOS"
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Upgrade-Insecure-Requests: 1
X-Forwarded-For: 172.69.17.115
X-Forwarded-Host: whoami.example.com
X-Forwarded-Port: 443
X-Forwarded-Proto: https
X-Forwarded-Server: bca3e42c8951
X-Real-Ip: 172.69.17.115

如果你无法访问https:////whoami.example.com,那么意味着上述配置出了问题。你可以讲traefik.yml注释掉的log.level: "DEBUG"取消注释,这样Traefik会输出更详细的日志信息,帮助你排查问题。

如果你在访问时遇到SSL证书错误,可能是因为Traefik还没有获取到SSL证书。你可以等待一段时间,Traefik会自动获取SSL证书并配置HTTPS。

comments powered by Disqus