[英]Nginx Serve React build and proxy_pass Django Rest api server
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;
}
}
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 以相同的顺序通过您在配置中写入的位置链传递您的请求。
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.