如何在Docker中配置Nginx作为Django反向代理并解决CSRF问题
Docker中Nginx反向代理Django:解决连接、CSRF错误及IP限制密码验证
核心问题修正
- Nginx容器连接Django失败:你在Nginx upstream中使用了容器随机名称
pk-portal-web-1,Docker Compose内部服务间通信应使用服务名web作为DNS地址。 - Django Admin CSRF错误:Django未正确识别反向代理的请求来源,需调整配置文件。
- 非特定IP密码验证:需在Nginx中配置IP白名单+HTTP Basic Auth组合规则。
一、修改Nginx配置文件
替换原Nginx配置为以下内容,修复连接问题并添加IP限制验证:
upstream hello_django { server web:8000; # 改用docker-compose服务名web } # 定义无需验证的白名单IP段,按需调整 allow 127.0.0.1; allow 192.168.1.0/24; deny all; server { listen 80; # 开启密码验证 auth_basic "Restricted Area"; auth_basic_user_file /etc/nginx/.htpasswd; location / { proxy_pass http://hello_django; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $server_name; } location /static/ { alias /code/staticfiles/; } # 白名单IP满足任一条件即可跳过验证 satisfy any; }
二、生成Nginx密码文件
在本地生成HTTP Basic Auth的密码文件,步骤如下:
# 安装htpasswd工具(Debian/Ubuntu:sudo apt install apache2-utils;CentOS:sudo yum install httpd-tools) htpasswd -c ./nginx/.htpasswd your_username # 按提示输入密码,生成的文件放在nginx目录下
三、更新Nginx Dockerfile
添加复制密码文件的步骤:
FROM nginx:1.25 RUN rm /etc/nginx/conf.d/default.conf COPY nginx.conf /etc/nginx/conf.d/ COPY .htpasswd /etc/nginx/.htpasswd # 新增该行,挂载密码文件
四、修复Django CSRF错误
修改Django项目的settings.py文件:
# 允许访问的域名/IP,按需添加 ALLOWED_HOSTS = ['localhost', '127.0.0.1'] # 信任反向代理的来源地址 CSRF_TRUSTED_ORIGINS = ['http://localhost:1337'] # 开启反向代理相关配置 USE_X_FORWARDED_HOST = True SECURE_PROXY_SSL_HEADER = ('HTTP_X_FORWARDED_PROTO', 'http') # 生产环境改用https
五、完善docker-compose.yml
给PostgreSQL服务添加网络配置,确保与Django服务连通:
services: web: build: . command: gunicorn config.wsgi -b 0.0.0.0:8000 environment: - SECRET_KEY=django-insecure-^+v=tpcw8e+aq1zc(j-1qf5%w*z^a-5*zfjeb!jxy(t=zv*bdg - ENVIRONMENT=development - DEBUG=True volumes: - .:/code - static_volume:/code/staticfiles expose: - 8000 depends_on: - db networks: - my-test-network db: image: postgres volumes: - postgres_data:/var/lib/postgresql/data/ networks: - my-test-network # 新增该行,加入统一网络 nginx: build: ./nginx ports: - "1337:80" volumes: - static_volume:/code/staticfiles depends_on: - web networks: - my-test-network volumes: postgres_data: static_volume: networks: my-test-network: driver: bridge
验证部署
执行以下命令重新构建并启动容器:
docker-compose down && docker-compose up --build
- 白名单IP访问
http://localhost:1337/admin可直接进入后台,无CSRF错误 - 非白名单IP访问会弹出密码验证框,输入正确账号密码后方可访问
内容的提问来源于stack exchange,提问作者Joe Tynan
相关产品推荐
相关产品推荐

