Nginx服务React构建和proxy_pass Django Rest API服务器

时间:2019-08-21 16:46:32

标签: python django nginx docker-compose nginx-reverse-proxy

domain.conf看起来像这样

我是使用Nginx传递Django API服务器的代理。 Nginx使用letencrypt SSL证书,当前正在侦听端口80和443。当在502错误的网关中使用react应用程序结果中的Axios访问Django API时,Nginx完美地提供了react build文件。 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 -从./config/nginx/conf.d

复制domain.conf

2 个答案:

答案 0 :(得分: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;
    }
}

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-用于迁移数据库,收集静态文件并启动gunicorn服务器

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

答案 1 :(得分:0)

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 [错误] 9#9:* 2连接到上游时,connect()失败(111:连接被拒绝),客户端:27.7.17.142,服务器:,请求: “ 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解析。