带有 Heroku 的 Quarkus 数据源

Quarkus datasource with Heroku

我正在尝试在 Heroku 上部署我的 Quarkus 应用程序。它工作正常,但我需要用固定值指定数据源参数。因为 Heroku 可能会轮换这个参数,所以这不是一个好主意。

在 Quarkus 中,我需要 application.properties 中的这 3 个参数:

quarkus.datasource.username
quarkus.datasource.password
quarkus.datasource.jdbc.url

Heroku 只给了我 1 个环境变量 (DATABASE_URL),它按以下方式定义了一个连接字符串: postgres://user:pass@server:port/db-name

我知道我可以像这样使用环境变量: quarkus.datasource.jdbc.url = jdbc:${DATABASE_URL}

但我需要拆分变量以提取用户和密码并更改前缀(postgresql 而不是 postgres)。

有人知道如何实现吗?

您可以为您的用例使用 JDBC_DATABASE_URLJDBC_DATABASE_USERNAMEJDBC_DATABASE_PASSWORD 环境变量。

有关更多详细信息,您可以在此处找到文档:https://devcenter.heroku.com/articles/connecting-to-relational-databases-on-heroku-with-java#using-the-jdbc_database_url

我创建了一个 bash 脚本来从 Heroku DATABASE_URL.

中提取三个 Quarkus 参数

它适用于 JVM 和 Native 版本。

我的application.properties:

quarkus.datasource.jdbc.url=${DB_JDBC_URL:jdbc-url}
quarkus.datasource.username=${DB_JDBC_USER:postgres}
quarkus.datasource.password=${DB_JDBC_PASSWORD:postgres}

简短版

# cut the DATABASE_URL after '@'
export DB_JDBC_URL=jdbc:postgresql://${DATABASE_URL#*@}

# substring the DATABASE_URL between '//' and ':'
export DB_JDBC_USER=$(expr $DATABASE_URL : '.*/\([^:]*\):.*')

# substring the DATABASE_URL between ':' and '@'
export DB_JDBC_PASSWORD=$(expr $DATABASE_URL : '.*:\([^@]*\)@.*')

长版

Bash 脚本

使用 heroku.sh 文件名将以下脚本保存在项目的根文件夹中。

#!/bin/sh
# =============================================================================
# This script automatically splits the Heroku ENV DATABASE_URL variable
# into the three JDBC variables needed from Quarkus.
# 
# It will only do the split if the DB_HEROKU_SPLIT is set to "true".
#
# If you set DB_HEROKU_SPLIT to 'false', you must pass the Quarkus parameters:
#   - DB_JDBC_URL;
#   - DB_JDBC_USER;
#   - DB_JDBC_PASSWORD.
# 
# For test purposes, you can set the DB_ECHO_VALUES to 'true' and check if the
# values are correct.
# 
# Pattern of DATABASE_URL from Heroku:
# --------------------------------------
#   postgres://username:password@host:port/databasename
# 
# Pattern of JDBC variables of Quarkus:
# -------------------------------------
#   quarkus.datasource.jdbc.url=jdbc:postgresql://host:port/databasename
#   quarkus.datasource.username=username
#   quarkus.datasource.password=password
# 
# =============================================================================

echo DB_HEROKU_SPLIT=[$DB_HEROKU_SPLIT] 

# check for 'true' in string (case insensitive)
if [[ "${DB_HEROKU_SPLIT,,}" == "true" ]]; then

  # cut the DATABASE_URL after '@'
  export DB_JDBC_URL=jdbc:postgresql://${DATABASE_URL#*@}

  # substring the DATABASE_URL between '//' and ':'
  export DB_JDBC_USER=$(expr $DATABASE_URL : '.*/\([^:]*\):.*')

  # substring the DATABASE_URL between ':' and '@'
  export DB_JDBC_PASSWORD=$(expr $DATABASE_URL : '.*:\([^@]*\)@.*')

fi

# check for 'true' in string (case insensitive)
if [[ "${DB_ECHO_VALUES,,}" == "true" ]]; then

  echo DATABASE_URL=[$DATABASE_URL]
  echo DB_JDBC_URL=[$DB_JDBC_URL]
  echo DB_JDBC_USER=[$DB_JDBC_USER] 
  echo DB_JDBC_PASSWORD=[$DB_JDBC_PASSWORD]

fi

Docker 忽略

记得将此文件包含到您的 .dockerignore:

*
!heroku.sh
!target/*-runner
!target/*-runner.jar
!target/lib/*
!target/quarkus-app/*

Dockerfile.jvm

将原来的ENTRYPOINT替换为:

# commands from original Quarkus Dockerfile.jvm file suppressed for breviety

COPY --chown=1001 heroku.sh /deployments/heroku.sh
RUN chmod 540 /deployments/heroku.sh

CMD [ "/bin/bash", "-c" , ". /deployments/heroku.sh && /deployments/run-java.sh" ]

Dockerfile.native

将原来的CMD替换为:

# commands from original Quarkus Dockerfile.jvm file suppressed for breviety

COPY --chown=1001 heroku.sh /work/heroku.sh
RUN chmod 540 /work/heroku.sh

CMD ["/bin/bash", "-c", ". ./heroku.sh && ./application", "-Dquarkus.http.host=0.0.0.0"]

Heroku 配置变量

DB_HEROKU_SPLIT

如果您希望 bash 脚本将 Quarkus 数据源变量提取给您,请将 DB_HEROKU_SPLIT 添加到您的 Heroku Config Vars 并将其设置为 true

将其设置为false,您可以在 Heroku Config Vars 中创建 Quarkus 数据源(DB_JDBC_URL、DB_JDBC_PASSWORD 和 DB_JDBC_PASSWORD)并将它们直接传递给Quarkus 绕过 bash 脚本。

DB_ECHO_VALUES

我还创建了一个 DB_ECHO_VALUES 变量,允许您在日志中显示数据源。如果要在屏幕上打印日志,只需将 DB_ECHO_VALUES 设置为 true。