I have a full stack application that I'm trying to setup with docker compose. Each application is running fine in their containers but I cannot make any requests to my backend API from the front end application. I used netshoot/curl/ping/nmap to verify that requests from the frontend container to backend container (http://backend:8080) are connecting. They are connecting, but when I make the request from my frontend application, which is running in a nginx server, the requests do not go through. I used tcpdump in the backend container (port 8080) to see if the request were coming through and there was no traffic when requests made from react app. I used tcpdump in the frontend container (port 80) to see if the request were being sent and there was no traffic when requests made from react app.
I've tried two different request configurations for my frontend request:
- Request made to http://backend:8080 - with no proxy pass in nginx
- Request made to http://localhost/api - with proxy pass shown in nginx config below
I'm pretty sure it is not a cors issue, but I configured cors in Spring to allow from frontend.
Docker, Nginx, and Spring Security config files below.
Spring Security Config:
@Slf4j
@Configuration
@EnableWebSecurity
public class SecurityConfig {
private final JwtFilter jwtFilter;
private final UserProfileService userProfileService;
@Autowired
public SecurityConfig(JwtFilter jwtFilter, UserProfileService userProfileService) {
this.jwtFilter = jwtFilter;
this.userProfileService = userProfileService;
}
//Using JWT for auth
@Bean
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.cors(cors -> cors.configurationSource(corsConfigurationSource())).csrf(CsrfConfigurer::disable)
.authorizeHttpRequests(req -> req.requestMatchers("/user/login","/user/register").permitAll()
.anyRequest().authenticated())
.sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
.addFilterBefore(jwtFilter, UsernamePasswordAuthenticationFilter.class);
return http.build();
}
@Bean
public AuthenticationManager authenticationManager() {
DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userProfileService);
authProvider.setPasswordEncoder(passwordEncoder());
return new ProviderManager(authProvider);
}
@Bean
public CorsConfigurationSource corsConfigurationSource() {
CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(List.of("http://localhost:5173", "http://192.168.128.54:80"));
configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS"));
configuration.setAllowedHeaders(List.of("*"));
configuration.setAllowCredentials(true);
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
source.registerCorsConfiguration("/**", configuration);
return source;
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
Docker Compose File
services:
backend:
build:
context: ./shewstringBE
dockerfile: Dockerfile
container_name: backend
ports:
- "8081:8080"
environment:
- SPRING_PROFILES_ACTIVE=prod
- SHEW_DB_URL=***removed for security***
- SHEW_DB_USER=***removed for security***
- SHEW_DB_PW=***removed for security***
- SHEW_JWT_SECRET_KEY=***removed for security***
networks:
app-network:
ipv4_address: 192.168.128.4
depends_on:
- mysql
frontend:
build:
context: ./shewstringFE
dockerfile: Dockerfile
container_name: frontend
ports:
- "81:80"
environment:
- SHEW_FE_TEST_PW=***removed for security***
networks:
app-network:
ipv4_address: 192.168.128.54
mysql:
image: mysql:latest
container_name: mysql
environment:
MYSQL_ROOT_PASSWORD: ***removed for security***
MYSQL_DATABASE: ***removed for security***
ports:
- "3307:3306"
volumes:
- mysql_data:/var/lib/mysql
networks:
- app-network
networks:
app-network:
driver: bridge
ipam:
config:
- subnet: 192.168.128.0/24
volumes:
mysql_data:
driver: local
Nginx Config
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name _;
location / {
try_files $uri $uri/ =404;
}
location /api/ {
proxy_pass http://backend:8080/;
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-Fowrarded-Proto $scheme;
}
Frontend Dockerfile:
FROM node:16-alpine as build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . ./
RUN npm run build
RUN ls /app
FROM ubuntu/nginx:latest
RUN apt update && apt install vim -y && apt install curl -y
COPY --from=build /app/dist /var/www/html
EXPOSE 80FROM node:16-alpine as build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm install
COPY . ./
RUN npm run build
RUN ls /app
FROM ubuntu/nginx:latest
RUN apt update && apt install vim -y && apt install curl -y
COPY --from=build /app/dist /var/www/html
EXPOSE 80
Backend Dockerfile
FROM openjdk:21-jdk-slim
WORKDIR /app
COPY target/shewstringBE-0.0.1-SNAPSHOT.jar app.jar
EXPOSE 8080
CMD ["java", "-jar", "app.jar"]