use*_*_12 6 reverse-proxy docker docker-compose traefik fastapi
假设我当前的公共 IP 是101.15.14.71
,我有一个名为的域example.com
,我使用 cloudflare 配置了该域,并且我创建了多个指向我的公共 ip 的 DNS 条目。
例如:
1) new1.example.com - 101.15.14.71
2) new2.example.com - 101.15.14.71
3) new3.example.com - 101.15.14.71
Run Code Online (Sandbox Code Playgroud)
现在,这是我的示例项目结构,
??? 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
Run Code Online (Sandbox Code Playgroud)
这里我有两个 fastAPI(即 myapp、myapp1)
这是我在myapp 和 myapp1中的main.py中的示例代码,它完全相同,但返回 staement 不同,仅此而已
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_main():
return {"message": "Hello world for my project myapp"}
Run Code Online (Sandbox Code Playgroud)
这里是我的Dockerfile对于MYAPP和myapp1,这里太两者都完全相同,但唯一不同的是我上部署MYAPP7777
并myapp17778
在不同的容器
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
Run Code Online (Sandbox Code Playgroud)
这是我的 myapp 和 myapp1 的 docker -compose.yml文件,这里我也有完全相同但唯一的区别是我更改了端口,
Run Code Online (Sandbox Code Playgroud)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文件夹,
acme.json # 我使用nano acme.json
没有任何内容的命令创建了它,但这样做是chmod 600 acme.json
为了获得适当的权限。
traefik_dynamic.toml
Run Code Online (Sandbox Code Playgroud)[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"] ]
Run Code Online (Sandbox Code Playgroud)[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"
Run Code Online (Sandbox Code Playgroud)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 服务,
new2.example.com
new3.example.com
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`)"
Run Code Online (Sandbox Code Playgroud)
所有服务只需要一个 docker-compose 文件,无需为每个容器定义一个文件。
\n您应该使用的项目结构应该类似于:
\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 docker-compose.yml\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 myapp\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .dockerignore\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Dockerfile\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 myapp1\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .dockerignore\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Dockerfile\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 traefik\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 acme.json\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 traefik.yml\n
Run Code Online (Sandbox Code Playgroud)\n创建容器时,除非用于开发目的,否则建议不要使用完整的镜像,例如 ubuntu。为了满足您的目的,我会推荐一个 python 图像,例如python:3.7-slim
.
不确定您是否将其用于开发或生产目的,但您也可以使用卷在容器内挂载应用程序目录(如果您将其用于开发,则特别有用),并且仅对 和 两者使用一个 Dockerfile,对其进行myapp
自myapp1
定义通过环境变量。
由于您已经在使用 traefik 的动态配置,因此我将通过文件中的 docker 标签完成容器配置的大部分设置docker-compose.yml
。
此时,您的 dockerfilemyapp
和将会非常相似,但我将它们保留为单独的文件,因为您将来可能需要根据应用程序的要求对它们进行更改。myapp1
我为端口使用了环境变量,它可以允许您从docker-compose.yml
文件中更改端口。
您可以使用以下Dockerfile
(./myapp/Dockerfile
和./myapp1/Dockerfile
):
FROM python:3.7-slim\n\nARG DEBIAN_FRONTEND=noninteractive\n\nENV PYTHONUNBUFFERED=1\n\nRUN pip3 install -U pip setuptools wheel && \\\n pip3 install gunicorn fastapi uvloop httptools "uvicorn[standard]"\n\nCOPY . /app\n\nENV PORT=7777 # and 7778 for myapp1\n\nENTRYPOINT /usr/local/bin/gunicorn -b 0.0.0.0:$PORT -w 1 -k uvicorn.workers.UvicornWorker app.main:app --chdir /app\n
Run Code Online (Sandbox Code Playgroud)\n注意:您确实应该为应用程序依赖项使用诗歌或requirements.txt文件之类的东西。
\n文件.dockerignore
(./myapp/.dockerignore
和./myapp1/.dockerignore
)应包含:
Dockerfile\n
Run Code Online (Sandbox Code Playgroud)\n由于整个目录都被复制到容器内,因此您不需要将其Dockerfile
放在其中。
你的主要 traefik 配置 ( ./traefik/traefik.yml
) 可以是这样的:
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 docker-compose.yml\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 myapp\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .dockerignore\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Dockerfile\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 myapp1\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 .dockerignore\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 Dockerfile\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82\xc2\xa0\xc2\xa0 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 traefik\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 acme.json\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 traefik.yml\n
Run Code Online (Sandbox Code Playgroud)\n注意:上面的 acme 配置将使用 stage 的 LetsEncrypt 服务器。确保所有详细信息均正确,并caServer
在测试一切正常后将其删除,以便与 LetsEncrypt 生产服务器进行通信。
你的./docker-compose.yml
文件应该是这样的:
FROM python:3.7-slim\n\nARG DEBIAN_FRONTEND=noninteractive\n\nENV PYTHONUNBUFFERED=1\n\nRUN pip3 install -U pip setuptools wheel && \\\n pip3 install gunicorn fastapi uvloop httptools "uvicorn[standard]"\n\nCOPY . /app\n\nENV PORT=7777 # and 7778 for myapp1\n\nENTRYPOINT /usr/local/bin/gunicorn -b 0.0.0.0:$PORT -w 1 -k uvicorn.workers.UvicornWorker app.main:app --chdir /app\n
Run Code Online (Sandbox Code Playgroud)\n您可以使用以下命令生成密码:
\nhtpasswd -n admin | sed \'s/\\$/\\$\\$/g\'\n
Run Code Online (Sandbox Code Playgroud)\n注意:如果您需要在 docker-compose 文件中使用文字美元符号,则需要按照此处$$
记录的方式使用。
在目录中发出docker-compose up
应该会启动所有服务,并按预期工作。
根据您提供的详细信息,上述内容应该适合您,但可以根据您的需求在多个点进一步改进。
\n此外,在文件中包含 traefik 仪表板的凭据docker-compose.yml
可能不是最好的,您可能需要使用 docker 机密。您还可以添加运行状况检查并考虑将myapp
和myapp1
放入单独的内部网络中。
如果您想进一步了解它,我建议您从Docker Compose 入门开始,并阅读:Dockerfile 参考和Compose 文件版本 3 参考
\n 归档时间: |
|
查看次数: |
245 次 |
最近记录: |