AWS EC2上React+Django+Docker-Compose用域名时出现Invalid Host Header错误
解决React应用"Invalid Host Header"生产环境安全方案
问题背景
在AWS EC2上部署React(前端)+Django(后端)Web应用,采用Docker-Compose容器化,Nginx反向代理将443端口流量转发至React的3000端口,以HTTPS提供服务。使用公网IP的HTTPS访问正常,但通过域名https://testportal.com访问时,出现Invalid Host Header错误。临时设置DANGEROUSLY_DISABLE_HOST_CHECK=true可解决问题,但该方案存在安全风险,不适用于生产环境。
相关配置信息
Docker Compose(docker-compose.yml)
version: "3" services: react-app: build: context: ./frontend/webapp dockerfile: Dockerfile ports: - "3000:3000" stdin_open: true tty: true environment: - NODE_OPTIONS=--max-old-space-size=16384 - NODE_OPTIONS=--openssl-legacy-provider - HOST=0.0.0.0 networks: - mynetwork django-app: build: context: ./backend/webapp dockerfile: Dockerfile ports: - "8000:8000" command: python manage.py runserver 0.0.0.0:8000 environment: - PYTHONDONTWRITEBYTECODE=1 - PYTHONUNBUFFERED=1 networks: - mynetwork networks: mynetwork: driver: bridge
React Dockerfile
FROM node:21.7.3 ENV NODE_OPTIONS="--max-old-space-size=16384 --openssl-legacy-provider" WORKDIR /app COPY package.json ./ RUN npm install COPY . . RUN npm run build EXPOSE 3000 CMD ["npm", "start"]
环境配置文件(.env)
HOST=testportal.com HTTPS=true PORT=3000
Nginx配置
server { listen 80; server_name www.testportal.com testportal.com; return 301 https://$host$request_uri; } server { listen 443 ssl; server_name www.testportal.com testportal.com; ssl_certificate /etc/letsencrypt/live/testportal.com/fullchain.pem; ssl_certificate_key /etc/letsencrypt/live/testportal.com/privkey.pem; ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers "ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256"; ssl_session_timeout 1d; ssl_session_cache shared:SSL:10m; ssl_stapling on; ssl_stapling_verify on; location / { proxy_pass http://localhost:3000; 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 $scheme; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection 'upgrade'; proxy_cache_bypass $http_upgrade; } error_page 404 /404.html; location = /404.html { internal; } }
/etc/hosts文件
127.0.0.1 localhost x.x.x.x testportal.com x.x.x.x www.testportal.com
已尝试操作
- 设置
DANGEROUSLY_DISABLE_HOST_CHECK=true可临时解决问题,但存在安全风险 - 验证域名已正确指向服务器公网IP
- 确认域名解析正常,Nginx路由无明显异常,但React仍抛出主机头错误
目标
安全配置应用,使https://testportal.com的请求可正常处理,无需禁用主机检查。
解决方案
方案1:切换为生产环境运行React应用(推荐)
当前Dockerfile使用npm start运行React开发服务器,该服务器设计用于开发场景,存在性能瓶颈和安全限制(如Host头检查)。生产环境应直接运行build后的静态文件,推荐使用Nginx镜像托管:
修改React Dockerfile
FROM node:21.7.3 as builder ENV NODE_OPTIONS="--max-old-space-size=16384 --openssl-legacy-provider" WORKDIR /app COPY package.json ./ RUN npm install COPY . . RUN npm run build # 使用轻量级Nginx镜像运行静态文件 FROM nginx:alpine # 复制build产物到Nginx静态目录 COPY --from=builder /app/build /usr/share/nginx/html EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]
更新docker-compose.yml中的react-app配置
react-app: build: context: ./frontend/webapp dockerfile: Dockerfile ports: - "3000:80" # 容器内端口改为Nginx默认的80 networks: - mynetwork # 移除stdin_open、tty及不必要的环境变量
方案2:配置开发服务器允许指定主机(不推荐生产环境使用)
若因特殊需求需继续使用npm start运行开发服务器,可通过以下方式配置允许的主机:
方法A:通过环境变量指定
在React项目的.env文件中添加:
HOST=0.0.0.0 ALLOWED_HOSTS=testportal.com,www.testportal.com
或在docker-compose.yml的react-app服务中添加环境变量:
environment: - NODE_OPTIONS=--max-old-space-size=16384 --openssl-legacy-provider - HOST=0.0.0.0 - ALLOWED_HOSTS=testportal.com,www.testportal.com
方法B:修改Webpack配置(需eject项目)
若项目已执行npm run eject,可编辑config/webpackDevServer.config.js中的allowedHosts:
allowedHosts: [ 'testportal.com', 'www.testportal.com', ],
验证与重启
确认Nginx配置中的proxy_set_header Host $host;已正确设置(当前配置已包含),然后重启所有服务:
docker-compose down docker-compose up --build -d
内容的提问来源于stack exchange,提问作者Vatsal Pathak
相关产品推荐
相关产品推荐

