A step-by-step guide to containerize a Spring Boot App with PostgreSQL
![](https://static.wixstatic.com/media/904ca2_6ed73cf3087e47cc88c5286cba444ae4~mv2.png/v1/fill/w_85,h_32,al_c,q_85,usm_0.66_1.00_0.01,blur_2,enc_auto/904ca2_6ed73cf3087e47cc88c5286cba444ae4~mv2.png)
Before we get started on how to dockerize the application, lets understand what is docker and what is the need to use Docker.
What is Docker?
Docker is a open source platform that enables developers to build, test and deploy the applications quickly. Docker packages the application with the necessary libraries, system tools, code, configuration files, dependencies, runtime and everything that the application needs to run into a container. Packaging the Spring Boot app into a Docker container ensures consistent behavior across different platforms.
Why Docker?
Docker supports a wide range of programming languages and frameworks. Whether you are building a web application or a microservices architecture, Docker provides a consistent platform for development and deployment.
Using Docker, we can quickly deploy the application in any environment without worrying about incompatible issues regardless of the machine’s configuration settings.
Step 1 : Create a Spring Boot Application
To create a Spring Boot Application, we can either use Spring Boot plugin in IntelliJ IDE or use Spring initializer.
I created a simple application with 2 entities Program and Batch and have performed CRUD operations on both Program and Batch. This is how the project structure looks.
Step 2 : Install Docker Desktop
Click Download Docker Desktop, it will take you to the site from where you can download Docker Desktop.
Step 3 : Package the Application into a JAR File
Run the following command to see the executable jar file generated in the target folder. -DskipTests option will skip the tests.
mvn package -DskipTests
Step 4 : Create Dockerfile
Lets create a file named Dockerfile in the root directory of our application. But, What is a Dockerfile?
A Dockerfile is a text file that contains all commands/set of instructions needed to build an image.
FROM openjdk:17
COPY ./target/*.jar demo.jar
ENTRYPOINT ["java", "-jar", "/demo.jar"]
FROM openjdk:17 : A valid Dockerfile must start with a FROM instruction. It sets the base image for the subsequent instructions. Since we are dockerizing a Java Spring Boot application, we are going to pull the openjdk:17
COPY ./target/*.jar demo.jar : It copies the JAR file from the target folder and adds them to the directory of the container at the path which is by default /
ENTRYPOINT [“java”, “-jar”, “/demo.jar”] : It specifies the command that will be executed when a container starts. It is configured to run a Java application packaged as a JAR file named demo.jar
Step 5 : Create Docker Compose file
Lets create a file named docker-compose.yml in the root directory of our application. So, what is Docker Compose?
Docker Compose is used to define and run multi-container applications. Specifying the required images, exposing the ports, managing the networks, setting up the volumes, declaring the dependencies, setting the environment variables, all these can be defined/configured here in a single yml file.
version: "3.8"
services:
postgresdb:
image: postgres
env_file: ./.env
environment:
- POSTGRES_USER=$POSTGRESDB_USER
- POSTGRES_PASSWORD=$POSTGRESDB_ROOT_PASSWORD
- POSTGRES_DB=$POSTGRESDB_DATABASE
ports:
- $POSTGRESDB_LOCAL_PORT:$POSTGRESDB_DOCKER_PORT
volumes:
- db:/var/lib/postgres
- ./init.sql:/docker-entrypoint-initdb.d/initdb.sql
app:
depends_on:
- postgresdb
build: .
env_file: ./.env
environment:
- SPRING_DATASOURCE_URL=jdbc:postgresql://postgresdb:$POSTGRESDB_DOCKER_PORT/$POSTGRESDB_DATABASE
- SPRING_DATASOURCE_USERNAME=$POSTGRESDB_USER
- SPRING_DATASOURCE_PASSWORD=$POSTGRESDB_ROOT_PASSWORD
- SPRING_JPA_HIBERNATE_DDL_AUTO=update
ports:
- $SPRING_LOCAL_PORT:$SPRING_DOCKER_PORT
volumes:
db:
version refers to the docker-compose version
services defines the services/containers that we need to run
postgresdb is a custom name for database container
image is the image which we have to pull. Here we are pulling postgres Docker official image from the dockerhub (a container registry built for developers and open source contributors to find, use, and share their container images)
env_file:./.env is a text file to define environment variables
environment defines/sets the environment variables for the PostgreSQL instance
ports defines the custom port to run the container. It maps the container’s internal port to the host port
volumes — db:/var/lib/postgres - This database volume ensures that the PostgreSQL data persists between container restarts. It maps the local volume to the directory within the PostgreSQL container. ./init.sql:/docker-entrypoint-initdb.d/initdb.sql — This initialization script volume mounts the script from the local directory into the directory within the PostgreSQL container. It will be executed when the PostgreSQL container starts up, to initialize the database with schema or data setup scripts
app is a custom name for application container
depends_on tells the app container that it should not start until the postgresdb container is up and running
build builds a new image from our Dockerfile which is in the root directory
environment defines/sets the environment variables required for the Spring Boot application to connect to the PostgreSQL database
volumes: db: The data stored in this named volume will be persisted even if the container is stopped
Note that the datasource URL contains the name of the database container postgresdb instead of localhost SPRING_DATASOURCE_URL=jdbc:postgresql://postgresdb:$POSTGRESDB_DOCKER_PORT/$POSTGRESDB_DATABASE
Step 6 : Create .env file
Lets create a .env file in the root directory of our project.
This .env file is a text file used to define environment variables that should be made available to Docker containers when running docker compose up. This file typically contains key-value pairs of environment variables.
POSTGRESDB_USER=lms
POSTGRESDB_ROOT_PASSWORD=lms
POSTGRESDB_DATABASE=lmsdb
POSTGRESDB_LOCAL_PORT=5432
POSTGRESDB_DOCKER_PORT=5432
SPRING_LOCAL_PORT=8080
SPRING_DOCKER_PORT=8080
Step 7 : Create init.sql file
In the init.sql file, Include the queries for creating the table and inserting data into the table based on the entities used in the application. I have provided a sample of what needs to be included in the init.sql file.
CREATE TABLE public.tbl_lms_program(
program_id integer NOT NULL,
creation_time timestamp(6) without time zone,
last_mod_time timestamp(6) without time zone,
program_description character varying(255) COLLATE pg_catalog."default",
program_name character varying(255) COLLATE pg_catalog."default",
program_status character varying(255) COLLATE pg_catalog."default",
CONSTRAINT tbl_lms_program_pkey PRIMARY KEY (program_id)
);
INSERT INTO public.tbl_lms_program(
program_id, creation_time, last_mod_time, program_description, program_name, program_status)
VALUES (1, '2024-05-05 01:43:02.035','2024-05-05 01:43:02.035', '001', 'SQL', 'Active');
This is how the project structure should look like at this point.
Once we have the docker-compose.yml, Dockerfile, .env and init.sql files ready, we can build the image and run the application with Docker Compose using a single command. Run this command in the root directory of the project.
docker compose up
This will start the containers for all the services defined in the docker-compose.yml file. You can see that the application is built using Docker Compose.
You can see the list of running containers (both the database and the application) using the command docker ps or using Docker Desktop
Now that the containers are up and running, we should be able to access the application at http://localhost:8080 on a browser or Postman
So, By following these steps, we have successfully containerized the Spring Boot application.
Conclusion :
In conclusion, Dockerizing a Spring Boot application with PostgreSQL offers numerous benefits, including enhanced portability, consistency, and scalability. By following the steps outlined in this article, now, we know how to containerize the application.
Thank you for joining me on this Dockerization adventure! I hope you found this article helpful and informative. If you have any questions or would like to share your experiences, I’d love to hear from you. Happy Dockerizing!