docker-compose实验案例之基于docker容器化部署下 Flask+Redis 访问计数功能的实现与调优

docker-compose实验案例之docker容器化部署下 Flask+Redis 访问计数功能的实现与调优

实验背景及其灵感:

​ 随着云计算和微服务架构的普及,应用的部署和运维模式发生了根本性变化。传统的 "单机部署" 模式难以满足微服务多组件、多环境一致性的需求,而 Docker 容器技术通过 "打包应用及其依赖" 实现了环境隔离与快速交付,Docker-Compose 则进一步解决了多容器服务的编排、依赖管理和网络配置问题,成为中小型微服务项目快速落地的核心工具。

​ 在 Web 应用开发中,"访问次数统计" 是典型的轻量级业务场景,既涉及 Web 服务的对外暴露,也涉及缓存服务的数据持久化与原子操作。选择 Flask(轻量级 Python Web 框架)+ Redis(高性能缓存数据库)的组合,能以极简的代码实现核心功能;同时,该场景天然适配容器化部署的需求 ------Web 服务和缓存服务需独立运行、相互依赖,且要求环境一致性(避免 "本地运行正常、部署出错" 的问题),成为容器编排入门的经典实践场景;

接下来我将通过 flask 接合 redis 完成访问次统计的功能的实验:

1.实验环境搭建

1.创建目录,并编写python应用程序

复制代码
[root@localhost ~]# mkdir myapp
[root@localhost ~]# cd myapp/

[root@localhost myapp]# vim app.py

import time
import redis
from flask import Flask

app = Flask(__name__)

cache = redis.Redis(host='redis', port=6379)
# 连接Redis服务:host为"redis"(对应docker-compose中redis服务名,容器间可通过服务名访问),端口6379
def get_hit_count():      # 设置重试次数最多为5,避免Redis启动延迟导致连接失败
    retries = 5
    while True:
        try:
            return cache.incr('hits')   # 原子操作:给Redis中"hits"键的值+1,返回最新值(实现计数)
        except redis.exceptions.ConnectionError as exc:
            if retries == 0:
                raise exc
            retries -= 1
            time.sleep(0.5)    # 重试逻辑:剩余重试次数>0时,等待0.5秒后重试;次数为0时抛出异常

@app.route('/')          # 定义根路由(访问/路径时触发)
def hello():
    count = get_hit_count()    # 获取当前访问次数
    return 'Hello World! I have been seen {} times.\n'.format(count)   # 返回带计数的响应内容

# 启动Flask服务:监听所有网卡(0.0.0.0),开启调试模式
if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)
    
#关键逻辑:Redis 连接的host='redis'是核心:docker-compose会为编排的服务创建专属网络,容器间可通过服务名(如redis)直接访问,无需手动配置 IP;
重试逻辑:解决depends_on仅保证启动顺序、不保证 Redis 服务就绪的问题(Redis 启动可能慢于 Web 服务,首次连接会失败,重试可规避);
cache.incr('hits'):Redis 原子递增操作,避免并发访问时计数错误。

2.安装程序并生成依赖库文件;

复制代码
[root@localhost myapp]# pip install redis
Collecting redis
  Downloading redis-7.0.1-py3-none-any.whl (339 kB)
     |████████████████████████████████| 339 kB 400 kB/s            
Collecting async-timeout>=4.0.3
  Downloading async_timeout-5.0.1-py3-none-any.whl (6.2 kB)
Installing collected packages: async-timeout, redis
Successfully installed async-timeout-5.0.1 redis-7.0.1
WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv

[root@localhost myapp]# pip freeze > requirements.txt

# 查看所有的依赖库
[root@localhost myapp]# cat requirements.txt 
blinker==1.9.0
click==8.3.1
Flask==3.1.2
itsdangerous==2.2.0
Jinja2==3.1.6
MarkupSafe==3.0.3
redis==7.1.0
Werkzeug==3.1.5
2.镜像构建

2.1编写dockerfile

复制代码
[root@localhost myapp]# vim Dockerfile
文件内容如下:

FROM python:3.14-alpine

WORKDIR /code

COPY . .

RUN pip install --no-cache-dir -r requirements.txt

EXPOSE 5000

CMD ["python", "app.py"]


#关键逻辑:选择alpine版本基础镜像:大幅降低镜像体积;设置容器内工作目录(后续命令均在该目录执行);COPY . .:将宿主机myapp目录下的app.py、requirements.txt等文件复制到容器内;安装依赖:--no-cache-dir 不缓存安装包,减少镜像体积;-r 读取requirements.txt的依赖清单;声明容器暴露的端口5000;容器启动命令:执行app.py,启动Flask服务。

2.2编写.dockerignore

复制代码
[root@localhost myapp]# vim .dockerignore
文件内容如下:

Dockerfile

2.3查看项目结构

复制代码
[root@localhost myapp]# ll
total 12
-rw-r--r--. 1 root root 582 Feb  1 15:57 app.py
-rw-r--r--. 1 root root 140 Feb  1 16:10 Dockerfile
-rw-r--r--. 1 root root 122 Feb  1 16:00 requirements.txt
3.定义服务

3.1编写docker-compose.yml

复制代码
[root@localhost myapp]# vim docker-compose.yml
文件内容如下:
services:
  web:
    build: .        # 构建规则:基于当前目录的Dockerfile构建镜像
    ports:
      - 5000:5000	# 端口映射:宿主机5000端口 -> 容器5000端口
    depends_on:		# 依赖关系:启动web前先启动redis
      - redis
  redis:			# 使用官方的redis alpine镜像
    image: redis:alpine

3.2启动并运行容器

复制代码
[root@localhost myapp]# docker-compose up -d
[+] Building 1.0s (11/11) FINISHED    
...
[+] up 4/4
 ✔ Image myapp-web         Built                                                                       1.1s
 ✔ Network myapp_default   Created                                                                     0.0s
 ✔ Container myapp-redis-1 Created                                                                     0.1s
 ✔ Container myapp-web-1   Created                                                                     0.0s

3.3查看运行容器

复制代码
[root@localhost myapp]# docker-compose ps
NAME            IMAGE          COMMAND                  SERVICE   CREATED              STATUS              PORTS
myapp-redis-1   redis:alpine   "docker-entrypoint.s..."   redis     About a minute ago   Up About a minute   6379/tcp
myapp-web-1     myapp-web      "python app.py"          web       About a minute ago   Up About a minute   0.0.0.0:5000->5000/tcp, [::]:5000->5000/tcp

3.4访问测试

复制代码
[root@localhost myapp]#  curl 192.168.110.148:5000
Hello World! I have been seen 1 times.
[root@localhost myapp]#  curl 192.168.110.148:5000
Hello World! I have been seen 2 times.
[root@localhost myapp]#  curl 192.168.110.148:5000
Hello World! I have been seen 3 times.
4.项目优化

4.1添加数据卷

修改docker-compose.yml文件

复制代码
[root@localhost myapp]# vim docker-compose.yml
文件内容如下:
services:
  web:
    build: .
    ports:
      - 5000:5000
    depends_on:
      - redis
    volumes:				#核心优化点,将宿主机myapp目录挂载到容器/code目录
      - .:/code
  redis:
    image: redis:alpine
    
#优化逻辑:将宿主机myapp目录挂载到容器/code目录,宿主机修改app.py后,容器内的代码会实时同步;无需重新构建镜像、重启容器,即可看到代码修改后的效果(Flask 调试模式会自动重载代码)。

4.2重启docker-compose并修改宿主机中的代码

复制代码
[root@localhost myapp]# docker-compose up -d
[root@localhost myapp]# vim app.py
修改内容如下:
@app.route('/')
def hello():
    count = get_hit_count()
    return 'Hello World! I am along! I have been seen {} times.\n'.format(count)
#修改访问回复,进行重新测试访问

4.3访问测试

复制代码
[root@localhost myapp]# curl 192.168.110.148:5000
Hello World! I am along! I have been seen 4 times.
[root@localhost myapp]# curl 192.168.110.148:5000
Hello World! I am along! I have been seen 5 times.
[root@localhost myapp]# curl 192.168.110.148:5000
Hello World! I am along! I have been seen 6 times.
[root@localhost myapp]# 
实验总结:

本实验以 "访问次数统计" 为业务载体,完整实现了从 "应用开发→依赖管理→镜像构建→多服务编排→功能验证→优化迭代" 的容器化部署全流程,最终达成以下目标:

  • 基于 Docker-Compose 实现 Flask Web 服务与 Redis 缓存服务的协同运行,容器间网络互通、依赖可控;
  • 实现访问次数的原子计数,验证 Redis 在轻量级数据存储场景的可用性;
  • 通过数据卷挂载优化开发流程,实现宿主机代码与容器内代码的实时同步,无需重复构建镜像。
学习心得:

​ 掌握容器化核心思想,理解 "镜像 - 容器" 的关系,以及 Dockerfile 如何将应用打包为标准化镜像;理解多容器编排逻辑,掌握 Docker-Compose 中servicesdepends_onportsvolumes等核心配置的作用,解决多服务的依赖、网络、数据同步问题;同时夯实基础组件使用能力:熟悉 Flask Web 框架的基础用法,以及 Redis 原子操作(incr)在计数场景的应用,理解缓存服务与 Web 服务的协同模式。

工程实践意义:

1.标准化部署流程:通过容器化消除 "开发环境与生产环境不一致" 的问题,降低部署门槛;

2.提升开发效率:数据卷挂载的优化方式,可复用于日常开发(如前端代码热更新、后端代码实时调试),减少 "改代码→构建镜像→重启容器" 的重复操作;

3.轻量化微服务落地:本实验是微服务架构的极简缩影,可扩展至更复杂的场景(如多 Web 节点负载均衡、Redis 集群、数据库服务编排),为中小型项目微服务改造提供参考。

相关推荐
维度攻城狮1 小时前
TrendRadar:搭建新闻热搜自动化推送工具,打破信息差
运维·自动化·trendradar
草木红1 小时前
docker 构建镜像时报 403 Forbidden
docker·容器
坚持就完事了1 小时前
Linux的用户
linux·运维·服务器
坚持学习前端日记1 小时前
AgentAi视频模型开发对接部署使用
前端·人工智能·python·flask·音视频
liulilittle2 小时前
Ubuntu 系统 libc6-dev 依赖冲突解决
linux·运维·服务器·ubuntu·shell
Wenhao.2 小时前
Docker 安装 Qdrant
运维·docker·容器
liulilittle2 小时前
Debian/Ubuntu 18.04 上安装 GLIBC 2.28 (2026)
linux·运维·服务器·开发语言·c++·ubuntu·debian
MMendex2 小时前
华为云项目实战day1
linux·服务器·nginx·华为云·ssh·负载均衡
不知名。。。。。。。。2 小时前
仿muduo库实现高并发服务器----通信链接管理Connection
运维·服务器·网络