1

I have a problem with dockerizing Spring Boot app. My docker-compose project consists of 4 parts:

  • back - it`s just Spring Boot application with Tomcat on 8080. Here are my controllers for front app.
  • front - Nginx + Angular
  • core - mainly consists of a TCP server for receiving some information to DB in database-app, implemented on a simple Java Socket.
  • database - Postgres, which I just download from the Docker Hub and configure to create the database necessary for the back-application.

My goal is to use my front-app, which is open in the browser on the host machine, manipulate data from the database from the database-app, through the controllers of my back-app.

So, I don't have any problems with building and running. Ports mapping for core, database and front apps works excellent. But not for back. I don't have any access from host to back-container from localhost:8080(curl requests from the host to container return an empty response, but curl in container bash works fine). In back-app I used Spring Security, so CORS is configured to allow all requests, and CSRF is disabled, if it's matter.

Generously apologize for my broken English!

Back Dockerfile

FROM maven:3.5-jdk-8 AS build
COPY src /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean package

FROM gcr.io/distroless/java  
ARG JAR_FILE=target/*.jar
COPY --from=build /usr/src/app/${JAR_FILE} /usr/app/back.jar
ENTRYPOINT ["java","-jar","/usr/app/back.jar"]

Core Dockerfile

FROM maven:3.5-jdk-8 AS build
COPY src /usr/src/app/src  
COPY pom.xml /usr/src/app  
RUN mvn -f /usr/src/app/pom.xml clean package

FROM gcr.io/distroless/java  
ARG JAR_FILE=target/*.jar
COPY --from=build /usr/src/app/${JAR_FILE} /usr/app/core.jar
ENTRYPOINT ["java","-jar","/usr/app/core.jar"]

Front Dockerfile

FROM node:12 as builder
COPY package.json package-lock.json ./
RUN npm install && mkdir /app && mv ./node_modules ./app
WORKDIR /app
COPY . .
RUN npm run ng build -- --deploy-url=/ --prod

FROM nginx
COPY ./.nginx/nginx.conf /etc/nginx/nginx.conf
RUN rm -rf /usr/share/nginx/html/*
COPY --from=builder /app/dist/snsr-front-app /usr/share/nginx/html
ENTRYPOINT ["nginx", "-g", "daemon off;"]

UPDATED 1: Dockerfile(s) are still the same.

docker-compose.yml

version: '3'

services:

    snsr-front-app:
        build: ./snsr-front-app
        ports: 
            - 4200:80
        depends_on: 
            - snsr-back-app
        image: mxmtrms/snsr-front-app
        networks: 
            - front-net

    snsr-back-app:
        build: ./snsr-back-app
        depends_on: 
            - database
        image: mxmtrms/snsr-back-app
        networks: 
            - back-net
            - front-net
        expose: 
            - 8080
        environment: 
            DB_URL: database
            DB_PORT: 5432


    snsr-core-app:
        build: ./snsr-core-app
        ports: 
            - 3000:3000
        depends_on: 
            - database
        image: mxmtrms/snsr-core-app
        networks:
            - back-net

    database: 
        image: postgres
        environment: 
            POSTGRES_USER: postgres
            POSTGRES_PASSWORD: masterkey
            POSTGRES_DB: snsr
        ports: 
            - 5432:5432
        networks: 
            - back-net
networks:
  back-net:
  front-net:

nginx.conf

worker_processes 4;

events { worker_connections 1024; }

http {

    upstream frontend {
        server 0.0.0.0:80;
    }
    upstream backend {
        server snsr-back-app:8080;
    }

    server {

        listen 80;
        root  /usr/share/nginx/html;
        include /etc/nginx/mime.types;

        location / {
            proxy_pass http://frontend;
            try_files $uri /index.html;
        }

        location /api {
            proxy_set_header Host $host;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://backend;
        }
    }
}

UPDATE 2 Backend logs: https://gist.github.com/mxmtrms/ff12e2481d0ccc2781f15a961de6eab9

docker ps: https://gist.github.com/mxmtrms/2baaadc0e4873fc8bb28453d5c6d04f4

2 Answers2

0

Frontend serve static content when you open your site in browser its work fine because you configure frontend port publiclly in nginx but when you perform any action its looking for backend url if backend url is not publically open then it can not able to make request. so you need to define your backend port in nginx so frontend can able to connect.

I hope it may help you. And also my english not that much good so sorry for that :)

You can define nginx configuration in your default.conf like this -

server {
    server_name hostname.com; // this is basically a host url where your application running
    location / {
        proxy_pass http://frontend; //this part will define in other file called upstream.conf
    }
    location /api { //I have consider all backend rest end point start through /api
        proxy_pass http://backend; //this part will define in other file called upstream.conf
    }
}

And then You need to create a new file in same directory upstream.conf and put given configuration -

upstream frontend {
    server 0.0.0.0:8091;
}
upstream backend {
    server 0.0.0.0:8081;
}

In the end just in your angular environment file put apiUrl - http://hostname.com/api

I hope it will help.

Vaibhav
  • 31
  • 1
  • 6
  • Yes, thanks for your reply. But, unfortunately, I have not reached the stage of setting up the work of the front and back. The `localhost:8080`, in principle, is not accessible from the host, since curl returns for any request empty respones, not only from browser and Nginx. – Maksim Termosa May 23 '20 at 17:50
  • is 8080 available on host? It could be taken by some running app – Alexander Pavlov May 24 '20 at 02:51
  • @MaksimTermosa I have edited my answer You can check the nginx configuration accordingly I hope its works. – Vaibhav May 24 '20 at 16:39
  • @AlexanderPavlov, yes it's available, of course. @Vaibhav I change my `nginx.config` based on your code snippets(see in my question UPDATED). But for some reason, Nginx threw errors about not being able to find upstreams when I put them in `upstream.conf`. So I just put them in `nginx.conf`. – Maksim Termosa May 25 '20 at 14:39
  • @Vaibhav, now for requst `curl --location --request POST 'http://localhost:4200/api/auth/signin' \ --header 'Content-Type: application/json' \ --data-raw ''` it throws: `[error] 6#6: *1 connect() failed (111: Connection refused) while connecting to upstream, client: 172.21.0.1, server: , request: "POST /api/auth/signin HTTP/1.1", upstream: "http://172.21.0.2:8080/api/auth/signin", host: "localhost:4200"`. And I can't even ping my `snsr-back-app:8080` (which is exposed) from `snsr-front-app` container by `telnet snsr-back-app 8080` it's return `Connection refused`. – Maksim Termosa May 25 '20 at 14:59
  • Check backend logs - probably it could not start for some reason, e.g. cannot connect database or beans misconfiguration – Alexander Pavlov May 25 '20 at 15:00
  • when you call `docker ps` - do you see backend in the list? What is its uptime after a few minutes - if it keeps restarting then uptime always will be few seconds – Alexander Pavlov May 25 '20 at 15:02
  • @AlexanderPavlov, checked many times. Now I will add a link to the main question on github code snippet with back logs. – Maksim Termosa May 25 '20 at 15:03
  • @AlexanderPavlov, added links in UPDATE 2. – Maksim Termosa May 25 '20 at 15:23
  • 1
    @MaksimTermosa In your docker compose file for backend service you need to add ports: - 8080:8080 so its connected to outside word. – Vaibhav May 25 '20 at 18:39
  • @MaksimTermosa and from configuration side create file default.conf under nginx/conf.d/ folder and put the configuration that I have provided and create separate file upstream.conf in same directory with the configuration that I have provided and your nginx.conf commented out or move from there. you can try this because i have already using the same way and its work fine. – Vaibhav May 25 '20 at 18:48
  • Yeah, `docker ps` tells 8080 is not exposed to outside. You can check if backend is ok by querying from inside `docker exec snsr-collector_snsr-back-app_1 curl localhost:8080` – Alexander Pavlov May 25 '20 at 19:56
0

The solution to the problem was to change the server.host in the back container from localhost to 0.0.0.0, since when calling docker ps, you can see that this is where Docker redirects the port.

This is also said here: https://stackoverflow.com/a/57427805/12305316