【问题标题】:Handling dynamic IP in Django ALLOWED_HOSTS with nginx使用 nginx 在 Django ALLOWED_HOSTS 中处理动态 IP
【发布时间】:2021-10-28 02:22:39
【问题描述】:

我认为我的 nginx.conf 存在问题,这导致实例一次又一次地重新启动,因为我的托管容器服务的运行状况检查失败。

我在 AWS Lightsail Containers 中运行我的设置,其中运行了三个容器:

  • nginx
  • django
  • nextjs

在我的 AWS Lightsail 实例上发布新版本时,它可以正常运行几分钟,然后遇到 503 错误,导致实例重新启动 - 运行几分钟然后再次重新启动。

查看日志我可以看到健康检查失败,django 抛出错误,说我应该将请求 IP 添加到允许的主机:

[28/Aug/2021:13:56:23] Invalid HTTP_HOST header: 'x.x.x.x'. You may need to add 'x.x.x.x' to ALLOWED_HOSTS.
[28/Aug/2021:13:56:23] Bad Request: /health.txt

问题是我的 lightsail 容器服务没有静态 IP(我也不相信我可以获得静态 IP)。

我当前的 nginx.conf 如下(感谢反馈)。 我的问题是我应该如何处理这个问题?我觉得设置ALLOWED_HOSTS = ['*'] 不是一个好方法。我可以对主机进行硬编码以进行运行状况检查或类似操作吗?

nginx.conf:

upstream backend {
    server ${BACKEND_HOST}:${BACKEND_PORT};
}
upstream frontend {
    server ${FRONTEND_HOST}:${FRONTEND_PORT};
}

server {
    listen 80 default_server;
    server_name example.com;
    server_tokens off;

    gzip on;
    gzip_proxied any;
    gzip_comp_level 4;
    gzip_types text/css application/javascript image/svg+xml;

    location /robots.txt {
        include proxy_params;
        proxy_pass http://backend;
    }

    location /health.txt {
        include proxy_params;
        proxy_pass http://backend;
    }

    location /api {
        include proxy_params;
        proxy_pass http://backend;
    }

    location /admin {
        include proxy_params;
        proxy_pass http://backend;
    }
    
    location / {
        proxy_pass http://frontend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
    }

}

【问题讨论】:

  • 对于你的 nginx 配置,当你对待位置相同时,你可以做location ~ ^/(first|second|third)
  • 谢谢@Amin,我会改的!

标签: django nginx nginx-reverse-proxy


【解决方案1】:

我使用 AWS EC2,通过运行状况检查,我动态获取实例的 ip,然后将其插入 ALLOWED_HOSTS(我认为它也适用于 Lightsail 容器):

import requests

def get_instance_ip():
    try:
        ip = requests.get('http://169.254.169.254/latest/meta-data/local-ipv4').text
    except requests.exceptions.ConnectionError:
        return None
    return ip

AWS_IP = get_ec2_instance_ip()

if AWS_IP is not None:
    ALLOWED_HOSTS += [AWS_IP]

您还可以创建一个中间件,该中间件始终为运行状况检查使用的路径返回 200 状态码(在 MIDDLEWARE 中的 django.middleware.security.SecurityMiddleware 之前插入自定义中间件以避免出现 Invalid HTTP_HOST header 错误)。

【讨论】:

  • 嗯,我喜欢这两个想法!第一个建议的问题(感谢代码示例)是我没有端点来要求最新的动态设置 IP?带有中间件的第二个似乎是一个不错的简单修复!但是它看起来确实有点hacky?
  • @Olsson 端点对于所有 EC2 实例都是相同的。 Lightsail Containers 构建在 EC2 之上,所以我认为我编写的端点应该可以工作。
  • 我认为它有效,因为它在运行状况检查时运行良好。不过好像又回来了?我尝试了中间件方法,基本上是if request.path == '/health.txt' ... return HttpResponse("...", status=200)。但是我仍然不断收到 503 和 Invalid HTTP_HOST header: 'x.x.x.x'. You may need to add 'x.x.x.x' to ALLOWED_HOSTS....
  • @Olsson 您是否在安全中间件之前插入了中间件(您的自定义中间件必须在设置中的MIDDLEWARE 列表中排在第一位)?您是否将 AWS 配置为使用该路径进行安全检查(默认情况下它使用“/”)?运行状况检查是否会继续失败,或者该错误是否与第一种方法不时比较?
  • 我想我已经用你上面的 code-sn-p 解决了。将其放在设置的顶部并附加IP。中间件被放置在安全中间件之前,所以不确定为什么某些请求会一直避免这样做。我没有适当的日志记录来获得足够的洞察力。 Lightsail 日志一团糟。
猜你喜欢
  • 2016-08-30
  • 2018-04-26
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 2014-08-23
  • 2013-05-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多