docker - docker-compose 中的快速 api 和 nginx 在连接到上游时显示 connect() 失败(111:连接被拒绝),客户端:172.27.0.1,服务器:
问题描述
fastapi nginx 模板
它是快速的 api 和 nginx 模板,但目前它不能按我预期的那样工作。当您 curl localhost 时,它会响应 502 bad gateway instaed of hello world ,这是在 main.py 中定义的...
docker logs web 显示connect() failed (111: Connection refused) while connecting to upstream, client: 172.27.0.1, server:
在 nginx 容器中。
但为什么 ??你怎么能解决这个错误?
文件树
.
├── Dockerfile
├── README.md
├── docker-compose.yml
├── main.py
├── nginx
│ ├── Dockerfile
│ └── nginx.conf
└── requirements.txt
构建并开始
docker-compose up -d --build
docker logs ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
cb79d9efaf75 fast-api-nginx-template_web "/docker-entrypoint.…" 4 minutes ago Up 4 minutes 0.0.0.0:80->80/tcp, :::80->80/tcp web
6b049c395508 fast-api-nginx-template_api "uvicorn main:app --…" 4 minutes ago Up 4 minutes 0.0.0.0:8000->8000/tcp, :::8000->8000/tcp api
curl localhost
<html>
<head><title>502 Bad Gateway</title></head>
<body>
<center><h1>502 Bad Gateway</h1></center>
<hr><center>nginx/1.21.1</center>
</body>
</html>
docker logs web
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
2021/08/28 13:58:37 [error] 31#31: *8 connect() failed (111: Connection refused) while connecting to upstream, client: 172.27.0.1, server: 127.0.0.1, request: "GET / HTTP/1.1", upstream: "http://172.27.0.3:8000/", host: "localhost"
172.27.0.1 - - [28/Aug/2021:13:58:37 +0000] "GET / HTTP/1.1" 502 157 "-" "curl/7.64.1"
docker logs api
INFO: Started server process [1]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
码头工人撰写
码头工人撰写
version: "3.9"
services:
web:
container_name: web
build: nginx
ports:
- 80:80
depends_on:
- api
networks:
- local-net
api:
container_name: api
build: .
ports:
- 8000:8000
networks:
- local-net
expose:
- 8000
networks:
local-net:
driver: bridge
网络
nginx/Dockerfile
FROM nginx
RUN apt-get update
COPY nginx.conf /etc/nginx/nginx.conf
nginx/nginx.conf
worker_processes 1;
events {
worker_connections 1024;
accept_mutex off;
use epoll;
}
http {
include mime.types;
upstream app_serve {
server web:8000;
}
access_log /var/log/nginx/access.log;
error_log /var/log/nginx/error.log;
server {
listen 80 ipv6only=on;
server_name 127.0.0.1;
location / {
proxy_pass http://app_serve;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
}
api
Dockerfile
ARG BASE_IMAGE=python:3.8-buster
FROM $BASE_IMAGE
RUN apt-get -y update && \
apt-get install -y --no-install-recommends \
build-essential \
openssl libssl-dev \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ARG USER_NAME=app
ARG USER_UID=1000
ARG PASSWD=password
RUN useradd -m -s /bin/bash -u $USER_UID $USER_NAME && \
gpasswd -a $USER_NAME sudo && \
echo "${USER_NAME}:${PASSWD}" | chpasswd && \
echo "${USER_NAME} ALL=(ALL) ALL" >> /etc/sudoers
COPY ./ /app
RUN chown -R ${USER_NAME}:${USER_NAME} /app
USER $USER_NAME
WORKDIR /app
ENV PATH $PATH:/home/${USER_NAME}/.local/bin
RUN pip3 install --user --upgrade pip
RUN pip3 install --user -r requirements.txt
RUN rm -rf ~/.cache/pip/*
EXPOSE 8000
# Execute
CMD ["uvicorn", "main:app", "--host", "127.0.0.1" ,"--port" ,"8000"]
主文件
from typing import Optional
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def load_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def load_item(item_id: int, q: Optional[str] = None):
return {"item_id": item_id, "q": q}
解决方案
乍一看,我认为这是因为您已将 uvicorn 绑定到127.0.0.1
,因此,您需要在 api 容器中添加一个额外的反向代理才能在外部提供它(除非您的容器在主机网络中运行,但默认情况下它是一个桥梁)。
绑定 uvicorn0.0.0.0
应该可以解决这个问题。更具体:
CMD ["uvicorn", "main:app", "--host", "0.0.0.0" ,"--port" ,"8000"]
为了确认这一点,我在0.0.0.0
和中运行了我的 fastapi 容器127.0.0.1
:
$ podman ps --no-trunc
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7121420b401ee1803474ff156280a5b5b154c55ae0fd47e1976d8fe9e5331c72 localhost/fastapi-mvc-template:test /usr/bin/fastapi serve --host 127.0.0.1 4 minutes ago Up 4 minutes ago 0.0.0.0:8000->8000/tcp test
dd35d89f161f818e5b34c138bd3d42bdb4d84100b76999d4fc2444c7d0d1a1d9 localhost/fastapi-mvc-template:0.1.0 /usr/bin/fastapi serve --host 0.0.0.0 2 minutes ago Up 2 minutes ago 0.0.0.0:9000->8000/tcp test_ok
$ curl localhost:8000/api/ready
curl: (56) Recv failure: Connection reset by peer
$ curl localhost:9000/api/ready
{"status":"ok"}
推荐阅读
- javascript - Rxjs 在管道中调用另一个订阅并以角度更改根订阅的变量
- single-page-application - Auth0 - 用户保持登录状态多长时间?
- python - 如何使用一个数据框的内容来索引另一个多级索引数据框?
- postgresql - Keycloak 在启动期间重试数据库连接
- python - 将函数应用于数据框列时处理空值
- c++ - 是否可以将 Qt WebEngine 中的代理 URL 列入白名单
- regex - 使用正则表达式在bash中提取字符串的第一个单词
- bash - 在bash中搜索多个目录中的文件
- c# - 将c#中的简单加密方法转换为php
- r - 使用 Lead() 和可能的循环添加新变量