> For the complete documentation index, see [llms.txt](https://docs.release.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.release.com/guides-and-examples/common-setup-examples/spring-postgresql.md).

# 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](https://github.com/docker/awesome-compose/). To help you focus on Spring and PostgreSQL only, we've created a repository with just the [`spring-postgres`](https://github.com/awesome-release/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.

## Requirements

Before getting started, [create a Release account](/getting-started/create-an-account.md) and [integrate your source control](/integrations/source-control-integrations.md) (GitHub, Bitbucket, or GitLab) account.

## Fork the `spring-postgres` example repository

Fork the [`spring-postgres`](https://github.com/awesome-release/spring-postgres) repository to a private or public repository in the version control service you integrated with your Release account.

## An overview of the application

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`:

```yaml
services:
  backend:
    build: backend
    #...
  db:
    image: postgres
    #...
#...
```

Let's look at the two services in more detail.

### The backend service

Excerpt from `docker-compose.yaml`:

```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.

### The `db` service

Excerpt from `docker-compose.yaml`:

```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
```

The `db` (short for database) service starts a container based on the [`postgres`](https://hub.docker.com/_/postgres) docker image.

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.

### How Docker Compose runs this app

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 in `backend/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 the `backend` image built in step 2.
5. Start a `db` container by running the `postgres` image retrieved in step 3.
6. Create a network called `spring-postgres` and connect both running containers to this network.

## Create a new application on Release

Now that we have an idea of how Docker Compose would run this application, let's see how to add the application to Release.

Log into Release, and [create an application](https://github.com/releasehub-com/docs/blob/main/examples/broken-reference/README.md) by clicking on **Create new app**.

![Create an application](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-39b54bf307966baba57d2897edfd515e48e4a5c6%2Fspring-postgres-create-application.png?alt=media\&token=e0f178aa-266b-4041-b18e-7dcbc566080d)

## Name your application and select your repository

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](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-a3e486cbb029ce9b1bd0bfdefe7ac18e2ec3d0ee%2Fspring-postgres-name-and-repo.png?alt=media\&token=3b26404e-b4dc-4497-a4d8-30ad913d4880)

## Pick your services

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](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-4aad5c62898999be6dd9fc85f6c232cc941a0e86%2Fspring-postgres-pick-services.png?alt=media\&token=45048fa3-f379-421f-bd62-406cb9cb20ab)

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

![Pick your services showing analysis result](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-ea2379f1ba13660e9c43535907374b11f023822a%2Fspring-postgres-pick-services-analyzed.png?alt=media\&token=bc5d2c44-f504-4db8-b211-a65168d8274a)

Click **Next step**.

## Generate a template

Release will generate a template based on the services from your `docker-compose.yaml` file.

![Generate an application template](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-fd71a28f2173baa3480bb53af9c312f66821cce2%2Fspring-postgres-application-template.png?alt=media\&token=4011dab7-e926-4f68-a9c4-516ae780344c)

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.

### Start `db` before `backend`

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:

```yaml
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`.

### Expose a container port on `db`

{% hint style="info" %}
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](/reference-documentation/application-settings/application-template/schema-definition.md#ports) in our template schema.
{% endhint %}

Add a container port to the `db` service by adding the lines below:

```diff
  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.

You can read more about [workflow parallelization](/reference-documentation/application-settings/application-template/schema-definition.md#workflow-parallelization) in the template schema documentation.

After editing the template, click **Next step**.

## Environment variables

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`.

### Setting the PostgreSQL database password via an environment variable

The [`postgres`](https://hub.docker.com/_/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](/reference-documentation/environment-settings/environment-specific-environment-variables/secrets.md), 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:

```bash
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

![Set your environment variables](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-26f196aeb0fdf13cc545dba438fed5ff53ac645b%2Fspring-postgres-pick-services-env-vars.png?alt=media\&token=b2798d1c-b3e2-4d87-bfc8-c4fa7d3dd07c)

Edit the YAML environment variables in Release to look like this:

```yaml
---
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.

## Build arguments

This application does not use any build arguments, so we can click **Next step**.

## Save and deploy

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`.

## View the resulting application

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](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-f4d2798f640c6b922f645720dfe22efd3e013aae%2Fspring-postgres-hostname.png?alt=media\&token=34205252-e931-4433-802d-9d3b70d4915f)

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!](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-e451f52601cf7d0d5cb366da54523594204b3ef3%2Fspring-postgres-result.png?alt=media\&token=dc099039-ca92-4af7-902f-b754eed73cd5)

## Troubleshooting

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](https://585411240-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M1neGLLQ0sDXeK6ooSo%2Fuploads%2Fgit-blob-e743eccd9a5bf84580c46e4ef220659611207bbb%2Fspring-postgres-service-logs.png?alt=media\&token=9d1302f1-5b7a-4a08-83c5-ab4d7257e08e)

## Further reading

If you would like to learn more about running Spring applications using Docker, view the [Spring Boot with Docker](https://spring.io/guides/gs/spring-boot-docker/) guide from Spring.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.release.com/guides-and-examples/common-setup-examples/spring-postgresql.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
