杰瑞科技汇

Flask+Nginx如何协同部署Python应用?

Of course! This is a very common and powerful stack for deploying web applications. Let's break it down, starting with what each component is, how they work together, and then walk through a practical setup.


The Big Picture: What are they and why use them together?

Imagine you're running a busy restaurant:

  • Python/Flask: This is the head chef. He's an expert at creating the unique, delicious dishes (your web application's logic). He's brilliant at cooking, but he's not great at handling a crowd of customers at the front door. He can only talk to one or two people at a time.
  • Nginx (Engine-X): This is the Maître d'. He's the first person to greet customers. He handles all the incoming requests, takes their orders, manages the waiting list, and serves static content like water and bread (CSS, JavaScript, images). He's very fast and can handle thousands of customers efficiently.
  • uWSGI / Gunicorn: This is the waiter who takes the order from the Maître d' and brings it to the head chef. The chef prepares the dish, and the waiter brings it back to the Maître d', who then serves it to the customer. This waiter is specialized in communicating orders between the front of the house (Nginx) and the back of the house (Flask).

Why this stack is so popular:

  1. Performance: Nginx is extremely fast at serving static files and handling network connections. It offloads this work from Flask, allowing Flask to focus only on dynamic content (Python code).
  2. Scalability: If the restaurant gets too busy, you can hire more waiters (run multiple uWSGI/Gunicorn workers). If it gets really busy, you can even hire multiple head chefs (run multiple Flask instances on different servers). Nginx can distribute the load between them.
  3. Security & Stability: Nginx acts as a shield. It can handle malicious requests, manage SSL/TLS for HTTPS, and buffer traffic, protecting your Flask app from direct exposure to the internet.
  4. Robustness: If the head chef (Flask app) crashes, the Maître d' (Nginx) can still serve static pages or a friendly error message, and can even try to restart the chef in the background.

Component Breakdown

A. Flask

  • What it is: A lightweight and flexible Python web framework.
  • Its Job: To define your application's routes (URLs), handle business logic, and render templates or return data (like JSON).
  • Key Limitation: The development server that comes with Flask (flask run) is not suitable for production. It's a single-threaded server and is not secure or performant.

B. uWSGI or Gunicorn (The Application Server)

  • What they are: WSGI (Web Server Gateway Interface) servers. They are the bridge between your Python application and a web server.
  • Their Job:
    1. To load your Flask application.
    2. To listen for incoming requests from Nginx.
    3. To manage a pool of "worker" processes/threads to handle those requests concurrently.
    4. To execute the Python code and return the response to Nginx.
  • uWSGI vs. Gunicorn:
    • Gunicorn: Known for being simple, stable, and easy to use. It's often the first choice for new projects.
    • uWSGI: More feature-rich and highly configurable. It can be faster in some scenarios and has built-in support for things like caching and process management. It's often used in more complex deployments.
    • For this guide, we'll use Gunicorn because it's simpler to get started with.

C. Nginx (The Reverse Proxy)

  • What it is: A high-performance web server and reverse proxy.
  • Its Job:
    1. Listen on Port 80/443: It's the public-facing server that accepts all incoming traffic from the internet.
    2. Handle Static Files: It directly serves static assets (CSS, JS, images) very quickly, without bothering Gunicorn/Flask.
    3. Reverse Proxy: It forwards dynamic requests (the ones that need Python) to Gunicorn. It does this by sending the request to a specific port where Gunicorn is listening (e.g., localhost:8000).
    4. SSL/TLS Termination: It handles the encryption/decryption for HTTPS traffic, unencrypting the request before passing it to Gunicorn. This simplifies your Flask app's configuration.
    5. Load Balancing: If you have multiple Gunicorn instances running, Nginx can distribute traffic among them.

Practical Step-by-Step Setup

Let's build a simple Flask app and deploy it with this stack.

Step 1: Project Structure

Create a directory for your project with the following structure:

my_flask_project/
├── app.py             # Your Flask application
├── requirements.txt   # Python dependencies
├── gunicorn.conf.py   # Gunicorn configuration (optional but good)
└── nginx/
    └── my_flask.conf  # Nginx configuration file

Step 2: The Flask Application (app.py)

This is a simple "Hello World" app to keep things focused.

# app.py
from flask import Flask
app = Flask(__name__)
@app.route('/')
def hello():
    return "<h1>Hello from Flask, served by Nginx and Gunicorn!</h1>"
@app.route('/health')
def health_check():
    return "OK", 200
if __name__ == '__main__':
    # This is for development only!
    app.run(host='0.0.0.0', port=5000)

Step 3: Python Dependencies (requirements.txt)

Create this file and add the necessary packages.

# requirements.txt
Flask
gunicorn

Step 4: Install Dependencies

Navigate to your project directory in the terminal and run:

python3 -m venv venv
source venv/bin/activate  # On Windows, use `venv\Scripts\activate`
pip install -r requirements.txt

Step 5: Run with Gunicorn

Before setting up Nginx, let's test Gunicorn directly. In your terminal (with the virtualenv active), run:

# The format is: gunicorn --bind <host>:<port> <module_name>:<app_variable_name>
gunicorn --bind 0.0.0.0:8000 app:app
  • app:app: The first app is the name of your Python file (app.py). The second app is the name of the Flask application instance inside that file (app = Flask(__name__)).

Now, open your browser and go to http://localhost:8000. You should see your "Hello World" message. If it works, you can stop Gunicorn with Ctrl+C.

Step 6: Configure Nginx

This is the most crucial part. We need to tell Nginx how to forward requests.

  1. Create the Nginx config file: Create the file my_flask_project/nginx/my_flask.conf and add the following content.

    # nginx/my_flask.conf
    server {
        listen 80;
        server_name localhost; # Replace with your domain name or IP
        location / {
            # Pass requests to the Gunicorn server
            proxy_pass http://127.0.0.1:8000;
            # Set headers to pass to the Gunicorn server
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
        # Optional: Serve static files directly if you have them
        # location /static {
        #     alias /path/to/your/static/files;
        # }
    }
  2. Enable the Nginx site: The location of Nginx configuration files varies by OS.

    • On Ubuntu/Debian: /etc/nginx/sites-available/
    • On CentOS/RHEL: /etc/nginx/conf.d/

    Create a symbolic link from your config file to the sites-enabled directory (on Ubuntu/Debian) or just copy it directly to conf.d (on CentOS/RHEL).

    # For Ubuntu/Debian
    sudo ln -s /path/to/your/my_flask_project/nginx/my_flask.conf /etc/nginx/sites-available/
    sudo ln -s /etc/nginx/sites-available/my_flask.conf /etc/nginx/sites-enabled/
    # For CentOS/RHEL
    # sudo cp /path/to/your/my_flask_project/nginx/my_flask.conf /etc/nginx/conf.d/
  3. Test and Reload Nginx: Before restarting, check for syntax errors.

    sudo nginx -t

    If it says syntax is ok and test is successful, reload Nginx to apply the changes.

    sudo systemctl reload nginx

Step 7: Run Everything Together

Now, start Gunicorn in the background. A good way to do this is with systemd, which will also automatically restart it if it crashes.

  1. Create a systemd service file: Create a file named gunicorn.service in /etc/systemd/system/.

    # /etc/systemd/system/gunicorn.service
    [Unit]
    Description=Gunicorn instance to serve my_flask_project
    After=network.target
    [Service]
    User=www-data  # Or your username
    Group=www-data # Or your user's group
    WorkingDirectory=/path/to/your/my_flask_project
    Environment="PATH=/path/to/your/my_flask_project/venv/bin"
    ExecStart=/path/to/your/my_flask_project/venv/bin/gunicorn --config gunicorn.conf.py app:app
    [Install]
    WantedBy=multi-user.target
    • Important: Replace all the /path/to/your/... placeholders with your actual paths.
    • User and Group: It's a security best practice to run services as a non-root user like www-data.
    • Environment: This tells systemd where to find the Python executables in your virtual environment.
    • ExecStart: This is the command to start Gunicorn. We're referencing a config file gunicorn.conf.py.
  2. Create the Gunicorn config file (gunicorn.conf.py): This is optional but recommended for better control.

    # gunicorn.conf.py
    bind = "127.0.0.1:8000"
    workers = 3 # Number of worker processes. (2 * CPU cores) + 1 is a good formula.
    worker_class = "sync" # Or "gevent" for async
    worker_connections = 1000
    max_requests = 1000
    max_requests_jitter = 50
    preload_app = True
    keepalive = 2
    timeout = 30
    graceful_timeout = 30
  3. Start and Enable the Gunicorn Service:

    sudo systemctl daemon-reload
    sudo systemctl start gunicorn
    sudo systemctl enable gunicorn # This makes it start on boot

    You can check its status with sudo systemctl status gunicorn.

Step 8: Final Test

Now, open your browser and navigate to http://localhost (or your server's IP address). You should see the "Hello World" message from Flask, but this time it's being served by Nginx, which forwarded the request to Gunicorn, which in turn ran your Python code.

Congratulations! You have successfully deployed a Flask application with Nginx and Gunicorn.

分享:
扫描分享到社交APP
上一篇
下一篇