Nginx Serve React 构建和 proxy_pass Django Rest api 服务器

Posted

技术标签:

【中文标题】Nginx Serve React 构建和 proxy_pass Django Rest api 服务器【英文标题】:Nginx Serve React build and proxy_pass Django Rest api server 【发布时间】:2019-12-26 23:53:00 【问题描述】:

domain.conf 看起来像这样

我是使用 nginx 传递 Django API 服务器的代理。 Nginx 使用letsencrypt SSL 证书,目前正在监听端口80 和443。Nginx 完美地服务于react 构建文件,同时在react app 中使用Axios 访问Django API 会导致502 bad gateway。 Axios 正在尝试以 baseURL 的形式访问“/api/v1/”。

server 
    listen 80;
    listen [::]:80;

    location /.well-known/acme-challenge/ 
        root /var/www/certbot;
    

    return 301 https://example.com$request_uri;


server 
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    # redirects www to non-www. wasn't work for me without this server block
    return 301 https://example.com$request_uri;


server 
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location / 
        root /var/www/frontend;
        try_files $uri $uri/ /index.html;
    

    location /api/ 
        proxy_pass http://localhost:8000;
        proxy_redirect default;
        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;
    

docker-compose.yml 的一部分看起来像这样

backend:
    build:
      context: .
      dockerfile: dockerFiles/backend/DockerFile
    tty: true
    ports:
      - "8000:8000"
    expose:
      - 8000
    volumes:
      - ./backend:/backend
    env_file:
      - backend/.env
    depends_on:
      - db

  frontend:
    image: node:latest
    command: sh start.sh
    working_dir: /frontend
    tty: true
    volumes:
      - ./frontend/:/frontend
    depends_on:
      - backend
    links: 
      - backend

  nginx:
    image: nginx:latest
    tty: true
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./config/nginx/conf.d:/etc/nginx/conf.d
      - ./frontend/dist:/var/www/frontend
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    depends_on:
      - backend

- start.sh 运行yarn yarn build - domain.conf 复制自./config/nginx/conf.d

【问题讨论】:

你有多个服务器监听同一个端口,要么他们应该有不同的域,要么他们应该有不同的端口。您需要在 nginx 中为 uwsgi 和静态文件创建不同的端点 @deathangel908 任何参考都会很好。谢谢。 【参考方案1】:

添加最终工作配置和 Docker 文件:

Nginx 配置

upstream backend_server 
    server backend:8000;


server 
    listen 80;

    location /.well-known/acme-challenge/ 
        root /var/www/certbot;
    

    location /api/ 
        return 301 https://$host$request_uri;
    

    location / 
        return 301 https://$host$request_uri;
    


server 
    listen 443 ssl;
    root /var/www/frontend;

    ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location /api/v1/ 
        proxy_pass http://backend_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 $https;
        proxy_connect_timeout 360s;
        proxy_read_timeout 360s;
    

    location / 
        try_files $uri /index.html;
    

码头工人撰写 还添加了带有 nginx 的 certbot 配置

version: '3.5'

services:
  db:
    container_name: db
    image: postgres:latest
    ports:
      - "5432"
    volumes:
      - postgres_data:/var/lib/postgresql/data/

  backend:
    container_name: backend
    build:
      context: .
      dockerfile: dockerFiles/backend/DockerFile
    tty: true
    ports:
      - "8000:8000"
    expose:
      - 8000
    volumes:
      - ./backend:/backend
    env_file:
      - backend/.env
    depends_on:
      - db

  frontend:
    container_name: frontend
    image: node:latest
    command: sh start.sh
    working_dir: /frontend
    tty: true
    volumes:
      - ./frontend/:/frontend
    depends_on:
      - backend
    links: 
      - backend

  nginx:
    container_name: nginx
    image: nginx:latest
    tty: true
    ports:
      - 80:80
      - 443:443
    volumes:
      - ./config/nginx/conf.d:/etc/nginx/conf.d
      - ./frontend/dist:/var/www/frontend
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    depends_on:
      - backend
    command: "/bin/sh -c 'while :; do sleep 6h & wait $$!; nginx -s reload; done & nginx -g \"daemon off;\"'"

  certbot:
    image: certbot/certbot
    restart: unless-stopped
    volumes:
      - ./data/certbot/conf:/etc/letsencrypt
      - ./data/certbot/www:/var/www/certbot
    entrypoint: "/bin/sh -c 'trap exit TERM; while :; do certbot renew; sleep 12h & wait $$!; done;'"


volumes:
  postgres_data: # <-- declare the postgres volume

start.sh -- 用于迁移数据库,收集静态文件并启动 gunicorn 服务器

# Start Gunicorn processes
echo Starting Gunicorn.
exec gunicorn <app-name>.wsgi:application -k gevent\
    --bind 0.0.0.0:8000 \
    --workers

【讨论】:

【参考方案2】:

Nginx 以相同的顺序通过您在配置中写入的位置链传递您的请求。

您可以随时查看 access.log 以了解发生了什么 您可以将日志级别设置为在 nginx 上进行调试,这样它就会告诉您发生了什么

正确的配置是:

server 
    listen 443 ssl;
    listen [::]:443 ssl;
    server_name example.com www.example.com;
    ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;

    location /api/ 
        proxy_pass http://frontend:8000;
        proxy_redirect default;
        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;
    

    location / 
        root /var/www/frontend;
        try_files $uri $uri/ /index.html;
    


我也不确定服务器配置顺序,但我会删除您的第一个侦听 443 的服务器,或者将其放在第一个服务器之后,或者至少给它命名为 www.

您还可以在 pychat.org 找到一个使用 nginx 和 django 的工作示例

编辑

仍然是 502 错误网关。 nginx access.log 和 error.log 为空。 nginx 终端日志显示 2019/08/21 19:22:00 [error] 9#9: *2 connect() failed (111: Connection refused) while connection to upstream, client: 27.7.17.142, server: , request: “POST /api/v1/login/facebook/HTTP/2.0”,上游:“http://127.0.0.1:8000/api/v1/login/facebook/”,主机:“example.com”,引用者:“https://example.com/login”

在你的 nginx 容器中没有进程监听端口 8000,你的前端在一个单独的容器中,不能通过 localhost 访问:你需要指定http://frontend:8000。 Docker集成了DNS解析,相当于容器名称。

【讨论】:

仍然是 502 错误网关。 nginx access.log 和 error.log 为空。 nginx 终端日志显示2019/08/21 19:22:00 [error] 9#9: *2 connect() failed (111: Connection refused) while connecting to upstream, client: 27.7.17.142, server: , request: "POST /api/v1/login/facebook/ HTTP/2.0", upstream: "http://127.0.0.1:8000/api/v1/login/facebook/", host: "example.com", referrer: "https:/example.com/login" 看到了您的编辑。应用了补丁,仍然与上述评论中的响应相同的错误。感谢您的努力。 修好了。将很快更新解决方案。 您很可能需要设置一个 WSGI HTTP 服务器并利用 wsgi 协议。不幸的是,nginx 不支持 wsgi 协议,因此你必须在中间有一些东西可以为你做这件事。你可以在这里阅读:digitalocean.com/community/tutorials/…

以上是关于Nginx Serve React 构建和 proxy_pass Django Rest api 服务器的主要内容,如果未能解决你的问题,请参考以下文章

Localhost、Php artisan serve 和 homestead Pro/Cons

.NET Core + React Antd Pro脚手架

极智开发 | nginx 部署 antd pro

React-Webpack-production 构建不适用于 nginx

React 应用程序在“npm start”期间工作,但在构建后返回 404

使用 Nginx 和 Docker 部署 React 和 Django