假如已经按照上一篇的流程创建了一个容器,并且在容器内安装了python环境以及flask相关的包,接下来启动一个服务,供容器外调用。

1. A quick start

首先要使用docker start命令启动一个已经停止的容器:

docker start -i c2f30

指定-i参数,则可以进入容器内部。

接下来,创建一个python脚本:

# test.py
from flask import Flask

app = Flask(__name__)

@app.route('/')
def func():
    return "Hello docker!"
    

if __name__ == '__main__':
    app.run('0.0.0.0', port=5000)

然后运行python test.py,控制台应该打印以下内容:

* Serving Flask app "test" (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: off
 * Running on http://0.0.0.0:5000/ (Press CTRL+C to quit)

好了,至此我们已经启动了一个简单的HTTP服务。接下来,需要让容器挂起在后台运行,然后去宿主机看看能不能请求到这个服务。

为了退出容器时让其在后台运行,可以按住Ctrl+P+Q退出。退出后用docker ps查看,发现该容器的状态是Up,即“挂起”。

打开宿主机的浏览器,在地址栏输入http://localhost:5000/,就可以看到屏幕显示的“Hello docker!”了。或者利用curl命令:

curl http://127.0.0.1:5000/

2. 为什么没有做端口映射?

注意到在第一步中,并没有做所谓的端口映射,但宿主机仍然可以请求到容器内的服务,这是因为在创建容器时指定了--network参数的值为host,其作用可以理解为容器和宿主机是网络共享的。既然网络都是共享的,当然不需要额外指定端口了。


如果在用docker run创建新容器时不指定--network,此时的网络连接方式为bridge,那么要想宿主机可以访问容器内的服务,就需要指定端口映射了:

docker run -it -p 50001:5000 my-first-image /bin/bash

-p参数的意思是将容器的端口(5000)映射到宿主机的50001上。

想象中,按照上述方式启动了一个容器,并执行python test.py。那么在容器外访问http://127.0.0.1:50001/,然而,我执行了curl命令后,得到的结果是:

[root@localhost ~]# curl http://127.0.0.1:50001/
curl: (56) Recv failure: Connection reset by peer

这是什么原因呢?我查了很久的资料,也在不同的平台上提问过,但目前仍然没有找到原因及解决方案。所以,只能采用--network host的方式生成容器了。

具体的问题描述我贴在了这里,如果哪位大神路过,欢迎不吝赐教!感激!