【问题标题】:Assigning port when building flask docker image构建烧瓶泊坞窗图像时分配端口
【发布时间】:2021-05-21 22:47:42
【问题描述】:

我最近使用烧瓶创建了一个应用程序,并将 py 文件放入 docker 容器中。但是,我对人们分配端口的在线案例感到困惑。

首先在我写的py文件的底部

if __name__ == "__main__":

app.run(host='0.0.0.0',port=8000, debug=True)

在某些情况下,我看到人们在制作 dockerfile 时在 CMD 中指定端口

CMD ["python3", "app.py", "--host=0.0.0.0", "--port=8000"]

根据我自己的经验,在 CMD 中分配的端口根本不适用于我的情况。我想了解这两种方法之间的区别以及何时使用每种方法。

【问题讨论】:

    标签: docker flask docker-image


    【解决方案1】:

    CMD ["python3", "app.py", "--host=0.0.0.0", "--port=8000"] 表示:Python 运行应用程序 app.py 并将 --host 和 --port 参数传递给该应用程序。由你的 app.py 来处理这些参数。如果您的应用不处理这些标志,则无需将它们添加到 CMD。

    如果您的代码中有app.run(host='0.0.0.0',port=8000),那么您的应用将始终监听容器内的端口 8000。在这种情况下,您可以使用CMD ["python3", "app.py"]

    如果您希望能够更改应用程序正在侦听的端口和主机,您可以添加一些代码来从命令行读取值。一旦你设置你的应用程序从命令行查看值,那么运行CMD ["python3", "app.py", "--host=0.0.0.0", "--port=8000"]

    【讨论】:

    • 好答案。我已经给出了另一种对您提出的(正确)观点的补充。
    【解决方案2】:

    关于这种方法:

    if __name__ == "__main__":
        app.run(host='0.0.0.0',port=8000, debug=True)
    

    __name__ 等于"__main__",当应用程序直接使用python 解释器(使用命令python app.py 执行)启动时——这是一个python 技术,与Flask 无关。在这种情况下,app.run 函数被调用,它接受所述的各种参数。 app.run 导致 Werkzeug 开发服务器运行。

    如果您使用像gunicorn 这样的生产WSGI 服务器执行程序,则此块将运行,因为在这种情况下__name__ 将不等于"__main__",所以app.run 调用被绕过。

    实际上,将app.run 调用放在这个if 块中意味着您可以使用python app.py 运行开发服务器,并避免在gunicorn 或类似产品中导入相同的代码时运行开发服务器。


    有很多较早的教程或帖子都引用了上述方法。现代版本的 Flask 附带 flask 命令,旨在替换它。所以基本上没有if,您可以启动开发服务器,以类似于gunicorn 的方式导入您的应用程序对象:

    flask run -h 0.0.0.0 -p 8000

    这会自动在app.py 中查找名为app 的对象,并接受主机和端口选项,如您在flask run --help 中所见:

    Options:
      -h, --host TEXT                 The interface to bind to.
      -p, --port INTEGER              The port to bind to.
    

    此方法的一个优点是,如果您使用自动重新加载器并引入语法错误,开发服务器不会崩溃。当然,相同的代码将与gunicorn 等生产服务器兼容。


    考虑到上述情况,关于您传递的命令:

    python app.py --host=0.0.0.0 --port=8000
    

    我不确定您是否对引用flask 命令支持的选项感到困惑,但是要使这个选项正常工作,您需要手动编写一些代码来处理这些选项。这可以通过像argparse 这样的python 模块来完成,但考虑到flask 命令实际上支持开箱即用,这可能是多余的。

    总结:您可能应该删除 if 块,并且您的 Dockerfile 应该包含:

    CMD ["flask", "run", "--host=0.0.0.0", "--port=8000"]
    

    您可能还希望检查FLASK_ENV 环境变量is setdevelopment 以使用自动重新加载器,并注意CMD 行需要在此Dockerfile 中更改以使用@987654357 运行@ 或类似的产品,但这可能超出了这个问题的范围。

    【讨论】:

    • 对我来说很有意义,非常感谢,确实我很困惑并在这里混合了@v25
    • 我还检查了我正在阅读@v25 的来源,很明显他们都没有写 CMD[python app.py --host=0.0.0.0 --port=8000],是我把事情搞混了……我的错,再次感谢您的详细解释。
    • @MeiNanZhu 很高兴我能帮上忙。我想进一步扩展最后一部分。如果您尽可能使用 docker compose,您可能希望查看我的 repo flask-reload-in-docker,这是我对使用 compose 文件覆盖同时支持 dev 和 prod 的看法,以及两者的单个 Dockerfile。对此有任何疑问,请随时针对 repo 记录问题。
    • 谢谢@v25。我经历了我在这个问题中发布的另一个谜团。 stackoverflow.com/questions/66250745/… 简而言之,当我有 app.run(debug=True) 时,容器运行我的 py 文件并立即退出。但是,在我取消 debug=True 后,容器不再退出(这是我需要的,所以我可以通过 IP 访问应用程序)。你是否偶然明白了背后的原因。非常感谢。
    猜你喜欢
    • 2022-09-23
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2019-09-19
    • 1970-01-01
    • 2014-03-22
    • 2022-08-13
    相关资源
    最近更新 更多