Docker 如何正确设置基本traefik反向代理?
假设我当前的公共IP是Docker 如何正确设置基本traefik反向代理?,docker,docker-compose,reverse-proxy,traefik,fastapi,Docker,Docker Compose,Reverse Proxy,Traefik,Fastapi,假设我当前的公共IP是101.15.14.71,我有一个名为example.com的域,我使用cloudflare配置了该域,并创建了多个指向我的公共IP的DNS条目 例如: 下面是我的示例项目结构 ├── myapp │ ├── app │ │ └── main.py │ ├── docker-compose.yml │ └── Dockerfile ├── myapp1 │ ├── app │ │ └── main.py │ ├── docker-comp
101.15.14.71
,我有一个名为example.com
的域,我使用cloudflare配置了该域,并创建了多个指向我的公共IP的DNS条目
例如:
下面是我的示例项目结构
├── 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 on7777
和myapp1 on7778
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文件,这里我也有完全相同的,但唯一的区别是我更改了端口
现在来看traefik文件夹
nano-acme.json
命令创建了它,其中没有任何内容,
但是没有chmod 600 acme.json
以获得适当的权限
- myapp7777,我需要通过
new2.example.com
- myapp17778,我需要通过
new3.example.com
- traefik dashboard,我需要通过
new1.example.com
basic auth I setup
)我在traefik\u 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
不确定是否将其用于开发或生产目的,但也可以使用卷在容器中装入应用程序目录(如果将其用于开发,则特别有用),并且仅将一个Dockerfile用于myapp
和myapp1
,通过环境变量对其进行自定义
由于您已经在使用traefik的动态配置,我将通过docker compose.yml
文件中的docker标签来完成容器配置的大部分设置
此时,myapp
和myapp1
的dockerfile将非常相似,但我将它们作为单独的文件保存,因为将来可能需要根据应用程序的要求对它们进行更改。我为端口使用了一个环境变量,它允许您从docker compose.yml
文件中更改端口
您可以使用以下Dockerfile
(/myapp/Dockerfile
和/myapp1/Dockerfile
):
注意:对于应用程序依赖项,您确实应该使用类似或文件的内容
.dockergnore
文件(/myapp/.dockergnore
和/myapp1/.dockergnore
)应包含:
Dockerfile
因为整个目录都被复制到容器中,而您不需要Dockerfile
在其中
您的主traefik配置(/traefik/traefik.yml
)可以是:
├── docker-compose.yml
├── myapp
│ ├── .dockerignore
│ ├── Dockerfile
│ └── app
│ └── main.py
├── myapp1
│ ├── .dockerignore
│ ├── Dockerfile
│ └── app
│ └── main.py
└── traefik
├── acme.json
└── traefik.yml
提供者:
码头工人:
exposedByDefault:false
全球的:
checkNewVersion:false
sendAnonymousUsage:false
api:{}
访问日志:{}
入口点:
网状物:
地址:“:80”
http:
重定向:
入口点:
致:“网络安全”
方案:“https”
网络安全:
地址:“:443”
发出砰的声响:
入口点:“网络安全”
证书解决者:
myresolver:
顶点:
caServer:“https://acme-staging-v02.api.letsencrypt.org/directory"
电子邮件:“example@example.com"
存储:“/etc/traefik/acme.json”
httpChallenge:
入口点:“网络”
注意:上面的acme配置将使用stage-letsencrypt服务器。确保所有详细信息正确无误,并在测试一切正常后删除caServer
,以便与letsencrypt生产服务器通信
您的/docker compose.yml
文件应该类似于:
├── docker-compose.yml
├── myapp
│ ├── .dockerignore
│ ├── Dockerfile
│ └── app
│ └── main.py
├── myapp1
│ ├── .dockerignore
│ ├── Dockerfile
│ └── app
│ └── main.py
└── traefik
├── acme.json
└── traefik.yml
版本:“3.9”
服务:
myapp:
建造:
上下文:./myapp
dockerfile:./dockerfile
图片:myapp
取决于:
-特拉菲克
揭露:
- 7777
标签:
-“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:
建造:
上下文:./myapp1
dockerfile:./dockerfile
图片:myapp1
取决于:
-特拉菲克
揭露:
- 7778
标签:
-“traefik.enable=true”
-“traefik.http.routers.myapp1.tls=true”
-“traefik.http.routers.myapp1.tls.certResolver=myresolver”
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.yml
├── myapp
│ ├── .dockerignore
│ ├── Dockerfile
│ └── app
│ └── main.py
├── myapp1
│ ├── .dockerignore
│ ├── Dockerfile
│ └── app
│ └── main.py
└── traefik
├── acme.json
└── traefik.yml
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
Dockerfile
htpasswd -n admin | sed 's/\$/\$\$/g'