Docker部署Flask后端遇uWSGI报错:未找到Python应用
问题描述
执行docker-compose -f dev.yml up启动服务后,前端运行正常,但所有后端请求都返回500状态码。相关错误日志显示uWSGI无法加载Python应用。
文件结构
nginx `-- default.conf mysql client server |-- app | |-- db | |-- lib | |-- __init__.py `-- app.ini `-- dev.Dockerfile `-- main.py `-- requirements.txt dev.yml
各文件内容
app.ini
[uwsgi] wsgi-file: /app/main.py uid = www-data gid = www-data socket = :5555 processes = 1 threads = 1 master = true chmod-socket = 660 vacuum = true callable = app die-on-term = true
后续添加了logto = %n.log用于输出日志
main.py
from app import create_app app = create_app() if __name__ == '__main__': app.run('0.0.0.0', 5000, False)
后端dev.Dockerfile
FROM python:3.9.16 WORKDIR /app COPY requirements.txt . RUN /usr/local/bin/python -m pip install --upgrade pip RUN /usr/local/bin/python -m pip install -r requirements.txt RUN cd /app ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 CMD ["uwsgi", "app.ini"]
app/init.py
#!/usr/bin/python import os from datetime import timedelta from flask import Flask, jsonify from app.db import db, mm from app.resourses import initialize_routes from app.resourses.auth import AuthError from app.error_handeler import handler from app.lib import get_db_string from dotenv import load_dotenv from flask_cors import CORS from app.db.models import get_user_by_id from app.lib import set_default_companies BASE_DIR = os.path.abspath(os.path.dirname(__file__)) if os.environ.get('ENV') == 'development': load_dotenv(f'{os.getcwd()}/.env.dev', override=True) else: load_dotenv(f'{os.getcwd()}/.env', override=True) def create_app(): api = Flask(__name__) api.config['JWT_PRIVATE_KEY'] = os.environ.get("PRIVATE_KEY") api.config['JWT_PUBLIC_KEY'] = os.environ.get("PUB_KEY") api.config["JWT_SECRET_KEY"] = os.environ.get("JWT_SECRET") api.config["JWT_HEADER_NAME"] = "access_token" api.config["JWT_HEADER_TYPE"] = "" api.config["JWT_TOKEN_LOCATION"] = ["headers", "cookies", "json"] api.config["JWT_COOKIE_SECURE"] = os.environ.get('FLASK_ENV') == 'production' api.config['PROPAGATE_EXCEPTIONS'] = True api.config["JWT_ACCESS_TOKEN_EXPIRES"] = timedelta(minutes=1) api.config["JWT_REFRESH_TOKEN_EXPIRES"] = timedelta(days=90) api.config['JWT_ACCESS_COOKIE_PATH'] = '/api/' api.config['JWT_REFRESH_COOKIE_PATH'] = '/token/refresh' api.config['JWT_ACCESS_COOKIE_NAME'] = 'access_token' api.config['JWT_REFRESH_COOKIE_NAME'] = 'refresh_token' api.config['JWT_COOKIE_CSRF_PROTECT'] = False api.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = False api.config["PROPAGATE_EXCEPTIONS"] = True api.config['SQLALCHEMY_DATABASE_URI'] = get_db_string() api.config['SQLALCHEMY_ECHO'] = True api.config['SQLALCHEMY_ENGINE_OPTIONS'] = { 'pool_size': 100, } api.config['SQLALCHEMY_POOL_SIZE'] = 100 api.config['SQLALCHEMY_POOL_RECYCLE'] = 280 api.secret_key = os.environ.get('FLASK_SECRET') db.init_app(api) mm.mm.init_app(api) with api.app_context(): db.create_all() set_default_companies() handler(api) initialize_routes(api) CORS(api) api.config['TESTING'] = os.environ.get("TEST_MODE", default=False) @api.errorhandler(AuthError) def handle_auth_error(ex): response = jsonify(ex.error) response.status_code = ex.status_code return response return api if __name__ == '__main__': create_app().run(port=5000, debug=True)
dev.yml
version: "3.7" services: nginx: build: context: ./nginx dockerfile: ./dev.Dockerfile container_name: nginx networks: - nginx_network restart: always depends_on: - backend ports: - "80:80" extra_hosts: - "host.docker.internal:host-gateway" volumes: - ./nginx/default.conf:/etc/nginx/conf.d/default.conf - ./client/build:/usr/share/nginx/html db: container_name: db build: ./mysql restart: always command: '--authentication_policy=mysql_native_password' healthcheck: test: [ "CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "--silent" ] interval: 3s retries: 5 start_period: 30s networks: mysql_net: aliases: - db ports: - "3306:3306" volumes: - ./data/data_volume:/var/lib/mysql backend: build: context: ./server dockerfile: ./dev.Dockerfile container_name: server restart: always networks: mysql_net: aliases: - server nginx_network: aliases: - server links: - db depends_on: - db env_file: - ./server/.env ports: - "5555:5555" volumes: - ./server:/app adminer: container_name: adminer image: adminer restart: always networks: mysql_net: aliases: - adminer nginx_network: aliases: - adminer ports: - "8080:8080" volumes: data_volume: driver: local networks: nginx_network: driver: bridge mysql_net: driver: bridge
Nginx default.conf
underscores_in_headers on; server { listen 0.0.0.0:80; server_name localhost; location /api { include uwsgi_params; add_header Content-Type application/json; uwsgi_pass server:5555; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_set_header Host $host; proxy_cache_bypass $http_upgrade; proxy_read_timeout 300s; proxy_connect_timeout 75s; } location /adminer { proxy_set_header X-Forwarded-Prefix "/adminer"; proxy_pass http://adminer:8080; } location ~* \.(?:css|js|json)$ { root /usr/share/nginx/html; try_files $uri $uri/; } location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html =404; } }
错误日志
Docker Compose启动日志片段
db | 2022-12-15T22:37:45.439021Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock db | 2022-12-15T22:37:45.439178Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.28' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL. server | --- no python application found, check your startup logs for errors --- server | [pid: 7|app: -1|req: -1/1] 172.19.0.1 () {64 vars in 1258 bytes} [Thu Dec 15 22:45:44 2022] POST /api/users/login => generated 21 bytes in 0 msecs (HTTP/1.1 500) 2 headers in 83 bytes (0 switches on core 0) nginx | 172.19.0.1 - - [15/Dec/2022:22:45:44 +0000] "POST /api/users/login HTTP/1.1" 500 32 "http://localhost/login" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36" "-"
uWSGI日志(app.log)
*** Starting uWSGI 2.0.21 (64bit) on [Fri Dec 16 18:47:11 2022] *** compiled with version: 10.2.1 20210110 on 15 December 2022 21:55:56 os: Linux-5.15.49-linuxkit #1 SMP Tue Sep 13 07:51:46 UTC 2022 nodename: 5338311c006d machine: x86_64 clock source: unix pcre jit disabled detected number of CPU cores: 6 current working directory: /app detected binary path: /usr/local/bin/uwsgi setgid() to 33 setuid() to 33 your memory page size is 4096 bytes detected max file descriptor number: 1048576 lock engine: pthread robust mutexes thunder lock: disabled (you can enable it with --thunder-lock) uwsgi socket 0 bound to TCP address :5555 fd 3 Python version: 3.9.16 (main, Dec 8 2022, 02:40:11) [GCC 10.2.1 20210110] Python main interpreter initialized at 0x55569cd5a090 python threads support enabled your server socket listen backlog is limited to 100 connections your mercy for graceful operations on workers is 60 seconds mapped 145840 bytes (142 KB) for 1 cores *** Operational MODE: single process *** *** no app loaded. going in full dynamic mode *** *** uWSGI is running in multiple interpreter mode *** spawned uWSGI master process (pid: 1) spawned uWSGI worker 1 (pid: 7, cores: 1) --- no python application found, check your startup logs for errors --- [pid: 7|app: -1|req: -1/1] 172.19.0.1 () {64 vars in 1239 bytes} [Fri Dec 16 18:47:51 2022] POST /api/users/login => generated 21 bytes in 1 msecs (HTTP/1.1 500) 2 headers in 83 bytes (0 switches on core 0)
解决建议
1. 验证Flask应用能否正常启动
进入后端容器直接运行main.py,排查应用初始化时的错误:
docker exec -it server bash python main.py
如果启动失败,根据终端输出的错误信息修复(比如依赖缺失、环境变量错误、数据库连接失败等)。
2. 修复Dockerfile代码复制逻辑
当前后端Dockerfile仅复制了requirements.txt,未复制main.py、app.ini和app目录。虽然dev.yml挂载了宿主机目录,但镜像本身缺少文件可能导致加载异常,修改Dockerfile:
FROM python:3.9.16 WORKDIR /app # 复制所有代码文件 COPY . . RUN /usr/local/bin/python -m pip install --upgrade pip RUN /usr/local/bin/python -m pip install -r requirements.txt ENV PYTHONDONTWRITEBYTECODE 1 ENV PYTHONUNBUFFERED 1 CMD ["uwsgi", "app.ini"]
3. 检查环境变量加载情况
app/__init__.py根据ENV变量加载不同的.env文件,需确认:
.env文件中是否设置了ENV=development,否则会加载.env而非.env.dev,若配置缺失会导致应用初始化失败- 进入容器查看环境变量是否正确加载:
docker exec -it server env
4. 排查数据库初始化异常
create_app()中执行db.create_all()和set_default_companies(),若数据库连接失败会导致app对象无法创建。临时修改main.py添加异常捕获:
from app import create_app import traceback try: app = create_app() print("App created successfully") except Exception as e: print(f"Failed to create app: {e}") traceback.print_exc() if __name__ == '__main__': app.run('0.0.0.0', 5000, False)
重启容器后查看日志,定位具体错误。
5. 增强uWSGI调试日志
在app.ini中添加调试配置,获取更详细的加载日志:
[uwsgi] wsgi-file: /app/main.py uid = www-data gid = www-data socket = :5555 processes = 1 threads = 1 master = true chmod-socket = 660 vacuum = true callable = app die-on-term = true logto = %n.log # 新增调试配置 log-level = debug py-autoreload = 1
内容的提问来源于stack exchange,提问作者Oleg Dudkin
相关产品推荐
相关产品推荐

