Flask url_for在docker / docker-compose下无法撰写正确的url

时间:2019-03-14 19:37:27

标签: python docker flask docker-compose docker-swarm

我有一个Flask应用程序,它运行在一个集群下运行的Docker容器中。当我使用url_for为API创建外部网址时,它将返回docker服务名称而不是绝对路径。

例如。

endpoint = url_for('api_v1.get_me_the_data', sn=123, 
                _external=True, _scheme="https")

返回类似https://app-primary:8000/api/v1/devices/123的内容。

其他详细信息:

  • 在Nginx反向代理后面使用Gunicorn运行

我尝试过玩SERVER_NAME,但是没有骰子。有简单的方法可以解决此问题吗?还是应该为url_for写一个包装函数?

2 个答案:

答案 0 :(得分:1)

由于您将python应用程序放在容器内以及Nginx的后面,因此您可能需要使用ProxyFix,它会做两件事:

  • 通过阅读REMOTE_ADDR
  • 获取客户端IP而不是nginx容器IP
  • 通过阅读HTTP_HOST
  • 设置主机名

接下来,您需要确保nginx发送这些标头:

proxy_set_header Host            $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

答案 1 :(得分:0)

我遇到了类似的问题。我正在使用 uwsgi 提供烧瓶应用程序,与另一个容器中的 nginx 交谈。我的密码重置功能正在发送带有容器名称而不是域名的链接。 尝试使用 test_request_contest 和 'SERVER_NAME' 配置变量,但失败了。链接仍然是本地主机。 最终对我有用的是一种快速且(非常)肮脏的方法:

def create_external_link(link):
    # splits after 'http(s)'
    linkParts = link.split("//")
    linkLeft = linkParts[0]
    linkRight = linkParts[1]
    # from the right part (after 'http://') take whats after 'containerName/' doing only one split
    linkRight = linkRight.split("/",1)[1]
    fullLink = linkLeft + '//example.com/' + linkRight
    return fullLink

然后在创建链接时并在将其进一步传递给例如邮件模板之前:

link = create_external_link(url_for('blueprint.endpoint', **kwargs, _external=True))

请尽快使用更好的解决方案,这是一个丑陋的黑客。