Docker容器中Angular前端无法解析Go后端服务地址问题求助
问题描述
Docker容器创建成功,但前端发起HTTP请求到后端服务时失败,报错信息:
GET http://backend:8080/questions net::ERR_NAME_NOT_RESOLVED
前端请求URL为http://backend:8080/questions,Referrer Policy为strict-origin-when-cross-origin。
相关配置及代码如下:
docker-compose.yml
version: "3.8" services: frontend: build: ./question-paper ports: - "4200:4200" backend: build: ./backend ports: - "8080:8080" environment: - DB_NAME=questions - DB_PORT=3306 - DB_HOST=database - DB_PASSWD=root - DB_USER=root depends_on: - database database: image: mysql restart: always environment: MYSQL_DATABASE: questions MYSQL_PASSWORD: root MYSQL_ROOT_PASSWORD: root ports: - "3806:3306" volumes: - ./init.sql:/docker-entrypoint-initdb.d/ # Check the path to init.sql - my-db:/var/lib/mysql volumes: my-db:
Angular请求代码
import { HttpClient } from '@angular/common/http'; import { Questions } from '../model/question-model'; import { Observable } from 'rxjs'; import { Inject, Injectable } from '@angular/core'; @Injectable({ providedIn: 'root', }) export class QuestionService { constructor(private httpClient: HttpClient) {} GetQuestions(): any { return this.httpClient.get('http://backend:8080/questions'); } }
Go后端代码
func main(){ mux := mux.NewRouter() handle := h.CORS( h.AllowedOrigins([]string{"*"}), h.AllowedMethods([]string{"GET", "POST", "PUT", "DELETE", "HEAD", "OPTIONS"}), h.AllowedHeaders([]string{"Content-Type", "Authorization", "Origin", "Accept"}), ) mux.HandleFunc("/questions", handlers.GetQuestions) http.ListenAndServe(":8080", handle(mux)) }
问题原因
错误的核心原因是:前端代码运行在用户的浏览器中,而非Docker容器内部。Docker Compose创建的内部网络DNS解析仅对容器生效,浏览器作为宿主机环境的应用,无法识别backend这个服务名,自然无法解析对应的IP地址,导致请求失败。
解决方案
以下是几种无需硬编码IP的优雅解决方案:
方案1:Angular代理配置(开发环境推荐)
利用Angular CLI的代理功能,将前端请求转发到后端容器:
- 在Angular项目根目录创建
proxy.conf.json:
{ "/api": { "target": "http://backend:8080", "secure": false, "pathRewrite": { "^/api": "" } } }
- 修改
angular.json,在projects -> [你的项目名] -> architect -> serve -> options中添加:
"proxyConfig": "proxy.conf.json"
- 调整前端请求代码为相对路径:
GetQuestions(): any { return this.httpClient.get('/api/questions'); }
启动Angular应用后,CLI会自动将/api开头的请求代理到http://backend:8080,同时解决跨域问题。
方案2:Nginx反向代理(生产环境推荐)
通过Nginx统一处理前端和后端请求,让浏览器通过同一域名访问,彻底避免跨域和DNS解析问题:
- 创建
nginx.conf配置文件:
server { listen 80; # 处理前端静态资源 location / { root /usr/share/nginx/html; try_files $uri $uri/ /index.html; } # 转发后端API请求 location /api/ { proxy_pass http://backend:8080/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; } }
- 修改
docker-compose.yml,添加Nginx服务并调整前端、后端的端口暴露:
version: "3.8" services: frontend: build: ./question-paper ports: [] # 不再暴露4200端口,仅内部网络访问 backend: build: ./backend ports: [] # 不再暴露8080端口,仅内部网络访问 environment: - DB_NAME=questions - DB_PORT=3306 - DB_HOST=database - DB_PASSWD=root - DB_USER=root depends_on: - database database: image: mysql restart: always environment: MYSQL_DATABASE: questions MYSQL_PASSWORD: root MYSQL_ROOT_PASSWORD: root ports: - "3806:3306" volumes: - ./init.sql:/docker-entrypoint-initdb.d/ - my-db:/var/lib/mysql nginx: image: nginx:alpine ports: - "80:80" volumes: - ./nginx.conf:/etc/nginx/conf.d/default.conf # 生产环境需挂载Angular构建后的静态文件目录: # - ./question-paper/dist/[项目名]/:/usr/share/nginx/html depends_on: - frontend - backend volumes: my-db:
- 前端请求代码改为
/api/questions,浏览器请求Nginx后,会被转发到后端服务。
方案3:环境变量动态配置
通过Angular的环境变量,根据开发/生产环境动态设置后端地址:
- 修改开发环境配置
src/environments/environment.ts:
export const environment = { production: false, backendUrl: 'http://localhost:8080' };
- 修改生产环境配置
src/environments/environment.prod.ts:
export const environment = { production: true, backendUrl: '/api' };
- 调整前端请求代码:
import { environment } from '../../environments/environment'; // ... GetQuestions(): any { return this.httpClient.get(`${environment.backendUrl}/questions`); }
开发时利用Docker端口映射的localhost:8080访问后端,生产时配合Nginx反向代理使用相对路径。
内容的提问来源于stack exchange,提问作者Pruthviraj
相关产品推荐
相关产品推荐

