简体   繁体   English

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

[英]Nginx Serve React build and proxy_pass Django Rest api server

domain.conf looks like this domain.conf 看起来像这样

I am proxy passing the Django API server using Nginx.我是使用 Nginx 传递 Django API 服务器的代理。 Nginx uses letsencrypt SSL certificates and is currently listening on port 80 and 443. Nginx perfectly serves the react build files while accessing the Django API using Axios in react app results in 502 bad gateway. Nginx 使用 letencrypt SSL 证书,目前正在侦听端口 80 和 443。Nginx 完美地为 react 构建文件提供服务,同时在 react 应用程序中使用 Axios 访问 Django API 导致 502 错误网关。 Axios is trying to access "/api/v1/" as baseURL. Axios 正在尝试访问“/api/v1/”作为 baseURL。

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;
    }
}

part of docker-compose.yml looks like this 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 runs yarn yarn build - domain.conf is copied from ./config/nginx/conf.d - start.sh 运行yarn yarn build - domain.conf 从./config/nginx/conf.d复制

Adding the Final Working Config and Docker Files:添加最终工作配置和 Docker 文件:

Nginx Config 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;
    }
}

docker-compose also added certbot config with nginx docker -compose还使用 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 -- for migrating database, collect static files and start gunicorn server start.sh -- 用于迁移数据库,收集静态文件并启动gunicorn服务器

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

Nginx passes your request through the chain of locations you write in the config, within the same order. Nginx 以相同的顺序通过您在配置中写入的位置链传递您的请求。

  • You can always check access.log to see what happens您可以随时查看 access.log 以了解会发生什么
  • You can set logs level to debug on nginx so it would tell you what happens您可以将日志级别设置为在 nginx 上进行调试,以便它会告诉您会发生什么

The correct configuration is:正确的配置是:

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;
    }

}

I'm also not sure about server configuration order, but I would either remove your first server that listens 443, or put it after the first one, or at least give it a name with www.我也不确定服务器配置顺序,但我会删除你的第一个监听 443 的服务器,或者把它放在第一个服务器之后,或者至少给它一个带www.的名字www.

You can also find a working example with nginx and django atpychat.org您还可以在pychat.org 上找到使用 nginx 和 django 的工作示例

edit编辑

still a 502 bad gateway.仍然是 502 坏网关。 nginx access.log and error.log are coming empty. nginx access.log 和 error.log 变空了。 The nginx terminal logs says 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" nginx 终端日志显示 2019/08/21 19:22:00 [error] 9#9: *2 connect() failed (111: Connection denied) while connected 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”

No processes listen for port 8000 inside your nginx container, you have the frontend in a separate container, which is NOT accessible via localhost: you need to specify http://frontend:8000 .没有进程在您的 nginx 容器内侦听端口 8000,您的前端位于单独的容器中,无法通过 localhost 访问:您需要指定http://frontend:8000 Docker has integrated DNS resolution which equals to container name. Docker 集成了 DNS 解析,相当于容器名称。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM