Comment on page
Spring and PostgreSQL
In this tutorial, we'll learn how to deploy a Java application on Release, using the Spring application framework with PostgreSQL as its database.
We'll start with the
spring-postgres
example application from Awesome Compose. To help you focus on Spring and PostgreSQL only, we've created a repository with just the spring-postgres
folder copied from Awesome Compose.Because Release supports creating applications using Docker Compose, we won't need to change anything in the example repository to add this application to Release.
We'll take a look at how Release converts the settings from the application's
docker-compose.yaml
to a template for new environments, then we'll explore how we can change the Release application slightly to follow best practices.Before getting started, create a Release account and integrate your source control (GitHub, Bitbucket, or GitLab) account.
Fork the
spring-postgres
repository to a private or public repository in the version control service you integrated with your Release account.Let's take a look at the contents of the repository, and try to figure out how this application is installed and started.
The repository looks like this:
.
├── backend
│ ├── src
│ │ └── ... (Java app source)
│ ├── Dockerfile
│ └── pom.xml
├── db
│ └── password.txt
├── README.md
└── docker-compose.yaml
Two folders,
backend
and db
, correspond to the two services defined in docker-compose.yaml
:services:
backend:
build: backend
#...
db:
image: postgres
#...
#...
Let's look at the two services in more detail.
Excerpt from
docker-compose.yaml
:backend:
build: backend
ports:
- 8080:8080
environment:
- POSTGRES_DB=example
networks:
- spring-postgres
You'll notice that the
backend
folder contains a Dockerfile, which, combined with the build: backend
directive from docker-compose.yaml
, indicates that a Docker image needs to be built for the backend
service before starting a container.The service joins the
spring-postgres
network, and forwards port 8080
on the host to port 8080
on the container.This service has one environmental variable,
POSTGRES_DB
, which will be used as the PostgreSQL database name.In the
backend/src
folder, you'll find the source code and other resources for the Java application. Of special interest is the backend/src/main/resources/application.properties
file, where Spring boot looks for settings such as database connection strings.Excerpt from
docker-compose.yaml
:db:
image: postgres
restart: always
secrets:
- db-password
volumes:
- db-data:/var/lib/postgresql/data
networks:
- spring-postgres
environment:
- POSTGRES_DB=example
- POSTGRES_PASSWORD_FILE=/run/secrets/db-password
expose:
- 5432
This service needs a volume to save data in, has two environment variables (
POSTGRES_DB
and POSTGRES_PASSWORD_FILE
), and exposes the container port 5432
on the spring-postgres
network.The
db
folder contains only one file, password.txt
, which the db
service can access as /run/secrets/db-password
at runtime.We won't run this application locally for this tutorial, but if we were to run
docker-compose up
from the root of this folder, we would expect Docker to go through the following steps:- 1.Read
backend/Dockerfile
and pull dependencies from a Docker registry. - 2.Build a
backend
Docker image based on the steps inbackend/Dockerfile
, and store the image locally. - 3.Pull the
postgres
image from a Docker registry and store it locally. - 4.Start a
backend
container by running thebackend
image built in step 2. - 5.Start a
db
container by running thepostgres
image retrieved in step 3. - 6.Create a network called
spring-postgres
and connect both running containers to this network.
Now that we have an idea of how Docker Compose would run this application, let's see how to add the application to Release.

Create an application
Enter a unique name for your application, and pick the forked repository you created earlier, then click Next step.

Enter a name and pick your repository
- 1.Pick Analyze the repository, so Release can create services from
docker-compose.yaml
. - 2.Select the branch from your repository you'd like to track in this application.
- 3.Select the
docker-compose.yaml
file. - 4.Click Start analysis.

Pick your services
Release will read your Docker Compose file, and list the services found:

Pick your services showing analysis result
Click Next step.
Release will generate a template based on the services from your
docker-compose.yaml
file.
Generate an application template
This template will be used to create new environments, and the defaults should work as expected for most Docker Compose applications.
For this example application, we'll need to make two changes to the template.
The first change makes sure the
db
service always starts before the backend
service.The Spring app we're installing runs database initialization scripts on startup. If there's no database to initialize, the
backend
service will fail to start.The section of the template we want to edit is under
workflows.setup
and workflows.patch
. Instead of running setup steps in parallel, we want them to follow a set order.Change
workflows.setup
and workflows.patch
to look like this:workflows:
- name: setup
order_from:
- services.db
- services.backend
- name: patch
order_from:
- services.db
- services.backend
Change
parallelize
to order_from
, then list the tasks in the order we want Release to execute them: services.db
, then services.backend
.Release does not currently convert
expose
directives when importing services from Docker Compose. Add a container_port
for each port in your Docker Compose file. Read more about ports in our template schema.Add a container port to the
db
service by adding the lines below: services:
- name: db
+ ports:
+ - type: container_port
+ port: '5432'
This change exposes port
5432
on the database container to the private network between your services.After editing the template, click Next step.
The
docker-compose.yaml
file from our repo lists the environment variables needed for each service. Both services use POSTGRES_DB
, and the db
service has one extra variable, POSTGRES_PASSWORD_FILE
.The
postgres
Docker image can read a password from a file specified in the POSTGRES_PASSWORD_FILE
environment variable, or it can read the POSTGRES_PASSWORD
environment variable directly.Since Release supports adding secrets as environment variables, let's use a
POSTGRES_PASSWORD
environment variable instead of a password file.There's no database password environment variable in the
backend
service from docker-compose.yaml
, so we'll need to find out how the backend
service knows the database password.The Spring Boot application reads the database password from the
backend/src/main/resources/application.properties
file.In our example application, this file has a database password setting,
spring.datasource.password
, that looks like this:spring.datasource.password=${POSTGRES_PASSWORD:db-wrz2z}
The line above means that Spring will try to read the database password from the
POSTGRES_PASSWORD
environment variable, but will use the hard-coded value db-wrz2z
if the variable POSTGRES_PASSWORD
does not exist.We can see that
db-wrz2z
matches the password from db/password.txt
in our repository.Instead of using this hard-coded password, we can set the
POSTGRES_PASSWORD
environment variable.You'll notice that both the
db
and backend
services can read this same environment variable to get the database password.Let's set it to a random string, like
xUnlL9U9J1Dh
.
Set your environment variables
Edit the YAML environment variables in Release to look like this:
---
defaults:
- key: POSTGRES_DB
value: example
- key: POSTGRES_PASSWORD
value: UNwmSZpmo9Aj
secret: true
services:
backend: []
db: []
Because both environment variables are used by both services, we don't need to specify them individually for each service. All services get all environment variables listed under the
defaults
section.You'll notice that we marked
POSTGRES_PASSWORD
as secret. This means that POSTGRES_PASSWORD
will be saved to an encrypted vault, and hidden from the Release interface after you save your changes.Click Next step to save your environment variables.
This application does not use any build arguments, so we can click Next step.
Click Save and deploy to create your application.
Release will now pull your repository and run
docker build
to build a Docker image of your backend
service, before setting up and deploying your two services, db
and backend
.After the build, setup, and deployment workflow completes, navigate to your new environment and click on the URL for the backend service.

Service hosted URL
This request runs the
controllers.HomeController.showHome
Java function on the backend
service, which reads a value from the PostgreSQL database running on the db
service, and returns the string Hello from Docker!
.
Hello from Docker!
If you don't see the result above, you can view the logs for each service in your environment to see whether either service logged any errors.
To view a service's logs, navigate to your environment's details page, scroll down to the list of services, and click on logs.

Service logs
If you would like to learn more about running Spring applications using Docker, view the Spring Boot with Docker guide from Spring.
Last modified 8mo ago