angularspring-bootdockerdocker-composedockerfile

Problem while dockerizing angular/spring boot application


I'm trying to dockerize an angular application with a spring boot one and setting a postgres Database. I setup everything but I'm having problems with nginx I suppose it doesn't forward the request to the backend application(spring boot), even though pinging works fine.

So I created a Dockerfile for the spring boot application :

# 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"]

And I have setup as well application.properties to get environment variables like follows :

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

I have setup 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("*");
            }
        };
    }
}

For the angular application I have setup a 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;"]

with this default.conf configuration file in nginx server :

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;
    }
}

While this is the base url used by services in this angular application :

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

and finally this is the 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:

when I'm testing everything turns out the angular application can't resolve backend:8081, I mean I always get ERR_NAME_NOT_RESLOVED for each request made by angular like this :

Response

I have tried lots of things but couldn't resolve the problem because I don't get it , is it a problem with nginx or CORS error or something else ?

And thanks in advance for anyone who is helping.


Solution

  • ERR_NAME_NOT_RESLOVED is a DNS error meaning that the hostname could not be resolved to an IP address. The issue likely is that even though your Angular app is hosted in a container, the code is actually running in your browser when you navigate to the app and the hostname is only resolved within the container network. See this related question, net::ERR_NAME_NOT_RESOLVED in browser using docker-compose.