{"id":442562,"date":"2026-04-12T12:44:59","date_gmt":"2026-04-12T04:44:59","guid":{"rendered":"https:\/\/idc.net\/help\/?p=442562"},"modified":"2026-03-28T12:46:31","modified_gmt":"2026-03-28T04:46:31","slug":"python-flask-fastapi%e5%ba%94%e7%94%a8%e9%83%a8%e7%bd%b2%e5%88%b0vps%ef%bc%9agunicornnginx%e5%8f%8d%e5%90%91%e4%bb%a3%e7%90%86%e5%ae%8c%e6%95%b4%e6%96%b9%e6%a1%88","status":"publish","type":"post","link":"https:\/\/idc.net\/help\/442562\/","title":{"rendered":"Python Flask\/FastAPI\u5e94\u7528\u90e8\u7f72\u5230VPS\uff1aGunicorn+Nginx\u53cd\u5411\u4ee3\u7406\u5b8c\u6574\u65b9\u6848"},"content":{"rendered":"<h2>\u4e3a\u4ec0\u4e48\u4e0d\u80fd\u76f4\u63a5\u7528 Flask \u5f00\u53d1\u670d\u52a1\u5668\u4e0a\u7ebf\uff1f<\/h2>\n<p>Flask \u548c FastAPI \u5185\u7f6e\u7684\u5f00\u53d1\u670d\u52a1\u5668\uff08<code>flask run<\/code> \u6216 <code>uvicorn main:app<\/code>\uff09\u53ea\u9002\u5408\u672c\u5730\u8c03\u8bd5\uff0c<strong>\u5355\u7ebf\u7a0b\u3001\u4e0d\u652f\u6301\u5e76\u53d1\u3001\u7f3a\u4e4f\u9519\u8bef\u6062\u590d\u673a\u5236<\/strong>\uff0c\u751f\u4ea7\u73af\u5883\u5fc5\u987b\u4f7f\u7528 Gunicorn\uff08WSGI\uff09\u6216 Uvicorn\uff08ASGI\uff09\u914d\u5408 Nginx \u53cd\u5411\u4ee3\u7406\u3002<\/p>\n<hr \/>\n<h2>\u4e00\u3001\u73af\u5883\u51c6\u5907<\/h2>\n<pre><code>sudo apt update\r\nsudo apt install python3 python3-pip python3-venv nginx -y\r\n\r\n# \u521b\u5efa\u9879\u76ee\u76ee\u5f55\r\nmkdir ~\/myapp &amp;&amp; cd ~\/myapp\r\n\r\n# \u521b\u5efa\u865a\u62df\u73af\u5883\r\npython3 -m venv venv\r\nsource venv\/bin\/activate\r\n\r\n# Flask \u9879\u76ee\u5b89\u88c5\u4f9d\u8d56\r\npip install flask gunicorn\r\n\r\n# FastAPI \u9879\u76ee\u5b89\u88c5\u4f9d\u8d56\r\n# pip install fastapi uvicorn[standard] gunicorn<\/code><\/pre>\n<hr \/>\n<h2>\u4e8c\u3001Flask \u5e94\u7528\u793a\u4f8b<\/h2>\n<pre><code>nano app.py<\/code><\/pre>\n<pre><code>from flask import Flask, jsonify\r\n\r\napp = Flask(__name__)\r\n\r\n@app.route('\/')\r\ndef index():\r\n    return jsonify({\"status\": \"ok\", \"message\": \"Hello from Flask!\"})\r\n\r\n@app.route('\/health')\r\ndef health():\r\n    return jsonify({\"status\": \"healthy\"})\r\n\r\nif __name__ == '__main__':\r\n    app.run()<\/code><\/pre>\n<hr \/>\n<h2>\u4e09\u3001Gunicorn \u542f\u52a8\u914d\u7f6e<\/h2>\n<p>\u521b\u5efa Gunicorn \u914d\u7f6e\u6587\u4ef6\uff1a<\/p>\n<pre><code>nano gunicorn.conf.py<\/code><\/pre>\n<pre><code># \u7ed1\u5b9a\u5730\u5740\uff08\u53ea\u76d1\u542c\u672c\u5730\uff0c\u7531 Nginx \u53cd\u5411\u4ee3\u7406\uff09\r\nbind = \"127.0.0.1:8000\"\r\n\r\n# worker \u6570\u91cf\uff1a\u63a8\u8350 CPU \u6838\u5fc3\u6570 \u00d7 2 + 1\r\nworkers = 3\r\n\r\n# \u6bcf\u4e2a worker \u7684\u7ebf\u7a0b\u6570\uff08Flask \u7528 sync worker\uff09\r\nthreads = 2\r\n\r\n# \u8bf7\u6c42\u8d85\u65f6\u65f6\u95f4\uff08\u79d2\uff09\r\ntimeout = 60\r\n\r\n# \u65e5\u5fd7\u914d\u7f6e\r\naccesslog = \"\/var\/log\/gunicorn\/access.log\"\r\nerrorlog = \"\/var\/log\/gunicorn\/error.log\"\r\nloglevel = \"info\"\r\n\r\n# \u8fdb\u7a0b\u540d\u79f0\r\nproc_name = \"myapp\"<\/code><\/pre>\n<pre><code># \u521b\u5efa\u65e5\u5fd7\u76ee\u5f55\r\nsudo mkdir -p \/var\/log\/gunicorn\r\nsudo chown youruser:youruser \/var\/log\/gunicorn\r\n\r\n# \u6d4b\u8bd5\u542f\u52a8\r\ngunicorn -c gunicorn.conf.py app:app<\/code><\/pre>\n<p>\u770b\u5230 <code>Booting worker with pid<\/code> \u7684\u8f93\u51fa\u8bf4\u660e\u542f\u52a8\u6210\u529f\u3002<\/p>\n<hr \/>\n<h2>\u56db\u3001FastAPI + Uvicorn \u914d\u7f6e\uff08\u5f02\u6b65\u6846\u67b6\uff09<\/h2>\n<pre><code>nano main.py<\/code><\/pre>\n<pre><code>from fastapi import FastAPI\r\n\r\napp = FastAPI()\r\n\r\n@app.get(\"\/\")\r\nasync def root():\r\n    return {\"message\": \"Hello from FastAPI!\"}\r\n\r\n@app.get(\"\/health\")\r\nasync def health():\r\n    return {\"status\": \"healthy\"}<\/code><\/pre>\n<p>FastAPI \u4f7f\u7528 Uvicorn worker\uff1a<\/p>\n<pre><code># gunicorn.conf.py for FastAPI\r\nbind = \"127.0.0.1:8000\"\r\nworkers = 3\r\nworker_class = \"uvicorn.workers.UvicornWorker\"\r\ntimeout = 60<\/code><\/pre>\n<pre><code>gunicorn -c gunicorn.conf.py main:app<\/code><\/pre>\n<hr \/>\n<h2>\u4e94\u3001systemd \u8fdb\u7a0b\u5b88\u62a4<\/h2>\n<pre><code>sudo nano \/etc\/systemd\/system\/myapp.service<\/code><\/pre>\n<pre><code>[Unit]\r\nDescription=My Python Web App\r\nAfter=network.target\r\n\r\n[Service]\r\nType=simple\r\nUser=youruser\r\nWorkingDirectory=\/home\/youruser\/myapp\r\nExecStart=\/home\/youruser\/myapp\/venv\/bin\/gunicorn -c gunicorn.conf.py app:app\r\nRestart=always\r\nRestartSec=5\r\nStandardOutput=journal\r\nStandardError=journal\r\n\r\n[Install]\r\nWantedBy=multi-user.target<\/code><\/pre>\n<pre><code>sudo systemctl daemon-reload\r\nsudo systemctl enable myapp\r\nsudo systemctl start myapp\r\nsudo systemctl status myapp<\/code><\/pre>\n<hr \/>\n<h2>\u516d\u3001Nginx \u53cd\u5411\u4ee3\u7406\u914d\u7f6e<\/h2>\n<pre><code>sudo nano \/etc\/nginx\/sites-available\/myapp<\/code><\/pre>\n<pre><code>server {\r\n    listen 80;\r\n    server_name your-domain.com;\r\n\r\n    location \/ {\r\n        proxy_pass http:\/\/127.0.0.1:8000;\r\n        proxy_http_version 1.1;\r\n        proxy_set_header Host $host;\r\n        proxy_set_header X-Real-IP $remote_addr;\r\n        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\r\n        proxy_set_header X-Forwarded-Proto $scheme;\r\n        proxy_read_timeout 60s;\r\n    }\r\n\r\n    # \u9759\u6001\u6587\u4ef6\u76f4\u63a5\u7531 Nginx \u63d0\u4f9b\uff0c\u4e0d\u7ecf\u8fc7 Python\r\n    location \/static\/ {\r\n        alias \/home\/youruser\/myapp\/static\/;\r\n        expires 30d;\r\n    }\r\n}<\/code><\/pre>\n<pre><code>sudo ln -s \/etc\/nginx\/sites-available\/myapp \/etc\/nginx\/sites-enabled\/\r\nsudo nginx -t &amp;&amp; sudo systemctl reload nginx<\/code><\/pre>\n<p>\u7528 Certbot \u7533\u8bf7 HTTPS \u8bc1\u4e66\uff1a<\/p>\n<pre><code>sudo certbot --nginx -d your-domain.com<\/code><\/pre>\n<hr \/>\n<h2>\u603b\u7ed3<\/h2>\n<p>Python Web \u5e94\u7528\u751f\u4ea7\u90e8\u7f72\u7684\u6807\u51c6\u67b6\u6784\uff1aGunicorn\/Uvicorn\uff08\u591a\u8fdb\u7a0b\u5e94\u7528\u670d\u52a1\u5668\uff09+ systemd\uff08\u8fdb\u7a0b\u5b88\u62a4\uff09+ Nginx\uff08\u53cd\u5411\u4ee3\u7406 + \u9759\u6001\u6587\u4ef6 + SSL\uff09\u3002\u8fd9\u5957\u67b6\u6784\u7a33\u5b9a\u6210\u719f\uff0c\u9002\u5408\u4ece\u5c0f\u578b API \u5230\u4e2d\u578b Web \u5e94\u7528\u7684\u5404\u79cd\u89c4\u6a21\u3002<\/p>\n<p><a title=\"\u9999\u6e2fVPS Python\u90e8\u7f72\" href=\"https:\/\/idc.net\/cloud-hk\/\">IDC.Net \u9999\u6e2f\u4e91\u670d\u52a1\u5668<\/a>\u9996\u6708 10 \u5143\u8d77\uff0cUbuntu 22.04 \u5f00\u7bb1\u5373\u7528\uff0cCN2 GIA \u76f4\u8fde\u5927\u9646\uff0c\u652f\u6301\u652f\u4ed8\u5b9d\u4ed8\u6b3e\uff0c\u9002\u5408 Python \u5e94\u7528\u7684\u751f\u4ea7\u90e8\u7f72\u3002<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u4e3a\u4ec0\u4e48\u4e0d\u80fd\u76f4\u63a5\u7528 Flask \u5f00\u53d1\u670d\u52a1\u5668\u4e0a\u7ebf\uff1f Flask \u548c FastAPI \u5185\u7f6e\u7684\u5f00\u53d1\u670d\u52a1\u5668\uff08flask  [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[202648,182397],"tags":[],"class_list":["post-442562","post","type-post","status-publish","format-standard","hentry","category-hkvps","category-python"],"_links":{"self":[{"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/posts\/442562","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/comments?post=442562"}],"version-history":[{"count":1,"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/posts\/442562\/revisions"}],"predecessor-version":[{"id":442563,"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/posts\/442562\/revisions\/442563"}],"wp:attachment":[{"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/media?parent=442562"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/categories?post=442562"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/idc.net\/help\/wp-json\/wp\/v2\/tags?post=442562"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}