#1
When working with Quarkus—a fast and efficient Java framework—it's essential to handle environment configurations cleanly, especially when connecting to external services like PostgreSQL. Using Docker locally and Kubernetes for production, you can configure PostgreSQL with minimal hassle by leveraging Quarkus profiles (dev and prod) and separating settings in application-dev.properties and application-prod.properties.
This guide covers how to configure PostgreSQL in Quarkus using application.properties, with a focus on simplicity, modularity, and best practices for both development and production environments.

Step 1: Add Required Dependencies

Start by including the necessary dependencies in your pom.xml. We assume you're also using the PostgreSQL and Kubernetes config extensions:
<dependencies>
  <!-- Quarkus PostgreSQL driver -->
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-jdbc-postgresql</artifactId>
  </dependency>

  <!-- Quarkus Hibernate ORM -->
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-hibernate-orm</artifactId>
  </dependency>

  <!-- Optional: Kubernetes config support -->
  <dependency>
    <groupId>io.quarkus</groupId>
    <artifactId>quarkus-kubernetes-config</artifactId>
  </dependency>
</dependencies>

Step 2: Set Up PostgreSQL Using Docker (for Dev)

Use Docker to spin up a local PostgreSQL instance:
docker run --name postgres-dev -e POSTGRES_USER=devuser -e POSTGRES_PASSWORD=devpass -e POSTGRES_DB=devdb -p 5432:5432 -d postgres:14
This sets up a development-ready PostgreSQL container with the database devdb and accessible credentials.

Step 3: Configure application-dev.properties

Create a file called application-dev.properties in src/main/resources and configure it like so:
%dev.quarkus.datasource.db-kind=postgresql
%dev.quarkus.datasource.username=devuser
%dev.quarkus.datasource.password=devpass
%dev.quarkus.datasource.jdbc.url=jdbc:postgresql://localhost:5432/devdb
%dev.quarkus.datasource.jdbc.driver=org.postgresql.Driver

%dev.quarkus.hibernate-orm.database.generation=drop-and-create
%dev.quarkus.hibernate-orm.sql-load-script=import.sql

This tells Quarkus how to connect to your local database and to auto-generate schema on app startup. You can adjust database.generation depending on whether you want to recreate the schema each time.

Step 4: Activate the Development Profile

Run your app in development mode using:
./mvnw quarkus:dev -Dquarkus.profile=dev
Quarkus will automatically pick up the settings from application-dev.properties.

Step 5: Production Configuration with Kubernetes

In production, hardcoding credentials or database URLs isn't ideal. Kubernetes ConfigMaps and Secrets provide a safe and dynamic way to manage these values.

5.1: Create a Kubernetes ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: postgres-config
data:
  db-kind: postgresql
  jdbc-url: jdbc:postgresql://postgres-service:5432/proddb
  hibernate-dialect: org.hibernate.dialect.PostgreSQLDialect

5.2: Create a Kubernetes Secret

apiVersion: v1
kind: Secret
metadata:
  name: postgres-secret
type: Opaque
data:
  username: cHJvZHVzZXI=  # base64 for 'produser'
  password: cHJvZHBhc3M=  # base64 for 'prodpass'

Step 6: Configure application-prod.properties

Now, reference the environment variables in application-prod.properties:
%prod.quarkus.datasource.db-kind=${DB_KIND:postgresql}
%prod.quarkus.datasource.username=${DB_USERNAME}
%prod.quarkus.datasource.password=${DB_PASSWORD}
%prod.quarkus.datasource.jdbc.url=${JDBC_URL}
%prod.quarkus.datasource.jdbc.driver=org.postgresql.Driver

%prod.quarkus.hibernate-orm.database.generation=validate
%prod.quarkus.hibernate-orm.dialect=${HIBERNATE_DIALECT}
%prod.quarkus.kubernetes-config.enabled=true
%prod.quarkus.kubernetes-config.config-maps=postgres-config
%prod.quarkus.kubernetes-config.secrets=postgres-secret

Step 7: Use Environment Variables in Kubernetes Deployment

Inject the environment variables into your container like this:
env:
  - name: QUARKUS_PROFILE
    value: prod
  - name: DB_KIND
    valueFrom:
      configMapKeyRef:
        name: postgres-config
        key: db-kind
  - name: JDBC_URL
    valueFrom:
      configMapKeyRef:
        name: postgres-config
        key: jdbc-url
  - name: HIBERNATE_DIALECT
    valueFrom:
      configMapKeyRef:
        name: postgres-config
        key: hibernate-dialect
  - name: DB_USERNAME
    valueFrom:
      secretKeyRef:
        name: postgres-secret
        key: username
  - name: DB_PASSWORD
    valueFrom:
      secretKeyRef:
        name: postgres-secret
        key: password

Step 8: Final Thoughts

Setting up PostgreSQL in Quarkus using profile-based application.properties allows you to maintain clear separation between development and production configurations. With Docker for local development and Kubernetes for production, this setup ensures flexibility, security, and maintainability.
Whether you're building a lightweight REST API or a full-scale reactive application, this approach ensures your PostgreSQL integration is both robust and adaptable to various deployment environments.

image quote pre code