You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker部署Flask天气服务请求返回404错误,如何排查解决?

问题描述

我开发了一个将在Docker中运行的Python脚本,脚本使用Flask框架调用OpenWeatherMap API获取天气数据。脚本、Dockerfile、依赖文件如下:

Python脚本(app.py)

from flask import Flask
import requests

app = Flask(__name__)
api_key = "308b62e9a346baf4145ea2f25ecf480e"
@app.route('/')
def index():
    return 'App Works!'

@app.route('/<string:city>/')
def weather_by_city(city):
    url=f'http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}'
   
    response = requests.get(url)
    if response.status_code == 200:
        data = response.json()
        temp = (data['main']['temp']-273.15)
    # Round the temperature to two decimal places.
        rounded_temp = round(temp, 2)

        print(f'Temperature: {rounded_temp} Celsius')
        desc = data['weather'][0]['description']

        print(f'Description: {desc}')

    else:
        print('Error fetching weather data')

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)

Dockerfile

FROM python:3
ENV PYTHONUNBUFFERED 1
RUN mkdir /app
WORKDIR /app
COPY requirements.txt /app
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
COPY . /app
EXPOSE 5000
CMD [ "python", "app.py"]

requirements.txt

certifi==2019.9.11
chardet==3.0.4
Click==7.0
Flask==1.1.1
idna==2.8
itsdangerous==1.1.0
Jinja2==2.10.3
MarkupSafe==1.1.1
requests==2.31.0
urllib3==2.0.7
Werkzeug==0.16.0

我在包含上述文件的目录中执行以下命令构建并运行容器:

sudo docker build -t weather:v1 .
sudo docker run -dit --rm -p 5000:5000 --name weather weather:v1

容器确认处于运行状态,但执行curl http://0.0.0.0:5000/london请求时返回404 Not Found页面。而直接在Python环境中调用OpenWeatherMap API的请求则返回200状态码。请问哪里操作出错了?


问题原因与解决方法

核心错误点

  1. 路由定义的HTML转义问题:你在路由里写了@app.route('/&lt;string:city&gt;/'),这里的&lt;是HTML转义字符,Flask无法识别为路由变量的起始符号<,导致这个路由规则完全无效,所以任何匹配/城市名的请求都会返回404。
  2. 路由斜杠匹配不一致:路由末尾带/,但你请求的是/london(不带斜杠),即使路由规则正确,Flask默认会重定向到带斜杠的路径,但当前路由规则本身错误,这一步也无法生效。
  3. 视图函数无客户端响应:当前weather_by_city函数仅在容器控制台打印数据,没有向请求客户端返回任何响应内容,就算路由修复,客户端也会得到空响应或500错误。

修正后的Python脚本

from flask import Flask, jsonify
import requests

app = Flask(__name__)
api_key = "308b62e9a346baf4145ea2f25ecf480e"

@app.route('/')
def index():
    return 'App Works!'

# 修正路由的HTML转义字符,同时设置strict_slashes=False支持带/和不带/的请求
@app.route('/<string:city>', strict_slashes=False)
def weather_by_city(city):
    url = f'http://api.openweathermap.org/data/2.5/weather?q={city}&appid={api_key}'
   
    response = requests.get(url)
    if response.status_code == 200:
        data = response.json()
        temp = (data['main']['temp'] - 273.15)
        rounded_temp = round(temp, 2)
        desc = data['weather'][0]['description']
        
        # 向客户端返回JSON格式的响应数据
        return jsonify({
            'city': city,
            'temperature_celsius': rounded_temp,
            'description': desc
        })
    else:
        # 返回错误信息及对应状态码
        return jsonify({'error': 'Error fetching weather data'}), response.status_code

if __name__ == '__main__':
    app.run(host="0.0.0.0", port=5000)

后续操作

修正脚本后,重新构建并运行容器:

sudo docker build -t weather:v2 .
sudo docker run -dit --rm -p 5000:5000 --name weather weather:v2

现在执行curl http://0.0.0.0:5000/london就能得到正常的JSON格式天气响应了。


内容的提问来源于stack exchange,提问作者GoT GOt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 05:55:00