Python 如何访问docker容器中的内部服务器?

Python 如何访问docker容器中的内部服务器?,python,docker,networking,flask,bokeh,Python,Docker,Networking,Flask,Bokeh,因此,我尝试对一个Flask应用程序进行dockerize,该应用程序执行以下操作: 在容器的127.0.0.1:5006中内部运行Bokeh服务器 地址 运行地址为0.0.0.0:5000的Flask应用程序 它可以从容器外部访问 建立连接后,Flask尝试从Bokeh服务器获取数据 (使用容器实例化)。但是当作为容器运行时,它永远不会访问容器自己的本地主机(甚至没有将其设置为--net=host) 我设法让它工作的唯一方法是在0.0.0.0中创建Bokeh服务器,并将容器的主机IP(我在Wi

因此,我尝试对一个Flask应用程序进行dockerize,该应用程序执行以下操作:

  • 在容器的127.0.0.1:5006中内部运行Bokeh服务器 地址
  • 运行地址为0.0.0.0:5000的Flask应用程序 它可以从容器外部访问
  • 建立连接后,Flask尝试从Bokeh服务器获取数据 (使用容器实例化)。但是当作为容器运行时,它永远不会访问容器自己的本地主机(甚至没有将其设置为--net=host)
  • 我设法让它工作的唯一方法是在0.0.0.0中创建Bokeh服务器,并将容器的主机IP(我在Windows上)传递给Flask尝试从中获取它的地址(请参阅autoload_server中的url字段)。但这显然不适用于其他机器

    以下是相关的代码块:

    server = Server({'/datavisualization': bokeh_app}, io_loop=io_loop, address="127.0.0.1",
                     allow_websocket_origin=["*"], host=["*"])
    
    @app.route('/')
    def bokeh_server():
        # Fetch Running Bokeh Server
        bokeh_embed = autoload_server(model=None,
                                      app_path="/datavisualization",
                                      url="http://127.0.0.1:5006")
    
        html = render_template('index.html', bokeh_embed=Markup(bokeh_embed))
    
        return html
    
    if __name__ == '__main__':
        from tornado.httpserver import HTTPServer
        from tornado.wsgi import WSGIContainer
        from bokeh.util.browser import view
        # Serve the Flask app
        http_server = HTTPServer(WSGIContainer(app))
        http_server.listen(5000, address='0.0.0.0')
        io_loop.add_callback(view, "http://0.0.0.0:5000/")
        io_loop.start()
    
    也许有人对Docker有更多的背景可以帮助我了解这里发生了什么?我假设从容器的角度来看,本地主机上发布的任何内容都可以被同一容器中发布的其他服务看到


    提前感谢

    我将根据我的评论回答我所怀疑的问题

    在我对Bokeh和
    server\u文档
    (from)的简要回顾中,似乎这个函数实际上生成了一些JavaScript。它实际上并没有从Python或Flask本身连接到Bokeh服务器。连接来自浏览器

    根据这些信息,收听
    http://127.0.0.1:5006
    不允许浏览器连接。即使容器在Windows或Mac上以
    --net=host
    模式运行,容器仍将侦听Docker虚拟机网络而不是实际主机,这仍会导致连接失败

    Bokeh服务器需要监听0.0.0.0,以便通过Docker NAT的任何IP都能够连接。此外,您需要告诉浏览器如何访问此容器。这意味着使用VM的IP地址或Docker容器端口所在计算机的IP


    在生产环境中,您可能会在负载平衡器或其他反向代理之后运行Flask和Bokeh服务器端口,然后这些端口可以公开一个IP/DNS名称来连接到它们。然后,您将使用该DNS名称或IP作为您的
    url
    参数。

    我将根据我的评论回答我所怀疑的问题

    在我对Bokeh和
    server\u文档
    (from)的简要回顾中,似乎这个函数实际上生成了一些JavaScript。它实际上并没有从Python或Flask本身连接到Bokeh服务器。连接来自浏览器

    根据这些信息,收听
    http://127.0.0.1:5006
    不允许浏览器连接。即使容器在Windows或Mac上以
    --net=host
    模式运行,容器仍将侦听Docker虚拟机网络而不是实际主机,这仍会导致连接失败

    Bokeh服务器需要监听0.0.0.0,以便通过Docker NAT的任何IP都能够连接。此外,您需要告诉浏览器如何访问此容器。这意味着使用VM的IP地址或Docker容器端口所在计算机的IP


    在生产环境中,您可能会在负载平衡器或其他反向代理之后运行Flask和Bokeh服务器端口,然后这些端口可以公开一个IP/DNS名称来连接到它们。然后,您将使用该DNS名称或IP作为
    url
    参数。

    如果您在Linux计算机上运行此设置,则
    --net=host
    将允许您的容器与主机的环回接口通信;该标志只是指定容器不应使用其自己的网络名称空间,而是仅在访问主机的所有网络适配器的情况下运行

    但是,如果您在Windows或MacOS中运行Docker,
    --net=host
    的工作方式不同,这是因为当Docker客户端在Windows机器上运行时,容器实际上在单独VM中的Docker守护进程上运行。如果运行
    --net=host
    并将Flask服务器指向
    localhost
    ,则实际上是从docker VM命中localhost,而不是运行Bokeh的Windows机器的localhost

    在Docker中,当您需要处理多个容器之间的通信时,网络可能会很棘手。您要处理的问题是如何在应用程序中发现服务。有几种方法可以解决此问题:

    最简单的方法可能是将Bokeh服务器的IP作为配置注入Flask应用程序;通常,这是使用环境变量来完成的,当运行带有
    -e BOKEH_IP=1.2.3.4
    标志的docker容器时,可以传递环境变量。您将在生产中配置不同的IP


    您还可以将Bokeh服务器容器化,然后使用Docker Compose、Docker Swarm或Kubernetes之类的工具来处理服务之间的通信。Docker Compose可以在一台机器上工作,Docker Swarm适合在多台机器上轻松调度容器,Kubernetes是一个更复杂、功能更全面的选项,用于协调大量交互服务。

    如果您在Linux机器上运行此设置,然后,
    --net=host
    将允许容器与主机的环回接口通信;该标志只是指定容器不应使用其自己的网络名称空间,而是仅在访问主机的所有网络适配器的情况下运行

    但是,如果您在Windows或MacOS中运行Docker,
    --net=host
    的工作原理不同,这是因为