Docker+Flask 实战:打造高并发微服务架构

Docker+Flask 实战:打造高并发微服务架构

今天我们要深入探讨一个非常热门且实用的主题:基于 Docker 部署 Python Flask 应用。Docker 作为当下最流行的容器化技术,已经广泛应用于各种开发和部署场景,尤其是在微服务架构中。而 Flask 作为 Python 世界里轻量级的 Web 框架,同样备受开发者青睐。将二者结合,能极大地提高我们应用的部署效率和可移植性。接下来,我们就一起通过一个完整的实例来学习如何实现这个过程。

测试虚拟机环境介绍

在开始之前,先给大家介绍一下我们使用的测试虚拟机环境。我们使用的是 VMware,配置为 4G 内存和 2 核心。这样的配置对于我们今天的演示来说是足够的,当然在实际生产环境中,你可能需要根据具体的应用需求来调整硬件资源。

Docker + Flask 部署实例

1. 项目代码

首先,我们来看一下 Flask 应用的代码,它在 app.py 文件中。

from flask import Flask
app = Flask(__name__)@app.route('/')
def hello():return "Hello Docker World!"if __name__ == '__main__':app.run(host='0.0.0.0', port=5000)

这段代码非常简单,我们导入了 Flask 框架,创建了一个 Flask 应用实例,然后定义了一个路由 /,当访问这个路由时,会返回一个简单的字符串。最后,我们通过 app.run 方法启动了这个应用,并将其监听在 0.0.0.0:5000 上,这样容器内的服务就能监听所有网络接口,而不仅仅是本地环回地址。

2. Dockerfile 配置

接下来,我们要在项目根目录创建一个 Dockerfile

# 使用轻量级 Python 基础镜像
FROM python:3.11-slim# 设置工作目录
WORKDIR /app# 代码到容器
COPY . .# 安装依赖(使用国内镜像加速)
RUN pip install --no-cache-dir -r requirements.txt# 暴露端口
EXPOSE 5000# 启动命令
CMD ["python", "app.py"]

这里面有几个关键的指令需要大家注意。首先是 FROM python:3.10-slim,我们使用的是官方的轻量级 Python 镜像,它的体积只有约 127MB,相比 centos 镜像更加高效,这对于我们构建和部署镜像来说可以节省很多时间和存储空间。然后是 --no-cache-dir 这个参数,它的作用是避免缓存依赖,确保每次构建时都能安装最新版本的依赖。EXPOSE 5000 声明了容器暴露的端口,不过需要注意的是,这只是一个声明,实际运行容器时还需要结合 -p 参数将容器端口映射到宿主机上。最后,CMD 指令定义了容器启动时要执行的命令。

3. 依赖管理

我们还需要创建一个 requirements.txt 文件,用来列出所有的依赖。

Flask==3.0.0

明确指定依赖的版本号是非常重要的,这样可以避免依赖冲突。建议大家在本地使用虚拟环境进行测试,确保所有依赖都能正常工作后,再进行打包。

4. 构建镜像

在项目目录下执行以下命令来构建镜像:

docker build --no-cache -t my-flask-app .

这里的 --no-cache 参数是强制重新构建镜像,避免缓存导致依赖未更新。

5. 运行容器

构建好镜像后,我们就可以启动容器并映射端口了。

docker run -d --name flask-container -p 8080:5000 my-flask-app

-d 参数表示后台运行容器,-p 8080:5000 是将宿主机的 8080 端口映射到容器的 5000 端口,--name 则是为容器指定一个名称,方便我们后续管理。

6. 测试访问

我们可以通过浏览器或终端来访问我们的应用:

curl http://localhost:8080
# 或
http://127.0.0.1:8080

如果一切正常,你应该能看到 Hello Docker World! 这个输出。

7. 调试与维护

在实际开发过程中,调试和维护是非常重要的。我们可以通过以下命令来查看容器的日志:

docker logs flask-container

如果需要进入容器的终端进行一些操作,可以使用:

docker exec -it flask-container /bin/bash

当我们修改了 app.py 中的代码后,需要重新执行 docker builddocker run 命令,或者使用 docker-compose 来简化这个流程。

完整高级优化实例

文件结构

下面我们来看一个更高级的优化实例,首先看一下文件结构:

.
├── docker-compose.yml      # 编排配置
├── Dockerfile              # 多阶段构建
├── app
│   ├── app.py             # Flask 主程序
│   └── requirements.txt   # 精确依赖
└── nginx└── nginx.conf         # 反向代理配置
Dockerfile(含多阶段构建)
# 构建阶段
FROM python:3.11-slim-bullseye AS builder
WORKDIR /build
COPY app/requirements.txt .
RUN pip install --user --no-cache-dir -r requirements.txt# 运行阶段
FROM python:3.11-slim-bullseye
WORKDIR /app# 安全配置
RUN adduser --disabled-password --gecos '' appuser && chown -R appuser:appuser /app
USER appuser# 依赖安装
# 这里要注意的是 /root/.local 不要写成 /home/appuser/.local,因为你的系统内没有这个目录
# 我是在 root 用户下执行的操作,所以是/root/.local
COPY --from=builder /root/.local /home/appuser/.local  
ENV PATH=/home/appuser/.local/bin:$PATH# 应用代码
COPY app .# 健康检查
HEALTHCHECK --interval=30s --timeout=5s CMD curl -f http://localhost:5000/health || exit 1
# 启动命令
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "--workers", "9", "--worker-class", "gevent", "app:app"]

这里使用了多阶段构建的方式,在构建阶段我们只安装依赖,然后在运行阶段将依赖复制过来,并使用非 root 用户运行应用,提高了容器的安全性。同时,我们还添加了健康检查,确保容器内的服务正常运行。启动命令使用了 gunicorn 作为 WSGI 服务器,并使用 gevent 作为工作类,提高了应用的并发性能。

app/app.py(含监控端点)
from flask import Flask
from prometheus_client import generate_latest, Counterapp = Flask(__name__)
REQUEST_COUNTER = Counter('http_requests_total', 'Total HTTP Requests')@app.route('/')
def hello():REQUEST_COUNTER.inc()return "Hello Production Docker World!"@app.route('/health')
def health():return "OK", 200@app.route('/metrics')
def metrics():return generate_latest()

在这个 app.py 中,我们添加了一些监控端点。/health 端点用于健康检查,/metrics 端点用于提供 Prometheus 监控数据,这样我们就能更好地监控应用的运行状态。

app/requirements.txt(精确版本控制)
Flask==3.0.0
gunicorn==21.2.0
gevent==23.9.1
prometheus-client==0.20.0

精确控制依赖的版本号可以避免因依赖版本不一致而导致的问题。

docker-compose.yml(生产编排)
version: '3.11'services:web:build: .ports:- "5000:5000"deploy:resources:limits:cpus: '2.0'memory: 1GBlogging:driver: "json-file"options:max-size: "100m"nginx:image: nginx:1.25ports:- "80:80"volumes:- ./nginx/nginx.conf:/etc/nginx/nginx.confdepends_on:- web

docker-compose.yml 是用于生产编排的,我们可以通过它来定义多个服务,并进行资源管控和日志配置。这里我们定义了 webnginx 两个服务,web 服务构建我们的 Flask 应用,nginx 服务作为反向代理,将请求转发到 web 服务上。

nginx/nginx.conf(反向代理配置)
worker_processes auto;events {worker_connections 1024;
}http {upstream flask {server web:5000;}server {listen 80;location / {proxy_pass http://flask;proxy_set_header Host $host;proxy_set_header X-Real-IP $remote_addr;}}
}

这个 nginx.conf 文件配置了反向代理,将所有请求转发到 web 服务的 5000 端口上。

部署流程
# 构建镜像
docker-compose build# 启动集群
docker-compose up -d# 验证部署
curl http://localhost/health

通过这几个简单的命令,我们就可以完成整个应用的部署和验证。

关键优化点说明

最后,我们来看一下这个高级优化实例的关键优化点:

优化方向实现方案
镜像体积多阶段构建(162MB 镜像)
并发性能Gunicorn + Gevent(9 workers)
安全基线非 root 用户运行 + 文件权限控制
可观测性Prometheus 监控端点 + 健康检查
资源管控CPU/内存限制 + 日志滚动策略

我们还进行了压力测试,所有参数均通过 wrk -t12 -c400 -d30s http://localhost/ 压力测试验证,QPS 为1125,可能是虚拟机的原因吧。

下面的几个版本的对比:

镜像组件镜像大小QPS
flask-app:v1Python:3.11 +Flask3.0138MB1000.95
flask-app:v2Python:3.11-alpine +Flask3.058.6MB899.78
flask-nginx-web:v1Python:3.11-slim-bullseye +Flask3.0+gunicorn21.2.0+
gevent23.9.1+prometheus-client0.20.0
162MB1125.04
flask-nginx-web:v2Python:3.11-alpine +Flask3.0+gunicorn21.2.0+
gevent23.9.1+prometheus-client0.20.0
92.7MB1049.89

alpin镜像确实小,从QPS的角度来看,并不是什么都用alpin镜像就好的。

总结

今天我们学习了如何基于 Docker 部署 Python Flask 应用,从简单的实例到高级优化实例,希望大家能对 Docker 的使用有更深入的理解。在实际开发中,大家可以根据自己的需求进行调整和优化,充分发挥 Docker 的优势。如果大家有任何问题,欢迎随时提问。谢谢大家!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/73414.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Linux find 命令完全指南

find 是 Linux 系统最强大的文件搜索工具&#xff0c;支持 嵌套遍历、条件筛选、执行动作。以下通过场景分类解析核心用法&#xff0c;涵盖高效搜索、文件管理及高级技巧&#xff1a; 一、基础搜索模式 1. 按文件名搜索&#xff08;精确/模糊匹配&#xff09; <BASH> f…

【量化策略】趋势跟踪策略

【量化策略】趋势跟踪策略 &#x1f680;量化软件开通 &#x1f680;量化实战教程 技术背景与应用场景 在金融市场中&#xff0c;趋势跟踪策略是一种基于市场趋势进行交易的量化投资方法。该策略的核心思想是“顺势而为”&#xff0c;即认为市场价格会沿着一定的方向持续移…

AI自动化、资本短视、三输与破局

当前AI应用中的一个深层矛盾&#xff1a;工程师使用AI将很专业的任务变成小白可以操作的工作&#xff0c;然后资本方给小白很少的钱把工程师裁掉了&#xff0c;然而小白不懂底层&#xff0c;出问题几乎无法修复。由此&#xff0c;技术普及与专业能力之间的断层引发了"三输…

Python数据分析之数据可视化

Python 数据分析重点知识点 本系列不同其他的知识点讲解&#xff0c;力求通过例子让新同学学习用法&#xff0c;帮助老同学快速回忆知识点 可视化系列&#xff1a; Python基础数据分析工具数据处理与分析数据可视化机器学习基础 四、数据可视化 图表类型与选择 根据数据特…

简述计算机网络中的七层模型和四层模型

在计算机网络中&#xff0c;网络协议栈的设计通常采用分层结构来处理不同的通信任务。常见的分层结构有OSI七层模型和TCP/IP四层模型。虽然它们的层次数量不同&#xff0c;但本质上都在解决如何有效地进行计算机间通信。本文将分别介绍这两种结构的功能和各层的协议。 一、OSI七…

2025高频面试算法总结篇【持续更新中】

文章目录 递归&回溯131. 分割回文串面试题 08.12. 八皇后 动态规划72编辑距离5. 最长回文子串279. 完全平方数300. 最长递增子序列 递归&回溯 131. 分割回文串 回溯思路&#xff1a; 临界条件&#xff1a; if (start s.length) > 保存 循环遍历这个字串 for (int…

【大模型学习】第二十二章 什么是对抗生成网络

目录 一、背景介绍 二、生活化例子说明什么是对抗生成网络 三、技术细节详解 &#xff08;一&#xff09;基本概念 &#xff08;二&#xff09;训练机制 &#xff08;三&#xff09;损失函数 一、背景介绍 对抗生成网络&#xff08;Generative Adversarial Networks, GANs…

摄像头模块ISP处理流程

摄像头模块的ISP&#xff08;图像信号处理器&#xff09;处理流程是对图像传感器输出的原始信号进行系统性优化的过程&#xff0c;主要分为以下关键步骤及对应功能模块&#xff1a; 一、原始信号输入与预处理 ‌传感器信号捕获‌ CMOS/CCD传感器将光信号转换为模拟电信号&…

linux系统安装和激活conda

安装 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.shbash ./Miniconda3-latest-Linux-x86_64.sh回车到最后按照输入yes&#xff0c;之后按提示操作。 激活 conda activate如果没有反应或者返回&#xff1a; bash: conda: command not found则…

(全)2024下半年真题 系统架构设计师 综合知识 答案解析02

系统架构设计师第二版教程VIP课程https://edu.csdn.net/course/detail/40283 面向对象技术 在UML用例图中&#xff0c;参与者之间存在 关系。 A. 聚合 B. 包含 C. 继承 D. 扩展 答案&#xff1a;C 解析&#xff1a;用例图描述了一组用例、参与者以及它们之间的关系…

【学习笔记】《逆向工程核心原理》03.abex‘crackme-2、函数的调用约定、视频讲座-Tut.ReverseMe1

文章目录 abexcrackme-21. Visual Basic文件的特征1.1. VB专用引擎1.2. 本地代码与伪代码1.3. 事件处理程序1.4. 未文档化的结构体 2. 开始调试2.1. 间接调用2.2. RT_MainStruct结构体2.3. ThunRTMain()函数 3. 分析crackme3.1. 检索字符串3.2. 查找字符串地址3.3. 生成Serial的…

深入解析Go语言Channel:源码剖析与并发读写机制

文章目录 Channel的内部结构Channel的创建过程有缓冲Channel的并发读写机制同时读写的可能性发送操作的实现接收操作的实现 并发读写的核心机制解析互斥锁保护环形缓冲区等待队列直接传递优化Goroutine调度 实例分析&#xff1a;有缓冲Channel的并发读写性能优化与最佳实践缓冲…

初识Linux(14)Ext系列⽂件系统

之前谈论的都是已打开文件在操作系统的中的管理&#xff0c;但是还有更多的文件没有被打开&#xff0c;被存在磁盘中&#xff0c;如何管理这些磁盘中的文件&#xff0c;就是本篇的学习目标。 目录 1.理解硬件 磁盘结构 扇区的读写 CHS地址定位 磁盘的逻辑结构 2. 引⼊⽂件…

电机控制常见面试问题(十二)

文章目录 一.电机锁相环1.理解锁相环2.电机控制中的锁相环应用3.数字锁相环&#xff08;DPLL&#xff09; vs 模拟锁相环&#xff08;APLL&#xff09;4.锁相环设计的关键技术挑战5.总结 二、磁链观测1.什么是磁链&#xff1f;2.为什么要观测磁链&#xff1f;3.怎么观测磁链&am…

Android `%d` 与 `1$%d` 格式化的区别

在 Android 开发中&#xff0c;我们经常需要对字符串进行格式化处理&#xff0c;比如动态填充数字、日期、字符等。 其中&#xff0c;%d 和 1$%d 都是格式化占位符&#xff0c;但它们在使用上有一些不同。 本文将详细解析这两者的区别&#xff0c;并结合 Kotlin 代码示例帮助你…

SpringBoot中使用kaptcha生成验证码

简介 kaptcha是谷歌开源的简单实用的验证码生成工具。通过设置参数&#xff0c;可以自定义验证码大小、颜色、显示的字符等等。 Maven引入依赖 <!-- https://mvnrepository.com/artifact/pro.fessional/kaptcha --><dependency><groupId>pro.fessional<…

如何在PHP中实现数据加密与解密:保护敏感信息

如何在PHP中实现数据加密与解密&#xff1a;保护敏感信息 在现代Web开发中&#xff0c;数据安全是一个至关重要的议题。无论是用户的个人信息、支付数据&#xff0c;还是其他敏感信息&#xff0c;都需要在存储和传输过程中进行加密&#xff0c;以防止数据泄露和恶意攻击。PHP作…

单元测试、系统测试、集成测试、回归测试的步骤、优点、缺点、注意点梳理说明

单元测试、系统测试、集成测试、回归测试的梳理说明 单元测试 步骤&#xff1a; 编写测试用例&#xff0c;覆盖代码的各个分支和边界条件。使用测试框架&#xff08;如JUnit、NUnit&#xff09;执行测试。检查测试结果&#xff0c;确保代码按预期运行。修复发现的缺陷并重新测…

C++能力测试题

以下是一些C能力测试题&#xff0c;涵盖了从基础语法到高级特性的多个方面&#xff1a; 选择题 1. 下面关于RTTI的说法&#xff0c;正确的是&#xff1f; A. 使用typeid前必须包含<type_info>头文件。 B. typeid只能用于多态类型或表达式。 C. typeid可以用于不完整类型…

模拟类似 DeepSeek 的对话

以下是一个完整的 JavaScript 数据流式获取实现方案&#xff0c;模拟类似 DeepSeek 的对话式逐段返回效果。包含前端实现、后端模拟和详细注释&#xff1a; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><titl…