Flask+Redis应用Docker部署启动报IndexError: pop from empty list排查
问题原因
- Redis访问地址错误:Dockerfile中默认配置的
REDIS_HOST=127.0.0.1指向Web容器自身的环回地址,而Redis服务运行在独立的容器中,Docker Compose默认桥接网络下需要通过服务名redis作为域名才能访问Redis服务,当前配置下Web容器完全无法连通Redis,导致连接池无可用连接,抛出IndexError: pop from empty list错误。 - 端口参数异常:
os.environ.get('REDIS_PORT')获取的环境变量为字符串类型,而redis.Redis的port参数要求传入整数,未做类型转换会触发参数校验错误;如果运行时环境变量未正确加载,还会返回None,直接触发日志中的NoneType报错。
解决方案
- 修改docker-compose.yml配置,传入正确的环境变量
在web服务下新增environment字段,覆盖默认的Redis连接配置,指向redis服务:
version: "3" services: web: build: . container_name: "python_app" ports: - "8000:8000" depends_on: - redis # 新增以下环境变量配置 environment: - REDIS_HOST=redis - REDIS_PORT=6379 redis: image: "redis:alpine" container_name: "redis" ports: - "6379:6379"
- 修改Flask代码,优化Redis连接逻辑
将端口参数转为整数类型,同时添加默认值兜底,避免环境变量读取失败导致的None报错:
import os import redis from flask import Flask app = Flask(__name__) redis = redis.Redis( host=os.environ.get('REDIS_HOST', '127.0.0.1'), password=None, # 端口转int,添加默认值兜底 port=int(os.environ.get('REDIS_PORT', 6379)), db=0, # 可选添加连接超时配置,避免无限等待 socket_connect_timeout=3 )
- 可选优化:解决服务启动顺序问题
depends_on仅控制容器启动顺序,不保证Redis服务完全初始化完成后再启动Web服务,可添加启动检测逻辑避免偶发连接失败:
- 首先修改Dockerfile,安装网络检测工具:
ARG PYTHON_VERSION=3.7-alpine FROM python:${PYTHON_VERSION} # 新增安装netcat RUN apk add --no-cache netcat-openbsd ENV REDIS_HOST 127.0.0.1 \ REDIS_PORT 6379 COPY requirements.txt . RUN pip install -r requirements.txt COPY . . CMD ["gunicorn", "-w", "4", "-b", "0.0.0.0:8000", "main:app"]
- 然后在docker-compose.yml的web服务下修改启动命令,等待Redis就绪后再启动服务:
command: sh -c "until nc -z redis 6379; do echo '等待Redis服务启动...'; sleep 1; done; gunicorn -w 4 -b 0.0.0.0:8000 main:app"
修改完成后重新执行docker-compose up --build即可正常启动。
内容的提问来源于stack exchange,提问作者n00
相关产品推荐
相关产品推荐

