Project Icon

meinheld-gunicorn-flask-docker

基于Meinheld和Gunicorn的高性能Flask应用Docker镜像

该项目提供基于Meinheld和Gunicorn的Flask Docker镜像,旨在优化Python Web应用性能。镜像具备自动调优功能,简化Flask应用部署流程。支持多个Python版本,适合单服务器环境下的简单应用。然而,在Kubernetes等集群环境中,用户可能需要考虑从头构建更合适的镜像。

测试 部署

支持的标签和对应的Dockerfile链接

已废弃的标签

🚨 以下标签不再受支持或维护,它们已从GitHub仓库中移除,但如果有人一直在拉取,最后推送的版本可能仍然在Docker Hub上可用:

  • python3.9-alpine3.13
  • python3.8-alpine3.11
  • python3.7-alpine3.8
  • python3.6
  • python3.6-alpine3.8
  • python2.7

这些版本的最后日期标签是:

  • python3.9-alpine3.13-2024-03-11
  • python3.8-alpine3.11-2024-03-11
  • python3.7-alpine3.8-2024-03-11
  • python3.6-2022-11-25
  • python3.6-alpine3.8-2022-11-25
  • python2.7-2022-11-25

注意:每个构建日期都有对应的标签。如果你需要"固定"所使用的Docker镜像版本,可以选择其中一个标签。例如:tiangolo/meinheld-gunicorn-flask:python3.7-2019-10-15

meinheld-gunicorn-flask

这是一个Docker镜像,使用MeinheldGunicorn管理,用于在Flask中使用**Python**构建高性能Web应用,并具有自动性能调优功能。

GitHub仓库https://github.com/tiangolo/meinheld-gunicorn-flask-docker

Docker Hub镜像https://hub.docker.com/r/tiangolo/meinheld-gunicorn-flask/

描述

使用Meinheld运行并由Gunicorn控制的Python Flask Web应用拥有Flask可实现的最佳性能之一(*)。

如果你已经有一个现成的Flask应用或正在构建一个新的应用,这个镜像将为你提供最佳(或接近最佳)的性能。

这个镜像包含一个"自动调优"机制,因此你只需添加你的代码就能自动获得良好的性能。而且无需做出牺牲(如日志记录)。

关于Python 3.10和3.11的说明

Meinheld当前发布的最新版本是1.0.2,发布于2020年5月17日。这个版本的Meinheld需要一个旧版本的Greenlet(>=0.4.5,<0.5),这与Python 3.10和3.11不兼容。这就是为什么这个镜像支持的最新Python版本是Python 3.9。

* 关于性能和功能的说明

如果你正在开始一个新项目,你可能会从更新更快的框架中受益,比如FastAPI(基于ASGI而不是像Flask和Django那样基于WSGI),以及像tiangolo/uvicorn-gunicorn-fastapi这样的Docker镜像。

它能给你带来约200%的Flask可达到的性能,即使使用这个镜像。

此外,如果你想使用WebSockets等新技术,使用基于ASGI的新框架(如FastAPI)会更容易。因为ASGI标准被设计为能够处理异步代码,如WebSockets所需的代码。

技术细节

Meinheld

Meinheld是一个高性能的WSGI兼容Web服务器。

Gunicorn

你可以使用Gunicorn来管理Meinheld并运行多个进程。

Flask

Flask是一个基于Werkzeug、Jinja 2和良好意图的Python微框架。

替代方案

这个镜像是作为tiangolo/uwsgi-nginx-flask的替代方案创建的,提供了约400%的性能提升。

它基于更通用的镜像tiangolo/meinheld-gunicorn。那是你用于其他WSGI框架(如Django)的镜像。

🚨 警告:你可能不需要这个Docker镜像

你可能正在使用Kubernetes或类似工具。在这种情况下,你可能不需要这个镜像(或任何其他类似的基础镜像)。你可能最好从头开始构建Docker镜像


如果你有一个使用Kubernetes、Docker Swarm模式、Nomad或其他类似复杂系统来管理多台机器上分布式容器的机器集群,那么你可能想要在集群级别处理复制,而不是使用在每个容器中启动多个工作进程进程管理器,这就是这个Docker镜像所做的。

在这些情况下(例如使用Kubernetes),你可能想要从头开始构建一个Docker镜像,安装你的依赖项,并运行单个进程,而不是使用这个镜像。

例如,使用Gunicorn,你可以有一个app/gunicorn_conf.py文件,内容如下:

# Gunicorn配置变量
loglevel = "info"
errorlog = "-"  # stderr
accesslog = "-"  # stdout
worker_tmp_dir = "/dev/shm"
graceful_timeout = 120
timeout = 120
keepalive = 5
threads = 3

然后你可以有一个Dockerfile,内容如下:

FROM python:3.9

WORKDIR /code

COPY ./requirements.txt /code/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /code/requirements.txt

COPY ./app /code/app

CMD ["gunicorn", "--conf", "app/gunicorn_conf.py", "--bind", "0.0.0.0:80", "app.main:app"]

你可以在FastAPI文档中关于:FastAPI in Containers - Docker的部分阅读更多关于这些想法的内容,因为相同的想法也适用于容器中的其他Web应用。

何时使用这个Docker镜像

一个简单的应用

如果你的应用足够简单,不需要(至少暂时不需要)过多地微调进程数量,可以直接使用自动化的默认设置,并且你在单个服务器上运行它而不是集群,那么你可能希望在容器中运行一个进程管理器来管理多个工作进程。

Docker Compose

你可能正在使用Docker Compose部署到单个服务器(而不是集群),所以你没有简单的方法来管理容器的复制(使用Docker Compose)同时保持共享网络和负载均衡

在这种情况下,你可能希望有一个单独的容器,其中有一个进程管理器在内部启动多个工作进程,就像这个Docker镜像所做的那样。

Prometheus和其他原因

你可能还有其他原因,使得拥有一个容器多个进程比拥有多个容器,每个容器一个进程更容易。

例如(取决于你的设置),你可能在同一个容器中有一些工具,比如Prometheus导出器,它应该能够访问每个进入的请求

在这种情况下,如果你有多个容器,默认情况下,当Prometheus来读取指标时,它每次都会获得单个容器的指标(处理该特定请求的容器),而不是获得所有复制容器的累积指标

那么,在这种情况下,拥有一个容器多个进程,以及同一容器上的本地工具(例如Prometheus导出器)收集所有内部进程的Prometheus指标并在该单个容器上公开这些指标可能会更简单。


FastAPI文档中关于:FastAPI in Containers - Docker的部分阅读更多相关内容,因为相同的概念也适用于容器中的其他Web应用。

如何使用

你不需要克隆这个仓库。

你可以将这个镜像作为其他镜像的基础镜像。

假设你有一个requirements.txt文件,你可以有一个这样的Dockerfile

FROM tiangolo/meinheld-gunicorn-flask:python3.9

COPY ./requirements.txt /app/requirements.txt

RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt

COPY ./app /app

它会期望在/app/app/main.py找到一个文件。

或者在/app/main.py找到一个文件。

并期望它包含一个名为app的变量,其中包含你的"WSGI"应用。

然后你可以从包含Dockerfile的目录构建你的镜像,例如:

docker build -t myimage ./

高级用法

环境变量

这些是你可以在容器中设置的环境变量及其默认值:

MODULE_NAME

Gunicorn要导入的Python "模块"(文件),该模块中包含实际的Flask应用程序变量。

默认情况下:

  • 如果存在 /app/app/main.py 文件,则为 app.main
  • 如果存在 /app/main.py 文件,则为 main

例如,如果您的主文件位于 /app/custom_app/custom_main.py,您可以这样设置:

docker run -d -p 80:80 -e MODULE_NAME="custom_app.custom_main" myimage

VARIABLE_NAME

Python模块中包含Flask应用程序的变量。

默认情况下:

  • app

例如,如果您的主Python文件包含以下内容:

from flask import Flask
api = Flask(__name__)

@api.route("/")
def hello():
    return "Hello World from Flask"

在这种情况下,api 是包含"Flask应用程序"的变量。您可以这样设置:

docker run -d -p 80:80 -e VARIABLE_NAME="api" myimage

APP_MODULE

传递给Gunicorn的Python模块和变量名字符串。

默认情况下,根据 MODULE_NAMEVARIABLE_NAME 变量设置:

  • app.main:app
  • main:app

您可以这样设置:

docker run -d -p 80:80 -e APP_MODULE="custom_app.custom_main:api" myimage

GUNICORN_CONF

Gunicorn Python配置文件的路径。

默认情况下:

  • 如果存在,则为 /app/gunicorn_conf.py
  • 如果存在,则为 /app/app/gunicorn_conf.py
  • /gunicorn_conf.py(包含的默认值)

您可以这样设置:

docker run -d -p 80:80 -e GUNICORN_CONF="/app/custom_gunicorn_conf.py" myimage

WORKERS_PER_CORE

此镜像将检查运行容器的当前服务器上可用的CPU核心数。

它会将工作进程数设置为CPU核心数乘以此值。

默认情况下:

  • 2

您可以这样设置:

docker run -d -p 80:80 -e WORKERS_PER_CORE="3" myimage

如果您在一个有2个CPU核心的服务器上使用值 3,它将运行6个工作进程。

您也可以使用浮点值。

例如,如果您有一个大型服务器(比如8个CPU核心)运行多个应用程序,而您有一个您知道不需要高性能的ASGI应用程序。并且您不想浪费服务器资源。您可以让它每个CPU核心使用 0.5 个工作进程。例如:

docker run -d -p 80:80 -e WORKERS_PER_CORE="0.5" myimage

在一个有8个CPU核心的服务器上,这将使它只启动4个工作进程。

WEB_CONCURRENCY

覆盖工作进程数的自动定义。

默认情况下:

  • 设置为当前服务器中CPU核心数乘以环境变量 WORKERS_PER_CORE。因此,在一个有2个核心的服务器上,默认情况下它将被设置为 4

您可以这样设置:

docker run -d -p 80:80 -e WEB_CONCURRENCY="2" myimage

这将使镜像启动2个工作进程,不管服务器上有多少个CPU核心可用。

HOST

Gunicorn使用的"主机",Gunicorn将在该IP上监听请求。

它是容器内部的主机。

因此,例如,如果您将此变量设置为 127.0.0.1,它将只在容器内部可用,而不是在运行它的主机上可用。

为了完整性提供,但您可能不应该更改它。

默认情况下:

  • 0.0.0.0

PORT

容器应该监听的端口。

如果您在一个限制性环境中运行容器,强制您使用某个特定端口(如 8080),您可以使用此变量设置它。

默认情况下:

  • 80

您可以这样设置:

docker run -d -p 80:8080 -e PORT="8080" myimage

BIND

传递给Gunicorn的实际主机和端口。

默认情况下,根据 HOSTPORT 变量设置。

因此,如果您没有更改任何内容,它将默认设置为:

  • 0.0.0.0:80

您可以这样设置:

docker run -d -p 80:8080 -e BIND="0.0.0.0:8080" myimage

LOG_LEVEL

Gunicorn的日志级别。

可选值之一:

  • debug
  • info
  • warning
  • error
  • critical

默认设置为 info

如果您需要牺牲日志记录来提高性能,可以将其设置为 warning,例如:

您可以这样设置:

docker run -d -p 80:8080 -e LOG_LEVEL="warning" myimage

日志被发送到容器的 stderrstdout,这意味着您可以使用 docker logs -f your_container_name_here 命令查看日志。

自定义Gunicorn配置文件

镜像在 /gunicorn_conf.py 包含一个默认的Gunicorn Python配置文件。

它使用上面声明的环境变量来设置所有配置。

您可以通过在以下位置包含一个文件来覆盖它:

  • /app/gunicorn_conf.py
  • /app/app/gunicorn_conf.py
  • /gunicorn_conf.py

自定义 /app/prestart.sh

如果您需要在启动应用程序之前运行任何内容,可以在 /app 目录中添加一个 prestart.sh 文件。镜像将自动检测并在启动所有内容之前运行它。

例如,如果您想添加Alembic SQL迁移(使用SQLALchemy),您可以在代码目录中创建一个 ./app/prestart.sh 文件(将由您的 Dockerfile 复制),内容如下:

#! /usr/bin/env bash

# 让数据库启动
sleep 10;
# 运行迁移
alembic upgrade head

它会等待10秒钟,给数据库一些时间启动,然后运行 alembic 命令。

如果您需要在启动应用程序之前运行Python脚本,您可以让 /app/prestart.sh 文件运行您的Python脚本,例如:

#! /usr/bin/env bash

# 在启动前运行自定义Python脚本
python /app/my_custom_prestart_script.py

🚨 Alpine Python警告

简而言之:对于Python项目,您可能不应该使用Alpine,而应该使用 slim Docker镜像版本。


想要更多细节?继续阅读 👇

Alpine对于其他语言更有用,在这些语言中,您可以在一个Docker镜像阶段(使用多阶段Docker构建)中构建静态二进制文件,然后将其复制到一个简单的Alpine镜像中,然后只执行该二进制文件。例如,使用Go。

但对于Python,由于Alpine不使用用于构建Python扩展的标准工具,在安装包时,在许多情况下Python(pip)找不到Alpine的预编译可安装包("wheel")。在调试了许多奇怪的错误之后,您会意识到您必须安装大量额外的工具并构建许多依赖项,只是为了使用一些常见的Python包。 😩

这意味着,尽管原始的Alpine镜像可能很小,但最终您会得到一个大小与使用标准Python镜像(基于Debian)相当的镜像,在某些情况下甚至更大。 🤯

在所有这些情况下,构建时间都会更长,消耗更多资源,构建依赖项的时间更长,也会增加其碳足迹,因为每次构建都会使用更多的CPU时间和能源。 🌳

如果您想要精简的Python镜像,您应该尝试使用仍然基于Debian但更小的 slim 版本。 🤓

测试

所有镜像标签、配置、环境变量和应用程序选项都经过测试。

发布说明

最新变更

升级

内部

0.5.0

功能

  • ✨ 添加对多架构构建的支持,包括 ARM(例如 Mac M1)。PR #138@tiangolo 提交。

重构

升级

  • ⬆️ 在 /docker-images 中将 flask 从 2.2.2 升级到 2.2.5。PR #129@dependabot[bot] 提交。

文档

  • 📝 更新 README.md 中的测试徽章。PR #137@alejsdev 提交。

内部

  • 🐛 修复 latest-changes GitHub Action,第二次尝试。PR #140@tiangolo 提交。
  • ⬆ 将 tiangolo/issue-manager 从 0.4.0 升级到 0.5.0。PR #131@dependabot[bot] 提交。
  • 👷 更新 dependabot。PR #126@tiangolo 提交。
  • 👷 更新 latest-changes GitHub Action。PR #125@tiangolo 提交。
  • 🐛 修复 latest-changes GitHub Action。PR #139@tiangolo 提交。
  • 👷 更新最新变更的令牌。PR #124@tiangolo 提交。
  • 👷 添加用于 Docker Hub 描述的 GitHub Action。PR #113@tiangolo 提交。

0.4.0

功能

本次发布的亮点:

  • 支持 Python 3.9 和 3.8。

  • 弃用 Python 3.6 和 2.7。

    • 最后的 Python 3.6 和 2.7 镜像可在 Docker Hub 上获取,但不会再更新或维护。
    • 带日期标签的最后镜像是 python3.6-2022-11-25python2.7-2022-11-25
  • 升级所有依赖项的版本。

  • 小改进和修复。

  • ✨ 添加对 Python 3.9 和 Python 3.9 Alpine 的支持。PR #50@tiangolo 提交。

  • 添加带有 Alpine 3.11 的 Python 3.8。PR #28

  • 添加对 Python 3.8 的支持。PR #27

重大变更

  • 🔥 弃用并移除 Python 3.6 和 2.7。PR #105@tiangolo 提交。
  • 🔥 移除对 Python 2.7 的支持。PR #63@tiangolo 提交。

升级

  • ⬆️ 在 /docker-images 中将 flask 从 2.0.1 升级到 2.2.2。PR #98@dependabot[bot] 提交。
  • ⬆️ 将 Flask 升级到支持 Python 3.6 的最新版本。PR #101@tiangolo 提交。

文档

  • 📝 添加关于 Python 3.10 和 3.11 的说明。PR #112@tiangolo 提交。
  • 📝 添加不建议在 Python 中使用 Alpine 的说明。PR #64@tiangolo 提交。
  • 📝 添加 Kubernetes 警告,说明何时使用此镜像。PR #62@tiangolo 提交。
  • ✏️ 修复 Readme 中重复的"注意"拼写错误。PR #61@tiangolo 提交。
  • 修复 README 中的拼写错误。PR #18@tahmid-choyon 提交。

内部

  • ⬆️ 将 autoflake 的要求从 ^1.3.1 更新至 ^2.0.0。PR #110@dependabot[bot] 提交。
  • ⬆️ 将 black 的要求从 ^20.8b1 更新至 ^22.10。PR #109@dependabot[bot] 提交。
  • ⬆️ 将 mypy 的要求从 ^0.971 更新至 ^0.991。PR #108@dependabot[bot] 提交。
  • ⬆️ 将 docker 的要求从 ^5.0.3 更新至 ^6.0.1。PR #107@dependabot[bot] 提交。
  • ⬆️ 升级 CI 操作系统。PR #111@tiangolo 提交。
  • 🔧 更新 Dependabot 配置。PR #106@tiangolo 提交。
  • 👷 添加定期 CI。PR #104@tiangolo 提交。
  • 👷 添加 alls-green GitHub Action。PR #103@tiangolo 提交。
  • 👷 不为 PR 运行双重 CI,仅在 master 分支上推送时运行。PR #102@tiangolo 提交。
  • ⬆️ 将 black 的要求从 ^19.10b0 更新至 ^20.8b1。PR #57@dependabot[bot] 提交。
  • ⬆️ 将 pytest 的要求从 ^5.4.1 更新至 ^7.0.1。PR #76@dependabot[bot] 提交。
  • ⬆️ 将 actions/checkout 从 2 升级至 3.1.0。PR #99@dependabot[bot] 提交。
  • ⬆️ 将 isort 的要求从 ^4.3.21 更新至 ^5.8.0。PR #55@dependabot[bot] 提交。
  • ⬆️ 将 tiangolo/issue-manager 从 0.2.0 升级至 0.4.0。PR #52@dependabot[bot] 提交。
  • ⬆️ 将 docker 的要求从 ^4.2.0 更新至 ^5.0.3。PR #66@dependabot[bot] 提交。
  • ⬆️ 将 actions/setup-python 从 1 升级至 4。PR #93@dependabot[bot] 提交。
  • ⬆️ 将 mypy 的要求从 ^0.770 更新至 ^0.971。PR #95@dependabot[bot] 提交。
  • 🔥 删除 Travis 备份文件。PR #67@tiangolo 提交。
  • ♻ 重构依赖项以改善 Dependabot 更新并减少使用的磁盘空间。PR #60@tiangolo 提交。
  • 👷 更新 Latest Changes GitHub Action。PR #59@tiangolo 提交。
  • 👷 添加 Dependabot 和外部依赖项以获取自动升级 PR。PR #51@tiangolo 提交。
  • 🎨 格式化 GitHub Action latest-changes。PR #42@tiangolo 提交。
  • 👷 添加 GitHub Action latest-changes,更新 issue-manager,添加资金。PR #41@tiangolo 提交。
  • 重构构建设置:
    • 使用 GitHub actions 进行 CI。
    • 简化、集中和消除代码和配置的重复。
    • 更新测试。
    • 从 Pipenv 迁移到 Poetry。
    • PR #26

0.3.0

  • 重构测试以使用环境变量,并为每个构建日期添加镜像标签,如 tiangolo/meinheld-gunicorn-flask:python3.7-2019-10-15。PR #17

0.2.0

  • 添加对 Python 2.7 的支持(你应该使用 Python 3.7 或 Python 3.6)。PR #11

  • 更新 Travis CI 配置。PR #10@cclauss 提交。

0.1.0

  • 添加对 /app/prestart.sh 的支持。

许可证

本项目根据 MIT 许可证的条款授权。

项目侧边栏1项目侧边栏2
推荐项目
Project Cover

豆包MarsCode

豆包 MarsCode 是一款革命性的编程助手,通过AI技术提供代码补全、单测生成、代码解释和智能问答等功能,支持100+编程语言,与主流编辑器无缝集成,显著提升开发效率和代码质量。

Project Cover

AI写歌

Suno AI是一个革命性的AI音乐创作平台,能在短短30秒内帮助用户创作出一首完整的歌曲。无论是寻找创作灵感还是需要快速制作音乐,Suno AI都是音乐爱好者和专业人士的理想选择。

Project Cover

有言AI

有言平台提供一站式AIGC视频创作解决方案,通过智能技术简化视频制作流程。无论是企业宣传还是个人分享,有言都能帮助用户快速、轻松地制作出专业级别的视频内容。

Project Cover

Kimi

Kimi AI助手提供多语言对话支持,能够阅读和理解用户上传的文件内容,解析网页信息,并结合搜索结果为用户提供详尽的答案。无论是日常咨询还是专业问题,Kimi都能以友好、专业的方式提供帮助。

Project Cover

阿里绘蛙

绘蛙是阿里巴巴集团推出的革命性AI电商营销平台。利用尖端人工智能技术,为商家提供一键生成商品图和营销文案的服务,显著提升内容创作效率和营销效果。适用于淘宝、天猫等电商平台,让商品第一时间被种草。

Project Cover

吐司

探索Tensor.Art平台的独特AI模型,免费访问各种图像生成与AI训练工具,从Stable Diffusion等基础模型开始,轻松实现创新图像生成。体验前沿的AI技术,推动个人和企业的创新发展。

Project Cover

SubCat字幕猫

SubCat字幕猫APP是一款创新的视频播放器,它将改变您观看视频的方式!SubCat结合了先进的人工智能技术,为您提供即时视频字幕翻译,无论是本地视频还是网络流媒体,让您轻松享受各种语言的内容。

Project Cover

美间AI

美间AI创意设计平台,利用前沿AI技术,为设计师和营销人员提供一站式设计解决方案。从智能海报到3D效果图,再到文案生成,美间让创意设计更简单、更高效。

Project Cover

AIWritePaper论文写作

AIWritePaper论文写作是一站式AI论文写作辅助工具,简化了选题、文献检索至论文撰写的整个过程。通过简单设定,平台可快速生成高质量论文大纲和全文,配合图表、参考文献等一应俱全,同时提供开题报告和答辩PPT等增值服务,保障数据安全,有效提升写作效率和论文质量。

投诉举报邮箱: service@vectorlightyear.com
@2024 懂AI·鲁ICP备2024100362号-6·鲁公网安备37021002001498号