Running ReactJS + Spring Boot Application with Docker Compose
Dockerfile for Spring Boot Application
FROM openjdk:11.0.4-jre
COPY build/libs/*.jar /app.jar
EXPOSE 8080
ENTRYPOINT ["java","-Djava.security.egd=file:/dev/./urandom","-jar","/app.jar"]
Running gradle build
generates the artifact under the build/libs
directory. Spring boot application exposes REST endpoint on port 8080
, and lets imagine a scenario that endpoints starts with the /api/*
path.
Dockerfile for React Application
React project can be build by yarn build
or npm run build
. It should be deployed on nginx
server. So we can use ngnix as the base image. We can configure the nginx with the following config:
The paths starts with /
will be redirected to nginx path and if it start with /api/
it is redirected to backend. We need to have this config as both backend and frontend is running on the same server. Now we can copy the build directory to nginx folder and and configuration to /etc/nginx/
folder.
FROM nginx:1.16.0-alpine
COPY --from=build /app/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
COPY ./nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
We can go one step further and build the project within container as well, and we can do in 2 steps in a Dockerfile:
# build environment
FROM node:12.4.0-alpine as build
WORKDIR /app
ENV PATH /app/node_modules/.bin:$PATH
COPY package.json /app/package.json
RUN npm install --silent
RUN npm install react-scripts@3.0.1 -g --silent
COPY . /app
RUN npm run build
# production environment
FROM nginx:1.16.0-alpine
COPY --from=build /app/build /usr/share/nginx/html
RUN rm /etc/nginx/conf.d/default.conf
COPY ./nginx/nginx.conf /etc/nginx/conf.d
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
Docker-compose file
version: "3"
services:
db:
image: "postgres"
container_name: "postgres"
environment:
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=root
- POSTGRES_DB=postgres
ports:
- "5432:5432"
volumes:
- ./db-data:/var/lib/postgresql/data
backend:
image: "turkogluc/backend"
container_name: "backend"
ports:
- "8080:8080"
depends_on:
- db
frontend:
image: "turkogluc/frontend"
container_name: "frontend"
ports:
- "80:80"
depends_on:
- backend
Note that all containers work in the same network, and they can communicate with each by using the service names as db
, backend
or frontend
. For example in the spring application database connection string should be as jdbc:postgresql://db:5432/postgres
. And React application can make the rest calls to http://backend/api/*
. Now we can run all the services:
docker-compose up