简体   繁体   English

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

[英]How to access an internal server within a docker container?

So I am trying to dockerize a Flask application which does the following: 因此,我正在尝试对执行以下操作的Flask应用程序进行泊坞化:

  1. Runs internally a Bokeh Server in the container's 127.0.0.1:5006 address. 在容器的127.0.0.1:5006地址内部运行Bokeh服务器。
  2. Runs the Flask application in the address 0.0.0.0:5000 so it is accessible from outside the container. 在地址0.0.0.0:5000中运行Flask应用程序,以便可以从容器外部对其进行访问。
  3. When a connection is made, Flask tries to fetch data from the Bokeh Server (which is instantiated with the container). 建立连接后,Flask尝试从Bokeh服务器(由容器实例化)中获取数据。 But when running as a container, it never gets to hit the container's own localhost (not even setting it to --net=host). 但是,当作为容器运行时,它永远不会碰到容器自己的本地主机(甚至没有将其设置为--net = host)。

The only way I have managed to get it working is creating the Bokeh server in 0.0.0.0 as well and passing the container's host IP (I am on Windows) to the address Flask tries to fetch it from (see url field in autoload_server). 我设法使其正常工作的唯一方法是在0.0.0.0中也创建Bokeh服务器 ,并将容器的主机IP(我在Windows上)传递到Flask尝试从其获取地址的地址(请参见autoload_server中的url字段)。 But this wouldn't work for other machines, obviously. 但这显然不适用于其他机器。

Here are the relevant chunks of code: 以下是相关的代码块:

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()

Maybe someone with more background on Docker could help me understand what is going on here please? 也许对Docker有更多背景的人可以帮助我了解这里的情况? I assumed that from the container's perspective anything published on localhost would be visible by other services published from within the same container. 我假设从容器的角度来看,在本地主机上发布的任何内容都可以被在同一容器内发布的其他服务看到。

Thanks in advance 提前致谢

I'm going to answer the question from what I suspect is going on based on my comment. 我将根据我的评论回答我所怀疑的问题。

In my very brief review of Bokeh and server_document (from https://docs.bokeh.org/en/latest/docs/user_guide/embed.html#bokeh-applications ), it would appear that this function actually generates some JavaScript. 在我对Bokeh和server_document简短回顾中(来自https://docs.bokeh.org/en/latest/docs/user_guide/embed.html#bokeh-applications ),似乎该函数实际上生成了一些JavaScript。 It doesn't actually make a connection to the Bokeh server from Python or Flask itself. 它实际上并没有通过Python或Flask本身与Bokeh服务器建立连接。 The connection comes from the browser. 连接来自浏览器。

Given this information, listening on http://127.0.0.1:5006 wouldn't allow the browser to connect. 有了这些信息,在http://127.0.0.1:5006监听将不允许浏览器连接。 Even with the container running in --net=host mode on Windows or Mac will leave the container listening on the Docker virtual machine network and not the actual host, still causing the connection to fail. 即使容器在Windows或Mac上以--net=host模式运行,也会使该容器在Docker虚拟机网络上而不是实际主机上侦听,仍然会导致连接失败。

The Bokeh server will need to listen on 0.0.0.0 so that any IP coming through the Docker NAT will be able to connect. Bokeh服务器将需要侦听0.0.0.0,以便通过Docker NAT的任何IP都可以连接。 In addition, you need to tell your browser how to get to this container. 另外,您需要告诉您的浏览器如何到达此容器。 This means using the IP address of the VM or the IP of your computer where the Docker container port is exposed. 这意味着使用VM的IP地址或暴露Docker容器端口的计算机的IP。

In a production setting you would likely run the Flask and Bokeh server ports behind a load balancer or other reverse proxy which could then expose a single IP / DNS name to connect to them. 在生产设置中,您可能会在负载均衡器或其他反向代理后面运行Flask和Bokeh服务器端口,然后可以公开单个IP / DNS名称以连接到它们。 You would then use that DNS name or IP as your url param. 然后,您将使用该DNS名称或IP作为您的url参数。

If you were running this setup on a Linux machine, then --net=host would allow your container to communicate with the host's loopback interface; 如果您是在Linux机器上运行此设置,则--net=host将允许您的容器与主机的环回接口通信; that flag is just specifying that the container should not use its own network namespace, and instead just runs with access to all of the host's network adaptors. 该标志仅指定容器不应该使用其自己的网络名称空间,而仅在可以访问主机的所有网络适配器的情况下运行。

However, --net=host doesn't work the same if you're running Docker in Windows or MacOS -- this is because while the docker client is running on your Windows machine, the containers are actually running on a docker daemon in a separate VM. 但是,如果在Windows或MacOS中运行Docker,-- --net=host工作原理将--net=host -这是因为,当Docker客户端在Windows计算机上运行时,这些容器实际上是在Windows操作系统中的docker守护程序上运行单独的VM。 If you run --net=host and point your Flask server at localhost , you are actually hitting the localhost from the docker VM, not your Windows machine's localhost where Bokeh is running. 如果运行--net=host并将Flask服务器指向localhost ,则实际上是从Docker VM而不是运行Bokeh的Windows计算机的localhost访问localhost。

Networking can be tricky in Docker when you need to deal with multiple containers talking to each other. 当您需要处理多个相互通信的容器时,在Docker中联网可能会很棘手。 The problem you are dealing with is how to discover services in your application. 您要解决的问题是如何在应用程序中发现服务。 There are a few ways to solve this problem: 有几种方法可以解决此问题:

The simplest is probably to inject the IP of your Bokeh server into your Flask app as config; 最简单的方法可能是将Bokeh服务器的IP作为配置注入到Flask应用中。 typically this is done using environment variables, which can be passed when running the docker container with the -e BOKEH_IP=1.2.3.4 flag. 通常,这是使用环境变量完成的,可以在运行带有-e BOKEH_IP=1.2.3.4标志的-e BOKEH_IP=1.2.3.4容器时传递该变量。 You would configure a different IP in production. 您将在生产中配置其他IP。

You could also containerize your Bokeh server, and then use something like Docker Compose, Docker Swarm, or Kubernetes to handle communication between your services. 您还可以对Bokeh服务器进行容器化,然后使用诸如Docker Compose,Docker Swarm或Kubernetes之类的东西来处理服务之间的通信。 Docker Compose works on a single machine, Docker Swarm is good for easily scheduling containers across multiple machines, and Kubernetes is a more complex and full-featured option for orchestrating large numbers of interacting services. Docker Compose可在单台机器上运行,Docker Swarm可以轻松地在多台机器上调度容器,而Kubernetes是一个更为复杂且功能齐全的选项,可用于协调大量交互服务。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM