You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Docker化Angular/Spring Boot应用时请求转发失败问题排查

问题:Angular+Spring Boot+Docker部署后,前端请求后端出现ERR_NAME_NOT_RESOLVED错误

我正在尝试将Angular应用与Spring Boot应用进行Docker化部署,并配置PostgreSQL数据库。所有组件已搭建完成,但发现Angular应用无法解析backend:8081地址,所有请求均返回ERR_NAME_NOT_RESOLVED错误,尽管容器间ping通信正常。


相关配置

Spring Boot应用Dockerfile

# Use a base image with JDK and Maven installed
FROM maven:3.8.4-openjdk-17-slim AS build

# Set the working directory
WORKDIR /app

# Copy the pom.xml file to the working directory
COPY pom.xml .

# Copy the entire project to the working directory
COPY src ./src

# Build the application with Maven
RUN mvn clean package -DskipTests

# Use a smaller base image for the runtime environment
FROM amazoncorretto:17-alpine-jdk

# Set the working directory
WORKDIR /app

# Copy the built JAR file from the build stage to the runtime image
COPY --from=build /app/target/restaurant.jar ./app.jar

RUN mkdir /app/storage

# Expose the port that your Spring Boot application listens on (if applicable)
EXPOSE 8081

# Command to run the application
CMD ["java", "-jar", "app.jar"]

application.properties配置

spring.datasource.url=${DB_URL}
spring.datasource.username=${DB_USERNAME}
spring.datasource.password=${DB_PASSWD}

# Hibernate settings
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.PostgreSQLDialect
spring.jpa.hibernate.ddl-auto=update

# Application's server port
#server.port=8081
server.port=${SERVER_PORT}

spring.servlet.multipart.max-file-size=5GB
spring.servlet.multipart.max-request-size=5GB

files.folder=${STORAGE}
front.address=${FRONT_ADDR}

# Application's name
spring.application.name=NapolitanaBack

CORS配置类

package com.napolitana.restaurant.config;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

@Configuration
public class CorsConfig {

    @Value("${front.address}")
    String frontAddress;

    @Bean
    public WebMvcConfigurer corsConfigurer() {
        return new WebMvcConfigurer() {
            @Override
            public void addCorsMappings(CorsRegistry registry) {
                registry.addMapping("/**")
                         .allowedOrigins(frontAddress)
                        //.allowedOrigins("*")
                        .allowedMethods("GET", "POST", "PUT", "DELETE", "PATCH")
                        .allowedHeaders("*");
            }
        };
    }
}

Angular应用Dockerfile

# Base image with Node.js installed
FROM node:18.20.2 AS build

# Set the working directory
WORKDIR /app

# Copy package.json and package-lock.json (if present) to the working directory
COPY package.json package-lock.json ./

# Install dependencies
RUN npm install

# Copy the entire project to the working directory
COPY . .

# Build the Angular app for production
RUN npm run build --prod

# Use NGINX base image for serving Angular application
FROM nginx:alpine

# Copy build artifacts from the build stage to NGINX public directory
COPY --from=build /app/dist/napolitana-front /usr/share/nginx/html

# Copy nginx.conf to configure the server
COPY default.conf /etc/nginx/conf.d/default.conf

# Expose the port that NGINX listens on
EXPOSE 80

# Command to start NGINX and serve the Angular app
CMD ["nginx", "-g", "daemon off;"]

Nginx的default.conf配置

server {
    listen 80;
    server_name frontend;

    location / {
        root /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /index.html;
    }

    location /api/ {
        proxy_pass http://backend:8081;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $http_host;
    }

    location /admin/ {
        alias /usr/share/nginx/html;
        index index.html;
        try_files $uri $uri/ /admin/index.html;
    }

    location ~ ^/admin/([a-zA-Z0-9\-_]+)/(.*)$ {
        alias /usr/share/nginx/html/admin/$1/;
        index index.html;
        try_files $uri $uri/ /admin/$1/index.html;
    }
}

Angular环境配置

export const environment = {
    BASE_URL: 'http://backend:8081/api'
}

docker-compose.yml配置

version: '3.8'

services:
  postgres:
    image: postgres:latest
    restart: always
    environment:
      POSTGRES_DB: napolitana
      POSTGRES_USER: gduser
      POSTGRES_PASSWORD: gduser
    volumes:
      - postgres_data:/var/lib/postgresql/data
    networks:
      - napolitana-network

  backend:
    build:
      context: ./NapolitanaBack
      dockerfile: Dockerfile
    image: backend-image:latest
    ports:
      - "8081:8081"
    volumes:
      - C:\Users\mr\Desktop\storage:/app/storage  # Bind mount to local folder for shared data
    environment:
      - DB_URL=jdbc:postgresql://postgres:5432/napolitana
      - DB_USERNAME=gduser
      - DB_PASSWD=gduser
      - SERVER_PORT=8081
      - STORAGE=/app/storage
      - FRONT_ADDR=http://frontend:80
    depends_on:
      - postgres
    networks:
      - napolitana-network

  frontend:
    build:
      context: ./NapolitanaFront
      dockerfile: Dockerfile
    image: frontend-image:latest
    ports:
      - "80:80"  # Map port 80 of the container to port 80 of the host
    volumes:
      - C:\Users\mr\Desktop\storage:/usr/share/nginx/html/assets/storage  # Bind mount to local folder for shared data
    depends_on:
      - backend  # Ensure backend service starts first
    networks:
      - napolitana-network

volumes:
  postgres_data:

networks:
  napolitana-network:

核心原因

浏览器运行在宿主机的网络环境中,而非Docker内部的napolitana-network网络,因此无法识别Docker Compose定义的backend服务域名(该域名仅在Docker内部网络可解析)。当前Angular的BASE_URL直接指向http://backend:8081/api,浏览器会尝试在本地DNS查找backend,必然失败。

此外,虽然你配置了Nginx反向代理规则,但前端并未利用该代理,而是直接请求后端服务,完全绕开了Nginx的转发逻辑。


解决方案

1. 修改Angular环境配置,利用Nginx代理

将Angular的环境配置改为相对路径,让请求发送到当前前端所在域名(即Nginx的宿主机80端口),再由Nginx转发到后端:

export const environment = {
    BASE_URL: '/api'
}

2. 调整Nginx反向代理路径(确保逻辑正确)

检查/api/的转发规则:如果Spring Boot接口本身带有/api前缀,当前配置无需修改;如果接口无前缀,需给proxy_pass末尾添加斜杠,避免路径拼接错误:

location /api/ {
    proxy_pass http://backend:8081/;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $http_host;
}

3. 修正CORS配置(可选,避免后续跨域问题)

现在前端通过Nginx代理请求后端,浏览器会认为是同域名请求,CORS规则不再生效。但如果后续有直接访问后端的场景,可将FRONT_ADDR改为宿主机地址(如http://localhost:80),或保留http://frontend:80(供Docker内部通信使用),确保Spring Boot的CORS配置允许该来源。

4. 重新构建并启动服务

修改配置后,需重新构建前端镜像并重启所有服务:

docker-compose down
docker-compose build frontend
docker-compose up -d

内容的提问来源于stack exchange,提问作者Ramez wechteti

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:25:58