支持的标签和对应的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镜像,使用Meinheld由Gunicorn管理,用于在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_NAME
和 VARIABLE_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的实际主机和端口。
默认情况下,根据 HOST
和 PORT
变量设置。
因此,如果您没有更改任何内容,它将默认设置为:
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
日志被发送到容器的 stderr
和 stdout
,这意味着您可以使用 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
版本。 🤓
测试
所有镜像标签、配置、环境变量和应用程序选项都经过测试。
发布说明
最新变更
升级
- ⬆ 将gunicorn从20.1.0升级到22.0.0。PR #149 由 @dependabot[bot] 提交。
内部
- 👷 更新 issue-manager.yml GitHub Action 权限。PR #151 由 @tiangolo 提交。
- 在 /docker-images 中将 gunicorn 从 20.1.0 升级到 22.0.0。PR #148 由 @dependabot[bot] 提交。
- ⬆ 将 docker/build-push-action 从 2 升级到 5。PR #144 由 @dependabot[bot] 提交。
- ⬆ 将 docker/setup-buildx-action 从 1 升级到 3。PR #143 由 @dependabot[bot] 提交。
- ⬆ 将 docker/login-action 从 1 升级到 3。PR #142 由 @dependabot[bot] 提交。
- ⬆ 将 actions/setup-python 从 4 升级到 5。PR #132 由 @dependabot[bot] 提交。
- ⬆ 将 peter-evans/dockerhub-description 从 3 升级到 4。PR #130 由 @dependabot[bot] 提交。
- ⬆️ 将 black 需求从 ^22.10 更新到 ^23.3。PR #120 由 @dependabot[bot] 提交。
- 🔧 添加 GitHub 讨论和问题模板,以及安全政策。PR #146 由 @alejsdev 提交。
- ⬆ 将 mypy 需求从 ^0.991 更新到 ^1.4。PR #136 由 @dependabot[bot] 提交。
- 🔧 更新
latest-changes.yml
。PR #141 由 @alejsdev 提交。
0.5.0
功能
重构
升级
- ⬆️ 在 /docker-images 中将 flask 从 2.2.2 升级到 2.2.5。PR #129 由 @dependabot[bot] 提交。
文档
内部
- 🐛 修复 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-25
和python2.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。
重大变更
升级
- ⬆️ 在 /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
0.1.0
- 添加对
/app/prestart.sh
的支持。
许可证
本项目根据 MIT 许可证的条款授权。