登录
首页 >  文章 >  python教程

Nginx配置SSL加速DockerFastAPI与React应用

时间:2025-07-10 14:48:27 427浏览 收藏

亲爱的编程学习爱好者,如果你点开了这篇文章,说明你对《Nginx配置SSL证书,加速Docker FastAPI与React应用》很感兴趣。本篇文章就来给大家详细解析一下,主要介绍一下,希望所有认真读完的童鞋们,都有实质性的提高。

使用Nginx为Docker容器化FastAPI与React应用配置SSL证书

本教程详细阐述了如何在Docker容器化环境中,利用Nginx作为反向代理为FastAPI后端和React前端应用配置SSL证书。通过将SSL终止卸载到Nginx,可以简化应用层的安全配置,解决直接在应用中处理SSL带来的复杂性(如CORS问题),并实现统一的证书管理和流量路由,确保前后端通信的安全性与高效性。

1. 理解SSL终止与Nginx反向代理

在生产环境中,直接在应用服务器(如FastAPI的Uvicorn)上配置SSL证书通常不是最佳实践。这会增加应用服务器的负担,并可能导致CORS等复杂问题。更推荐的做法是使用一个专门的反向代理服务器,如Nginx,来处理SSL加密与解密(即SSL终止)。客户端的HTTPS请求首先到达Nginx,Nginx解密后将HTTP请求转发给后端的应用服务,再将应用服务的HTTP响应加密后返回给客户端。这种架构有以下优势:

  • 性能优化: Nginx针对高并发和静态文件服务进行了优化,处理SSL握手和加密/解密效率更高。
  • 安全集中: 所有的SSL配置和证书管理都集中在Nginx,方便维护和更新。
  • 简化应用: 后端应用无需关心SSL,只需监听HTTP端口,降低了应用开发的复杂性。
  • 负载均衡与路由: Nginx可以轻松实现负载均衡和基于域名/路径的请求路由。

2. 项目结构与Docker Compose概览

假设您的项目包含一个FastAPI后端、一个React前端和一个PostgreSQL数据库,并通过Docker Compose进行容器化管理。初始的docker-compose.yml可能如下所示:

version: '3.7'
services:
  frontend:
    container_name: "frontend"
    build:
      context: ./frontend
    stop_signal: SIGTERM
    ports:
      - "80:80" # 前端直接暴露80端口
    volumes:
      - ./uploads:/app/uploads
    networks:
      - good_network
    depends_on:
      - backend

  backend:
    container_name: "backend"
    build:
      context: ./backend
    stop_signal: SIGTERM
    ports:
      - "8000:8000" # 后端直接暴露8000端口
    networks:
      - good_network
    volumes:
      - ./uploads:/app/uploads
    depends_on:
      - postgres

  postgres:
    container_name: "postgres"
    image: postgres:16.0
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -d sugar -U postgres" ]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 5s
    restart: unless-stopped
    ports:
      - "5432:5432"
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    networks:
      - good_network

networks:
  good_network:

volumes:
  postgres_data:

在此基础上,我们将引入Nginx服务。

3. 获取SSL证书

在配置Nginx之前,您需要获取SSL证书。通常,这可以通过Certbot工具与Let's Encrypt服务完成,它能提供免费的、受信任的证书。假设您的域名是mysite.ru,并且您希望后端通过子域名back.mysite.ru访问。

通过Certbot获取证书后,证书文件通常会存储在/etc/letsencrypt/live//目录下,例如:

  • fullchain.pem:包含主证书和所有中间证书。
  • privkey.pem:证书的私钥。
  • chain.pem:仅包含中间证书(有时也包含在fullchain.pem中)。

这些文件需要在Nginx容器中可访问。

4. Nginx配置 (nginx.conf)

创建一个nginx.conf文件,用于定义Nginx如何处理传入的HTTP和HTTPS请求,并将其代理到内部的FastAPI和React服务。

# 定义Nginx工作进程可以同时处理的最大连接数
events {
  worker_connections 1024;
}

http {
    # 定义后端服务的上游(upstream)
    # 'back' 是内部服务名称,对应docker-compose中的backend服务
    # 'back.mysite.ru:8000' 是后端服务在Docker网络中的地址和端口
    upstream back {
        server back.mysite.ru:8000;
    }

    # 定义前端服务的上游(upstream)
    # 'front' 是内部服务名称,对应docker-compose中的frontend服务
    # 'mysite.ru:80' 是前端服务在Docker网络中的地址和端口
    upstream front {
        server mysite.ru:80;
    }

    # Nginx服务器块:处理后端服务的HTTP请求(back.mysite.ru:80)
    server {
        listen 80;
        server_name back.mysite.ru; # 监听子域名

        location / {
            # 将请求代理到名为'back'的上游服务
            proxy_pass http://back;
            # 设置Host头,确保后端服务能正确识别请求来源
            proxy_set_header Host $host;
            # 传递客户端的真实IP地址
            proxy_set_header X-Real-IP $remote_addr;
            # 传递代理链中的所有IP地址
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # 告知后端服务,原始请求是通过HTTP协议到达Nginx的
            proxy_set_header X-Forwarded-Proto http;
        }
    }

    # Nginx服务器块:处理后端服务的HTTPS请求(back.mysite.ru:443)
    server {
        listen 443 ssl; # 监听443端口并启用SSL
        server_name back.mysite.ru;

        # SSL证书路径,这些路径将通过Docker卷挂载到容器内部
        ssl_certificate /etc/letsencrypt/live/back.mysite.ru/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/back.mysite.ru/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/back.mysite.ru/chain.pem; # 可选,用于信任链

        location / {
            proxy_pass http://back; # 代理到内部的HTTP后端服务
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            # 告知后端服务,原始请求是通过HTTPS协议到达Nginx的
            proxy_set_header X-Forwarded-Proto https;
        }
    }

    # Nginx服务器块:处理前端服务的HTTP请求(mysite.ru:80)
    server {
        listen 80;
        server_name mysite.ru;

        location / {
            proxy_pass http://front;
            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 http;
        }
    }

    # Nginx服务器块:处理前端服务的HTTPS请求(mysite.ru:443)
    server {
        listen 443 ssl;
        server_name mysite.ru;

        ssl_certificate /etc/letsencrypt/live/mysite.ru/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/mysite.ru/privkey.pem;
        ssl_trusted_certificate /etc/letsencrypt/live/mysite.ru/chain.pem;

        location / {
            proxy_pass http://front;
            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 https;
        }
    }
}

注意事项:

  • upstream块中的server地址应是Docker内部网络中服务可访问的名称和端口(例如,back.mysite.ru:8000或直接使用服务名backend:8000,具体取决于您的DNS解析和网络配置)。这里假设您在Docker Compose中为服务定义了别名或使用了内部DNS解析。在标准Docker Compose网络中,服务名即为主机名,所以backend:8000和frontend:80通常可以直接使用。
  • ssl_certificate、ssl_certificate_key和ssl_trusted_certificate路径必须指向Nginx容器内部可以访问的证书文件。

5. Nginx Dockerfile

创建一个简单的Nginx Dockerfile,将自定义的nginx.conf复制到容器中:

FROM nginx:latest # 使用官方Nginx镜像

# 将自定义的nginx.conf复制到Nginx的配置目录
COPY nginx.conf /etc/nginx/nginx.conf

将此文件保存为nginx/Dockerfile(假设您在项目根目录下创建了一个nginx子目录)。

6. 更新Docker Compose配置

现在,将Nginx服务集成到docker-compose.yml中:

version: '3.7'
services:
  frontend:
    container_name: "frontend"
    build:
      context: ./frontend
    stop_signal: SIGTERM
    # 不再直接暴露80端口到主机,由Nginx处理
    # ports:
    #   - "80:80"
    volumes:
      - ./uploads:/app/uploads
    networks:
      - good_network
    depends_on:
      - backend

  backend:
    container_name: "backend"
    build:
      context: ./backend
    stop_signal: SIGTERM
    # 不再直接暴露8000端口到主机,由Nginx处理
    # ports:
    #   - "8000:8000"
    networks:
      - good_network
    volumes:
      - ./uploads:/app/uploads
    depends_on:
      - postgres

  postgres:
    container_name: "postgres"
    image: postgres:16.0
    healthcheck:
      test: [ "CMD-SHELL", "pg_isready -d sugar -U postgres" ]
      interval: 5s
      timeout: 5s
      retries: 5
      start_period: 5s
    restart: unless-stopped
    ports:
      - "5432:5432"
    volumes:
      - ./postgres_data:/var/lib/postgresql/data
    networks:
      - good_network

  # 新增Nginx服务
  nginx:
    build: ./nginx # 指向Nginx Dockerfile所在的目录
    ports:
      - "80:80"   # 暴露HTTP端口,用于重定向或Certbot验证
      - "443:443" # 暴露HTTPS端口
    volumes:
      # 挂载宿主机的Certbot证书目录到Nginx容器
      # 确保宿主机上的 /etc/letsencrypt 目录存在且包含有效证书
      - /etc/letsencrypt:/etc/letsencrypt:ro # 只读模式挂载
    networks:
      - good_network
    depends_on:
      - frontend # 确保前端服务启动后再启动Nginx
      - backend  # 确保后端服务启动后再启动Nginx

networks:
  good_network:

volumes:
  postgres_data:

关键更改:

  1. 移除frontend和backend服务的ports映射: 它们现在只在内部网络中通过Nginx访问。
  2. 新增nginx服务:
    • build: ./nginx:告诉Docker Compose在./nginx目录下构建Nginx镜像。
    • ports: - "80:80" - "443:443":将Nginx容器的80和443端口映射到宿主机的80和443端口,以便外部流量访问。
    • volumes: - /etc/letsencrypt:/etc/letsencrypt:ro:这是最关键的一步。它将宿主机上Certbot生成的证书目录挂载到Nginx容器的相同路径,并以只读(ro)模式挂载,确保Nginx可以读取证书文件。在运行此配置之前,请确保您的宿主机上已经通过Certbot或其他方式获取了证书,并位于/etc/letsencrypt目录下。
    • depends_on: - frontend - backend:确保Nginx在前端和后端服务启动后才启动。

7. 部署与验证

  1. 获取证书: 在宿主机上运行Certbot命令获取或更新您的域名(mysite.ru和back.mysite.ru)的SSL证书。例如:
    sudo certbot certonly --nginx -d mysite.ru -d back.mysite.ru
    # 或者如果Nginx不在宿主机上,使用webroot模式
    # sudo certbot certonly --webroot -w /var/www/html -d mysite.ru -d back.mysite.ru

    确保证书文件已正确生成并放置在/etc/letsencrypt/live/目录下。

  2. 启动服务: 在项目根目录下运行:
    docker-compose up --build -d
  3. 验证:
    • 通过浏览器访问 https://mysite.ru 和 https://back.mysite.ru。检查是否显示安全连接(绿色锁图标)。
    • 您也可以使用curl命令验证:
      curl -v https://mysite.ru
      curl -v https://back.mysite.ru/your_api_endpoint

      检查输出中是否有SSL/TLS握手信息。

8. 总结与最佳实践

通过Nginx作为反向代理进行SSL终止,您已经成功地为Docker容器化的FastAPI和React应用配置了HTTPS。这种方法不仅解决了直接在应用层处理SSL的复杂性,还提供了更灵活、更安全的部署方案。

其他注意事项和最佳实践:

  • HTTP到HTTPS重定向: 为了强制所有流量都使用HTTPS,您可以在Nginx的HTTP服务器块中添加重定向规则:
    server {
        listen 80;
        server_name mysite.ru back.mysite.ru;
        return 301 https://$host$request_uri; # 将所有HTTP请求重定向到HTTPS
    }
  • CORS处理: 当Nginx作为反向代理时,FastAPI应用仍然会收到来自Nginx的HTTP请求。如果您的FastAPI应用需要处理CORS,请确保在FastAPI应用中正确配置CORS中间件,允许来自您前端域名的请求。例如,如果您的前端在mysite.ru,后端在back.mysite.ru,则FastAPI的CORS配置应允许https://mysite.ru作为源。Nginx通过X-Forwarded-Proto: https头告知后端原始请求是HTTPS,后端可以据此进行逻辑判断。
  • 证书自动续期: 对于Let's Encrypt证书,务必设置Certbot的自动续期机制(通常Certbot安装后会自动配置一个cron job或systemd timer)。
  • Nginx安全强化: 考虑在Nginx配置中添加额外的安全措施,如:
    • add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always; (HSTS)
    • 配置更强的SSL/TLS协议和密码套件,禁用旧版本和弱加密算法。
    • 限制请求体大小,防止DDoS攻击。
  • 日志管理: 配置Nginx的访问日志和错误日志,以便于监控和故障排查。

通过遵循这些步骤和最佳实践,您可以构建一个安全、高效且易于维护的Docker容器化应用部署环境。

到这里,我们也就讲完了《Nginx配置SSL加速DockerFastAPI与React应用》的内容了。个人认为,基础知识的学习和巩固,是为了更好的将其运用到项目中,欢迎关注golang学习网公众号,带你了解更多关于的知识点!

相关阅读
更多>
最新阅读
更多>
课程推荐
更多>