簡體   English   中英

如何正確設置基本 traefik 反向代理?

[英]How can I properly setup basic traefik reverse proxy?

Assume my current public IP is 101.15.14.71 , I have a domain called example.com which I configured using cloudflare and I created multiple DNS entry pointing to my public ip.

例如:

1) new1.example.com - 101.15.14.71
2) new2.example.com - 101.15.14.71
3) new3.example.com - 101.15.14.71

現在,這是我的示例項目結構,

├── myapp
│   ├── app
│   │   └── main.py
│   ├── docker-compose.yml
│   └── Dockerfile
├── myapp1
│   ├── app
│   │   └── main.py
│   ├── docker-compose.yml
│   └── Dockerfile
└── traefik
    ├── acme.json
    ├── docker-compose.yml
    ├── traefik_dynamic.toml
    └── traefik.toml

這里我有兩個 fastAPI(即 myapp、myapp1)

這是我在 myapp 和 myapp1 的main.py中的示例代碼,它完全相同,但返回狀態不同,僅此而已

from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_main():
    return {"message": "Hello world for my project myapp"}

這是 myapp 和 myapp1 的Dockerfile ,這里也完全相同,但唯一的區別是我將 myapp 部署在7777上,將 myapp1 部署在7778上的不同容器中

FROM ubuntu:latest

ARG DEBIAN_FRONTEND=noninteractive
RUN apt update && apt upgrade -y
RUN apt install -y -q build-essential python3-pip python3-dev

# python dependencies
RUN pip3 install -U pip setuptools wheel
RUN pip3 install gunicorn fastapi uvloop httptools "uvicorn[standard]"

# copy required files
RUN bash -c 'mkdir -p /app'
COPY ./app /app


ENTRYPOINT /usr/local/bin/gunicorn \
    -b 0.0.0.0:7777 \ # this line I use for myapp dockerfile
    -b 0.0.0.0:7778 \ # this line I change for myapp1 dockerfile
    -w 1 \
    -k uvicorn.workers.UvicornWorker app.main:app \
    --chdir /app

這是 myapp 和 myapp1 的docker-compose.yml文件,這里我也有完全相同但唯一的區別是我更改了端口,

 services: myapp: # I use this line for myapp docker-compose file myapp1: # I use this line for myapp1 docker-compose file build: . restart: always labels: - "traefik.enable=true" - "traefik.docker.network=traefik_public" - "traefik.backend=myapp" # I use this line for myapp docker-compose file - "traefik.backend=myapp1" # I use this line for myapp1 docker-compose file - "traefik.frontend.rule=Host:new2.example.com" # I use this for myapp compose file - "traefik.frontend.rule=Host:new3.example.com" # I use this for myapp1 compose file - "traefik.port=7777" # I use this line for myapp docker-compose file - "traefik.port=7778" # I use this line for myapp1 docker-compose file networks: - traefik_public networks: traefik_public: external: true

現在來到 traefik 文件夾,

  1. acme.json # 我使用nano acme.json命令創建了它,其中沒有任何內容,但是chmod 600 acme.json獲得了適當的權限。

  2. traefik_dynamic.toml

 [http] [http.routers] [http.routers.route0] entryPoints = ["web"] middlewares = ["my-basic-auth"] service = "api@internal" rule = "Host(`new1.example.com`)" [http.routers.route0.tls] certResolver = "myresolver" [http.middlewares.test-auth.basicAuth] users = [ ["admin:your_encrypted_password"] ]
  1. traefik.toml
 [entryPoints] [entryPoints.web] address = ":80" [entryPoints.web.http] [entryPoints.web.http.redirections] [entryPoints.web.http.redirections.entryPoint] to = "websecure" scheme = "https" [entryPoints.websecure] address = ":443" [api] dashboard = true [certificatesResolvers.myresolver.acme] email = "reallygoodtraefik@gmail.com" storage= "acme.json" [certificatesResolvers.myresolver.acme.httpChallenge] entryPoint = "web" [providers] [providers.docker] watch = true network = "web" [providers.file] filename = "traefik_dynamic.toml"
  1. docker-compose.yml
 services: traefik: image: traefik:latest ports: - 80:80 - 443:443 - 8080:8080 volumes: - /var/run/docker.sock:/var/run/docker.sock -./traefik.toml:/traefik.toml -./acme.json:/acme.json -./traefik_dynamic.toml:/traefik_dynamic.toml networks: - web networks: web:

這些是關於我的文件的詳細信息,我在這里想要實現的是,

我想使用基本身份驗證設置 traefik 和 traefik 儀表板,我部署了兩個我的 fastapi 服務,

  • myapp 7777 ,我需要通過new2.example.com訪問這個應用程序
  • myapp1 7778 ,我需要通過new3.example.com訪問這個應用程序
  • traefik 儀表板,我需要通過new1.example.com訪問它

所有這些都應該是 https 並且還啟用了認證自動更新。

我從最新版本的 traefik 的在線文章中獲得了所有這些信息。 但問題是這不起作用。 我使用 docker-compose 構建和部署 traefik,然后打開 api 儀表板。 它要求輸入密碼和用戶( basic auth I setup )我輸入了我在traefik_dynamic.toml中設置的用戶詳細信息,但它不起作用。

我哪里做錯了? 請幫助我糾正配置中的錯誤。 我真的很想了解更多關於這方面的信息。

錯誤更新:

traefik_1  | time="2021-06-16T01:51:16Z" level=error msg="Unable to obtain ACME certificate for domains \"new1.example.com\": unable to generate a certificate for the domains [new1.example.com]: error: one or more domains had a problem:\n[new1.example.com] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: Invalid response from http://new1.example.com/.well-known/acme-challenge/mu85LkYEjlvnbDI-wM2xMaRFO1QsPDNjepTDb47dWF0 [2606:4700:3032::6815:55c4]: 404\n" rule="Host(`new1.example.com`)" routerName=api@docker providerName=myresolver.acme

traefik_1  | time="2021-06-16T01:51:19Z" level=error msg="Unable to obtain ACME certificate for domains \"new2.example.com\": unable to generate a certificate for the domains [new2.example.com]: error: one or more domains had a problem:\n[new2.example.com] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: Invalid response from http://new2.example.com/.well-known/acme-challenge/ykiCAEpJeQ1qgVdeFtSRo3q-ATTwgKdRdGHUs2kgIsY [2606:4700:3031::ac43:d1e9]: 404\n" providerName=myresolver.acme routerName=myapp1@docker rule="Host(`new2.example.com`)"

traefik_1  | time="2021-06-16T01:51:20Z" level=error msg="Unable to obtain ACME certificate for domains \"new3.example.com\": unable to generate a certificate for the domains [new3.example.com]: error: one or more domains had a problem:\n[new3.example.com] acme: error: 403 :: urn:ietf:params:acme:error:unauthorized :: Invalid response from http://new3.example.com/.well-known/acme-challenge/BUZWuWdNd2XAXwXCwkeqe5-PHb8cGV8V6UtzeLaKryE [2606:4700:3031::ac43:d1e9]: 404\n" providerName=myresolver.acme routerName=myapp@docker rule="Host(`new3.example.com`)"

所有服務只需要一個 docker-compose 文件,無需為每個容器定義一個。

您應該使用的項目結構應該類似於:

├── docker-compose.yml
├── myapp
│   ├── .dockerignore
│   ├── Dockerfile
│   └── app
│       └── main.py
├── myapp1
│   ├── .dockerignore
│   ├── Dockerfile
│   └── app
│       └── main.py
└── traefik
    ├── acme.json
    └── traefik.yml

創建容器時,除非它們用於開發目的,否則建議不要使用完整的鏡像,例如 ubuntu。 專門針對您的目的,我建議您使用 python 映像,例如python:3.7-slim

不確定您是否將其用於開發或生產目的,但您也可以使用卷將應用程序目錄掛載到容器內(如果您將其用於開發,則特別有用),並且只對myappmyapp1使用一個 Dockerfile ,通過環境變量自定義它。

由於您已經在使用 traefik 的動態配置,我將通過docker-compose.yml文件中的 docker 標簽來完成容器配置的大部分設置。

此時,您的myappmyapp1的 dockerfile 將非常相似,但我將它們分開保存,因為您可能需要根據未來應用程序的要求對它們進行更改。 我為端口使用了一個環境變量,它可以讓您從docker-compose.yml文件中更改端口。

您可以使用以下Dockerfile./myapp/Dockerfile./myapp1/Dockerfile ):

FROM python:3.7-slim

ARG DEBIAN_FRONTEND=noninteractive

ENV PYTHONUNBUFFERED=1

RUN pip3 install -U pip setuptools wheel && \
    pip3 install gunicorn fastapi uvloop httptools "uvicorn[standard]"

COPY . /app

ENV PORT=7777 # and 7778 for myapp1

ENTRYPOINT /usr/local/bin/gunicorn -b 0.0.0.0:$PORT -w 1 -k uvicorn.workers.UvicornWorker app.main:app --chdir /app

注意:你真的應該為你的應用依賴使用詩歌requirements.txt文件。

.dockerignore文件( ./myapp/.dockerignore./myapp1/.dockerignore )應包含:

Dockerfile

由於整個目錄都被復制到容器中,並且您不需要Dockerfile在那里。

您的主要 traefik 配置( ./traefik/traefik.yml )可能類似於:

providers:
  docker:
    exposedByDefault: false

global:
  checkNewVersion: false
  sendAnonymousUsage: false

api: {}
accessLog: {}

entryPoints:
  web:
    address: ":80"
    http:
      redirections:
        entryPoint:
          to: "websecure"
          scheme: "https"
  websecure:
    address: ":443"

ping:
  entryPoint: "websecure"

certificatesResolvers:
  myresolver:
    acme:
      caServer: "https://acme-staging-v02.api.letsencrypt.org/directory"
      email: "example@example.com"
      storage: "/etc/traefik/acme.json"
      httpChallenge:
        entryPoint: "web"

注意:上面的 acme 配置將使用階段 letencrypt 服務器。 確保所有細節都正確,並在測試一切正常后刪除caServer ,以便與letsencrypt生產服務器通信。

您的./docker-compose.yml文件應該類似於:

version: "3.9"

services:
  myapp:
    build:
      context: ./myapp
      dockerfile: ./Dockerfile
    image: myapp
    depends_on:
      - traefik
    expose:
      - 7777
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp.tls=true"
      - "traefik.http.routers.myapp.tls.certResolver=myresolver"
      - "traefik.http.routers.myapp.entrypoints=websecure"
      - "traefik.http.routers.myapp.rule=Host(`new2.example.com`)"
      - "traefik.http.services.myapp.loadbalancer.server.port=7777"
  myapp1:
    build:
      context: ./myapp1
      dockerfile: ./Dockerfile
    image: myapp1
    depends_on:
      - traefik
    expose:
      - 7778
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.myapp1.tls=true"
      - "traefik.http.routers.myapp1.tls.certResolver=myresolver"
      - "traefik.http.routers.myapp1.entrypoints=websecure"
      - "traefik.http.routers.myapp1.rule=Host(`new3.example.com`)"
      - "traefik.http.services.myapp1.loadbalancer.server.port=7778"
  traefik:
    image: traefik:v2.4
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - ./traefik/traefik.yml:/etc/traefik/traefik.yml
      - ./traefik/acme.json:/etc/traefik/acme.json
    ports:
      - 80:80
      - 443:443
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.api.tls=true"
      - "traefik.http.routers.api.tls.certResolver=myresolver"
      - "traefik.http.routers.api.entrypoints=websecure"
      - "traefik.http.routers.api.rule=Host(`new1.example.com`)"
      - "traefik.http.routers.api.service=api@internal"
      - "traefik.http.routers.api.middlewares=myAuth"
      - "traefik.http.middlewares.myAuth.basicAuth.users=admin:$$apr1$$4zjvsq3w$$fLCqJddLvrIZA.CCoGE2E." # generate with htpasswd. replace $ with $$

您可以使用以下命令生成密碼:

htpasswd -n admin | sed 's/\$/\$\$/g'

注意:如果您需要 docker-compose 文件中的文字美元符號,則需要使用此處記錄的$$

在目錄中發出docker-compose up應該會啟動所有服務,並按預期工作。

根據您提供的詳細信息,以上內容應該對您有用,但可以根據您的需要在多個方面進一步改進。

此外,在docker-compose.yml文件中擁有 traefik 儀表板的憑據可能不是最好的,您可能希望為其使用 docker 機密。 您還可以添加運行狀況檢查並考慮將myappmyapp1放入單獨的內部網絡。

如果您想進一步了解它,我建議您從Get started with Docker Compose 開始,並閱讀: Dockerfile 參考Compose 文件版本 3 參考

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM