Docker中Python脚本CMD启动CPU占100%,手动启动正常问题咨询
我来帮你拆解下这个诡异的问题——同样的脚本,用Dockerfile的CMD启动就CPU拉满到100%,手动执行却一切正常,大概率是这几个细节出了问题:
1. 环境变量配置错误(最可能的元凶)
先看你的docker-compose.yml里consumer服务的环境变量配置:
- REDIS_HOST = redis
这里有个非常容易忽略的错误:环境变量的等号两边不能有空格!Docker要求环境变量必须写成KEY=VALUE的格式,空格会被解析成变量名或值的一部分。
这种错误会导致容器里实际生效的环境变量是:
- 变量名:
REDIS_HOST(末尾带空格) - 变量值:
redis(开头带空格)
你的Python脚本里如果用os.getenv("REDIS_HOST")读取,会直接得到None。如果脚本里处理Redis连接失败的逻辑是无限循环重试且没有添加等待延迟(比如一个while循环不断尝试连接,没加time.sleep()),那脚本就会疯狂占用CPU循环重试,直接跑到100%。
而你手动执行时,大概率是在容器里手动设置了正确的REDIS_HOST=redis,或者临时修改了脚本里的Redis地址,所以能正常连接Redis,CPU使用率自然就降下来了。
修复方法:把docker-compose里的环境变量改成正确格式:
environment: - REDIS_HOST=redis
然后重启容器即可。
2. 进程启动上下文的细微差异
Docker用CMD ['python', 'script.py']这种exec格式启动进程时,不会启动shell环境;而你用docker exec进入容器手动执行时,是在shell环境下运行的。
虽然理论上环境变量应该一致,但如果你的脚本依赖某些shell初始化的变量(比如PATH的细微调整),或者脚本里有依赖shell的逻辑,也可能导致运行差异。不过这个概率比第一个原因低很多,优先排查环境变量问题。
3. 快速验证方法
你可以先进入运行中的consumer容器,查看环境变量是否正确:
docker exec <你的consumer容器ID> printenv
如果看不到正确的REDIS_HOST=redis,反而看到带空格的变量,那就能实锤是环境变量的问题了。
另外,也可以查看容器日志,看看是不是一直在输出“Redis连接失败”的重试信息:
docker logs <你的consumer容器ID>
如果日志里全是连接失败的内容,那就能确认是无限重试循环导致的CPU跑满了。
内容的提问来源于stack exchange,提问作者Tom J Muthirenthi

