[ traefik代理 ]


目录:

Traefik容器代理工具

代理原理

请求流程
客户端访问域名和端口

用户在浏览器中访问 https://local.chenhaifeng.top:8010/api/。
请求通过 HTTPS 协议到达 local.chenhaifeng.top,解析到本地机器(127.0.0.1)。
Traefik 接收请求

Traefik 监听了 443 端口(websecure entrypoint)。
由于你的 traefik.http.routers.django.rule 定义了 Host(local.chenhaifeng.top),Traefik 匹配到这个路由规则。
Traefik 判断该路由需要通过 django 服务的 loadbalancer.server.port=8010 处理请求。
Traefik 转发到 Django 容器

Traefik 使用内部 Docker 网络将请求代理到 django_test 服务的 8010 端口。
Traefik 不需要暴露 8010 端口,因为它通过 Docker 网络直接与 django_test 通信。
Django 处理请求并返回响应

django_test 容器监听其内部的 8010 端口,处理 /api/ 请求。
响应通过 Docker 网络返回到 Traefik。
Traefik 返回响应给客户端

Traefik 接收来自 Django 的响应,并将其通过 HTTPS 返回给客户端。

使用

就是往想要代理的docker容器启动命令里添加labels, 或者后期update进去也可以, traefik会自动识别到全部容器的labels, 自动处理

需求

像把启动的一个django容器, 正常访问是127.0.0.1:8010,使用traefik代理实现https://local.chenhaifeng.top->就是访问到http://127.0.0.1:8010

准备:

  • 1 我已经在阿里云有个域名local.chenhaifeng.top,
  • 2 解析的ip是自己当前这台电脑的ip:192.168.1.80
  • 3 申请了免费ssl证书并下载了apache版本的 里面有3个文件分别是
    • local.chenhaifeng.top_chain.crt(不用)
    • local.chenhaifeng.top.key(使用)
    • local.chenhaifeng.top_public.crt(使用)

实现

1.docker-compose.yml (保险起见同时部署traefik, 和django)

version: '3.8'

services:
  traefik:
    image: traefik:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml:ro"
      - "./ssl:/certs"

  django_test:
    build: .
    image: django_test
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.django_test.rule=Host(`local.chenhaifeng.top`)"
      - "traefik.http.routers.django_test.entrypoints=websecure"
      - "traefik.http.routers.django_test.tls=true"
      - "traefik.http.services.django_test.loadbalancer.server.port=8010"
    networks:
      - default

networks:
  default:
    driver: bridge

部署django的dockerfile

FROM python:3.11

ENV PYTHONUNBUFFERED 1
WORKDIR /code/djangoblog/

COPY . .
RUN pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple && \
    pip config set install.trusted-host mirrors.aliyun.com && \
    pip install django

CMD ["python", "manage.py", "runserver", "0.0.0.0:8010"]

2.traefik.yml (配置文件)

providers:
  docker:
    #defaultRule: "Host(`{{ trimPrefix `/` .Name }}.docker.localhost`)"
    exposedByDefault: false  # 避免自动暴露所有容器

  #file:
  #  directory: "/etc/traefik/config"

api:
  insecure: true

entrypoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
    http:
      tls:  
        domains:
          - main: "local.chenhaifeng.top"  # 主域名(可选)

tls:
  certificates:
    - certFile: "/certs/local.chenhaifeng.top_public.crt"
      keyFile: "/certs/local.chenhaifeng.top.key"

测试

https://local.chenhaifeng.top

二. 代理代理多个不同的django容器, https域名代理到http

local.chenhaifeng.top -> 127.0.0.1 home.chenhaifeng.top -> 192.168.1.80 (apche证书下载好放到当前目录的ssl文件夹下)

确保外部网络存在:首先确认你定义的外部网络 shared_network 确实已经存在。如果没有,你可以先创建它:

docker network create shared_network

1. 启动t traefik的docker-compose.yml

version: '3.8'

services:
  traefik:
    image: traefik:latest
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080" # 127.0.0.1:8080查看traefik的后台可以
    volumes:
      - "/var/run/docker.sock:/var/run/docker.sock:ro"
      - "./traefik.yml:/etc/traefik/traefik.yml:ro"
      - "./ssl:/certs"  # 生成的ssl证书放到这里
    networks:
      - shared_network

networks:
  shared_network:
    external: true

2. traefik.yml 配置文件

providers:
  docker:
    #defaultRule: "Host(`{{ trimPrefix `/` .Name }}.docker.localhost`)"
    exposedByDefault: false  # 避免自动暴露所有容器

  #file:
  #  directory: "/etc/traefik/config"

api:
  insecure: true

entrypoints:
  web:
    address: ":80"
  websecure:
    address: ":443"
    http:
      tls:  
        domains:
          - main: "local.chenhaifeng.top"  # 主域名(可选)

tls:
  certificates:
    - certFile: "/certs/local.chenhaifeng.top_public.crt"
      keyFile: "/certs/local.chenhaifeng.top.key"
    - certFile: "/certs/home.chenhaifeng.top_public.crt"
      keyFile: "/certs/home.chenhaifeng.top.key"

3. 容器django-1的docker-compose-django.yml(这个使用域名home.chenhaifen.top解析为127.0.0.1)

version: '3.8'

services:
  django_test:
    build: .
    image: django_test
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.django_test.rule=Host(`home.chenhaifeng.top`)"
      - "traefik.http.routers.django_test.entrypoints=websecure"
      - "traefik.http.routers.django_test.tls=true"
      - "traefik.http.services.django_test.loadbalancer.server.port=8010"
    networks:
      - shared_network

networks:
  shared_network:
    external: true

4. 容器django2的django-compose.yml(这个使用域名local.chenhaifeng.top: 解析为192.168.1.80 当前电脑ip)

version: "3"

volumes:
  backend_local_postgres_data: {}
  backend_local_postgres_data_backups: {}

services:
  django: &django
    build:
      context: ./backend
      dockerfile: ./compose/local/django/Dockerfile
    image: backend_local_django
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.cews_django.rule=Host(`local.chenhaifeng.top`)"
      - "traefik.http.routers.cews_django.entrypoints=websecure"
      - "traefik.http.routers.cews_django.tls=true"
      - "traefik.http.services.cews_django.loadbalancer.server.port=8020"
    container_name: cews_django
    depends_on:
      - postgres
      - redis
    volumes:
      - ./backend:/app:z
    env_file:
      - ./backend/.envs/.local/.django
      - ./backend/.envs/.local/.postgres
      - ./backend/.envs/.local/.mongo
    # ports:
      # - "8020:8020"
    command: /start
    networks:
      - shared_network


  postgres:
    build:
      context: ./backend
      dockerfile: ./compose/production/postgres/Dockerfile
    image: backend_production_postgres
    # container_name: backend_local_postgres
    ports:
      - 5432:5432
    volumes:
      - backend_local_postgres_data:/var/lib/postgresql/data
      - backend_local_postgres_data_backups:/backups
    env_file:
      - ./backend/.envs/.local/.postgres

    # docs:
    #   image: backend_local_docs
    container_name: backend_local_docs
    networks:
      - shared_network
  #   build:
  #     context: .
  #     dockerfile: ./compose/local/docs/Dockerfile
  #   env_file:
  #     - ./.envs/.local/.django
  #   volumes:
  #     - ./docs:/docs:z
  #     - ./config:/app/config:z
  #     - ./backend:/app/backend:z
  #   ports:
  #     - "9000:9000"
  #   command: /start-docs

  redis:
    image: redis:6
    ports:
      - 6379:6379
    networks:
      - shared_network
    # container_name: backend_local_redis

  celeryworker:
    <<: *django
    image: backend_local_celeryworker
    container_name: cews_celeryworker
    depends_on:
      - redis
      - postgres
    ports: []
    command: /start-celeryworker
    networks:
      - shared_network

  celerybeat:
    <<: *django
    image: backend_local_celerybeat
    container_name: cews_celerybeat
    depends_on:
      - redis
      - postgres
    ports: []
    command: /start-celerybeat
    networks:
      - shared_network

  flower:
    <<: *django
    image: backend_local_flower
    container_name: cews_flower
    ports:
      - "5555:5555"
    command: /start-flower
    networks:
      - shared_network

  mongo:
    image: mongo
    restart: always
    env_file:
      - ./backend/.envs/.local/.mongo
    ports:
      - 27017:27017
    networks:
      - shared_network

  mongo-express:
    image: mongo-express
    restart: always
    ports:
      - 8081:8081
    env_file:
      - ./backend/.envs/.local/.mongo
    depends_on:
      - mongo

    networks:
      - shared_network

networks:
  shared_network:
    external: true