Docker部署Angular+Django时前端无法调用后端接口问题
使用Docker部署Django Rest Framework与Angular应用,包含三个容器:django(api服务)、db(PostgreSQL)、搭载Nginx的angular容器。部署后可通过localhost:80访问Angular页面,但前端调用http://localhost:8000/api/sensores/获取数据时失败,Chrome控制台报错:
Error al obtener sensores: ct {headers: e, status: 0, statusText: 'Unknown Error', url: 'http://localhost:8000/api/sensores/', ok: false, …}
GET http://localhost:8000/api/sensores/ net::ERR_CONNECTION_REFUSED
在angular-nginx容器的exec控制台中执行curl http://api:8000/api/sensores/可正常获取数据,但前端无法完成该调用。
相关配置文件
docker-compose.yml
version: '3.8' services: angular: container_name: angular-nginx build: ./hello # context: ./hello ports: - "80:80" volumes: - ./hello/nginx.conf:/etc/nginx/nginx.conf:ro - ./hello/dist/hello/browser:/usr/share/nginx/html depends_on: - db api: build: context: ./django command: gunicorn helloDocker.wsgi:application --bind 0.0.0.0:8000 volumes: - ./django:/app expose: - "8000" environment: - DEBUG=False - DJANGO_SECRET_KEY=your_secret_key - DATABASE_URL=postgres://myuser:mypassword@localhost:5432/vituclim depends_on: - db # Servicio de base de datos db: container_name: postgre image: postgres:latest environment: POSTGRES_DB: vituclim POSTGRES_USER: myuser POSTGRES_PASSWORD: mypassword volumes: - db_data:/var/lib/postgresql/data volumes: db_data:
nginx.conf(Angular容器内)
user nginx; worker_processes auto; pid /var/run/nginx.pid; events { worker_connections 1024; } http { include /etc/nginx/mime.types; default_type application/octet-stream; access_log /var/log/nginx/access.log; server { listen 80; server_name localhost; location / { root /usr/share/nginx/html; index index.html; try_files $uri $uri/ /index.html; } location /api/ { proxy_pass http://api:8000/;o 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; } } }
Angular服务代码
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; import { Sensor } from './sensor'; @Injectable({ providedIn: 'root' }) export class HelloWorldService { private nombreContenedorDjango = 'api' private apiUrl = 'http://'+this.nombreContenedorDjango+':8000/api'; // URL del backend constructor(private http: HttpClient) {} getMessage(): Observable<{message: string}> { return this.http.get<{message: string}>(`${this.apiUrl}/mensaje/`); } getSensores(): Observable<Sensor[]> { return this.http.get<any>(`${this.apiUrl}/sensores/`); } }
1. 修正Angular服务的API地址
前端代码在浏览器中运行,无法识别Docker内部的服务名api,需将API地址改为相对路径,让Nginx反向代理处理转发:
private apiUrl = '/api'; // 直接使用相对路径,由Nginx转发到后端
2. 修复Nginx配置的语法错误
nginx.conf中proxy_pass行末尾多了一个多余的o,导致配置失效,修正后:
location /api/ { proxy_pass http://api:8000/; 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; }
3. 修正Django的数据库连接地址
api服务的DATABASE_URL使用localhost会指向容器自身,需改为Docker Compose中的db服务名:
environment: - DEBUG=False - DJANGO_SECRET_KEY=your_secret_key - DATABASE_URL=postgres://myuser:mypassword@db:5432/vituclim
4. 配置Django跨域(可选)
若仍存在跨域问题,需安装并配置django-cors-headers:
- 安装依赖:
pip install django-cors-headers
- 修改Django的
settings.py:
INSTALLED_APPS = [ # ... 'corsheaders', ] MIDDLEWARE = [ 'corsheaders.middleware.CorsMiddleware', 'django.middleware.common.CommonMiddleware', # ... ] CORS_ALLOWED_ORIGINS = [ "http://localhost:80", ]
内容的提问来源于stack exchange,提问作者Miguel Ángel Guaita Villaseñor

