1. Why Gunicorn and Nginx are Needed?¶
The built-in development server of Flask (flask run) is only suitable for local debugging. It does not support high concurrency and is insecure, making it unable to directly provide production-level services. In a production environment, two tools are typically required:
- Gunicorn: As a WSGI server, it runs the Flask application, handles client requests, and returns results (similar to an “application server”).
- Nginx: As a reverse proxy server, it manages static resources (e.g., images, CSS, JS), load balances, encrypts SSL, and forwards dynamic requests to Gunicorn (similar to a “gatekeeper + administrator”).
2. Preparation¶
Assume you have already installed Python and have a simple Flask application (e.g., app.py with the following content):
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
return "Hello, Flask!"
if __name__ == '__main__':
app.run()
3. Install Required Tools¶
- Install Gunicorn (WSGI server):
pip install gunicorn
- Install Nginx (reverse proxy server):
- For Ubuntu/Debian:sudo apt-get update && sudo apt-get install nginx
- For CentOS/RHEL:sudo yum install nginx
- Verify installation:nginx -v(version number displayed indicates success).
4. Start Gunicorn Service¶
Gunicorn requires specifying the Flask application’s entry point and port. The syntax is:
gunicorn [options] module_name:Flask_instance_name
Example: For an application in app.py with an entry point app (i.e., app = Flask(__name__)):
# Bind to 127.0.0.1:8000 with 4 workers (adjust based on CPU cores, typically CPU cores * 2 + 1)
gunicorn -w 4 -b 127.0.0.1:8000 app:app
- Parameter Explanation:
-w 4: Specifies 4 worker processes (w= worker; process count:CPU cores * 2 + 1to avoid excessive resource usage).-b 127.0.0.1:8000: Binds to the address and port (local access only; adjust for public exposure in production).app:app:appis the module name (app.py), and the secondappis the Flask instance name (app = Flask(__name__)).
Verify Gunicorn:
Open a browser to http://127.0.0.1:8000, or test via command line:
curl http://127.0.0.1:8000 # Should return "Hello, Flask!"
5. Configure Nginx Reverse Proxy¶
Nginx forwards client requests to Gunicorn (127.0.0.1:8000) and handles static resources.
5.1 Create Nginx Configuration File¶
For Ubuntu/Debian, place configuration files in /etc/nginx/sites-available/. Create a new file (e.g., flask_app):
sudo nano /etc/nginx/sites-available/flask_app
5.2 Write Nginx Configuration¶
Paste the following content, replacing server_name with your domain or server IP (use localhost for local testing):
server {
listen 80; # Listen on port 80 (HTTP)
server_name localhost; # Replace with your domain (e.g., example.com)
# Forward dynamic requests to Gunicorn
location / {
proxy_pass http://127.0.0.1:8000; # Gunicorn address
proxy_set_header Host $host; # Forward request headers
proxy_set_header X-Real-IP $remote_addr; # Forward real IP
}
# Serve static files (CSS, JS, images) directly via Nginx
location /static {
alias /path/to/your/flask/static; # Replace with your Flask static directory
expires 30d; # Cache static files for 30 days
}
}
Note: If the Flask app has no static files, delete the location /static block.
5.3 Enable Configuration and Restart Nginx¶
- Create a symlink to
sites-enabled(Nginx loads this directory by default):
sudo ln -s /etc/nginx/sites-available/flask_app /etc/nginx/sites-enabled/
- Check configuration syntax:
sudo nginx -t # "syntax is ok" indicates no errors
- Restart Nginx:
sudo systemctl restart nginx # or service nginx restart
6. Verify the Final Result¶
Access your server’s IP or domain (e.g., http://localhost). You should see the Flask app’s response: “Hello, Flask!”.
7. Advanced: Gunicorn Process Management (Auto-Start on Boot)¶
To avoid manually starting Gunicorn after server restarts, use systemd for auto-start:
- Create a systemd service file:
sudo nano /etc/systemd/system/gunicorn.service
- Add the following content (replace paths and parameters):
[Unit]
Description=Gunicorn instance to serve Flask app
After=network.target
[Service]
User=your_username # Replace with your actual username (e.g., ubuntu)
WorkingDirectory=/path/to/your/flask/app # Replace with app directory
ExecStart=/home/your_username/.local/bin/gunicorn -w 4 -b 127.0.0.1:8000 app:app # Gunicorn command
[Install]
WantedBy=multi-user.target
- Start and enable auto-start:
sudo systemctl start gunicorn
sudo systemctl enable gunicorn # Auto-start on boot
8. Common Troubleshooting¶
-
Nginx Cannot Forward Requests:
- Check Gunicorn status:ps aux | grep gunicorn
- Check port usage:lsof -i:80(modify Nginxlistenif port 80 is occupied).
- Verify firewall rules:sudo ufw allow 80/tcp(Ubuntu) orsudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT. -
Static Files Not Loading:
- Confirmlocation /staticaliaspath is correct (e.g.,/home/ubuntu/myapp/static).
- Restart Nginx:sudo systemctl restart nginx.
Summary¶
By running Flask with Gunicorn (WSGI server) and using Nginx as a reverse proxy, you achieve production-grade deployment. The core steps are “start Gunicorn → configure Nginx to forward requests”. Further optimizations include HTTPS and load balancing.