环境配置

Goat 使用环境变量来配置应用程序、数据库连接、工作目录以及特定环境相关的设置。

在本地开发环境中,这些值通常存储在以下文件中:

.env

应用程序使用的变量名称以下列前缀开头:

GOAT_

文件 .env 应仅包含适用于本地环境的配置。不要将其视为存储生产环境密钥的位置,也不要在公共仓库中放入真实的密码、令牌或密钥。

重要变量

变量含义
GOAT_DEV启用应用程序的开发模式。
GOAT_DB_MAIN_HOST主 PostgreSQL 数据库的主机。
GOAT_DB_MAIN_PORT主 PostgreSQL 数据库的端口。
GOAT_DB_MAIN_USER主数据库用户。
GOAT_DB_MAIN_PASS主数据库用户的密码。
GOAT_DB_MAIN_NAME主数据库名称。
GOAT_DB_TEST_HOST测试所使用数据库的主机。
GOAT_DB_TEST_PORT测试数据库的端口。
GOAT_DB_TEST_USER测试数据库用户。
GOAT_DB_TEST_PASS测试数据库用户的密码。
GOAT_DB_TEST_NAME测试数据库名称。
GOAT_JWT_SECRET用于签署 JWT 令牌的密钥。
GOAT_URL_BASE应用程序的公共基础 URL。
GOAT_DIR_DATA应用程序数据目录。
GOAT_DIR_TMP本地临时文件目录。
GOAT_DIR_SHARED_TMP在进程或容器之间共享的临时目录。
GOAT_DOMAIN目标环境配置所使用的域名。

本地配置示例

最小化的本地环境配置可以如下所示:

GOAT_DEV=TRUE

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=admin
GOAT_DB_MAIN_PASS=local-password
GOAT_DB_MAIN_NAME=maindb

GOAT_JWT_SECRET=zmien-na-dlugi-losowy-sekret

GOAT_URL_BASE=http://localhost:8080/

示例中的值仅用于开发环境。

共享环境、预发布环境和生产环境的访问凭据应通过适用于相应环境的配置机制提供。

开发模式

使用以下变量:

GOAT_DEV

来指定应用程序是否以开发模式运行。

示例:

GOAT_DEV=TRUE

开发模式可能会影响应用程序的行为,包括:

  • 日志记录,
  • 诊断,
  • 错误处理,
  • 缓存,
  • 辅助工具,
  • 前端或后端的启动方式。

不要假定开发环境配置适用于生产环境。

主数据库配置

主 PostgreSQL 连接由以下一组变量指定:

GOAT_DB_MAIN_HOST
GOAT_DB_MAIN_PORT
GOAT_DB_MAIN_USER
GOAT_DB_MAIN_PASS
GOAT_DB_MAIN_NAME

示例:

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=admin
GOAT_DB_MAIN_PASS=local-password
GOAT_DB_MAIN_NAME=maindb

这些值由应用程序以及负责操作主数据库的脚本使用。

在本地环境中,PostgreSQL 默认由 Docker 中的 Goat 脚本启动。

独立的测试数据库

测试可以使用单独的连接:

GOAT_DB_TEST_HOST
GOAT_DB_TEST_PORT
GOAT_DB_TEST_USER
GOAT_DB_TEST_PASS
GOAT_DB_TEST_NAME

将测试数据库与开发数据库分离,可降低意外删除或修改日常工作中使用的数据的风险。

示例配置:

GOAT_DB_TEST_HOST=localhost
GOAT_DB_TEST_PORT=5433
GOAT_DB_TEST_USER=admin
GOAT_DB_TEST_PASS=local-password
GOAT_DB_TEST_NAME=testdb

尤其重要的是,测试期间执行的破坏性操作绝不能指向生产数据库。

JWT 密钥

变量:

GOAT_JWT_SECRET

应用程序使用它来签署 JWT 令牌。

该值应当:

  • 足够长,
  • 随机,
  • 对相应环境唯一,
  • 不可公开访问。

请勿在生产环境中使用示例密钥。

不要将真实的 GOAT_JWT_SECRET 保存到受 Git 跟踪的文件中。

每个环境都应拥有自己的值。特别是,本地、测试和生产环境不应共用同一个密钥。

应用程序公共地址

变量:

GOAT_URL_BASE

用于指定应用程序的公共基础地址。

本地可以是:

GOAT_URL_BASE=http://localhost:8080/

在目标环境中,该值应与应用程序客户端实际使用的地址相对应。

它可用于生成:

  • 绝对链接,
  • 回调地址,
  • 消息中的地址,
  • 元数据,
  • 指向应用程序资源的链接。

数据和临时文件目录

Goat 允许配置用于存储数据和临时文件的位置。

为此使用:

GOAT_DIR_DATA
GOAT_DIR_TMP
GOAT_DIR_SHARED_TMP

GOAT_DIR_DATA 指定用于存放应用程序数据的目录。

GOAT_DIR_TMP 可由单个进程用于存储临时文件。

GOAT_DIR_SHARED_TMP 用于必须可供多个进程或容器访问的临时数据。

显式定义这些目录有助于让应用程序适应不同的运行环境。

环境域名

变量:

GOAT_DOMAIN

可用于指定与当前环境相关的域名。

该值可由部署配置、反向代理、地址生成或其他基础设施组件使用。

例如:

GOAT_DOMAIN=example.com

不应自动将其等同于 GOAT_URL_BASE。

GOAT_DOMAIN 描述域名,而 GOAT_URL_BASE 可以包含带有协议、端口和基础路径的完整地址。

密钥与版本控制

存储在仓库中的配置文件应仅包含安全的示例值。

请将真实密钥存储在版本控制之外。

这尤其适用于:

GOAT_DB_MAIN_PASS
GOAT_DB_TEST_PASS
GOAT_JWT_SECRET

在本地环境中,它们可以位于 .env。

在共享环境和生产环境中,最好通过以下方式提供它们:

  • 平台环境变量,
  • CI/CD 系统,
  • 密钥管理器,
  • 部署平台提供的机制。

良好的做法是在仓库中保存一个示例文件,例如:

.env.example

其中包含所需变量的名称,但不包含真实密钥。

示例:

GOAT_DEV=TRUE

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=
GOAT_DB_MAIN_PASS=
GOAT_DB_MAIN_NAME=

GOAT_JWT_SECRET=

GOAT_URL_BASE=http://localhost:8080/

此类文件可在不泄露敏感数据的情况下,简化新环境的准备工作。

容器配置

本地 Goat 脚本使用 Docker 来启动项目基础设施的一部分。

尤其是,数据库脚本会在容器中启动 PostgreSQL,并通过以下端口在本地提供访问:

5433

因此,从直接在主机上运行的进程角度来看,连接可能如下所示:

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433

当应用程序本身在容器内运行时,情况则有所不同。

对于 Docker 内部的进程:

localhost

表示的是其自身容器,而不是主机系统。

因此,开发脚本可以将数据库主机覆盖为:

host.docker.internal

此时,流程可简化如下:

容器中的应用程序
        ↓
host.docker.internal:5433
        ↓
由主机暴露的端口
        ↓
PostgreSQL

这样,无论指定命令是直接在主机上执行,还是在容器内执行,都可以使用相同的项目配置。

本地配置与目标环境配置

不应将本地的 .env 原封不动地复制到服务器上。

本地配置针对开发便利性进行了优化:

localhost
由 Docker 暴露的端口
GOAT_DEV=TRUE
本地密码
本地目录

而生产环境可能使用:

内部 PostgreSQL 主机
由平台提供的密钥
HTTPS
持久化卷
不同的数据目录
GOAT_DEV=FALSE

因此,配置应被视为依赖于环境的元素,而不是应用程序代码的一部分。

典型本地工作流

本地配置的准备过程可以如下:

cp .env.example .env

然后填写项目所需的值:

GOAT_DEV=TRUE

GOAT_DB_MAIN_HOST=localhost
GOAT_DB_MAIN_PORT=5433
GOAT_DB_MAIN_USER=admin
GOAT_DB_MAIN_PASS=local-password
GOAT_DB_MAIN_NAME=maindb

GOAT_JWT_SECRET=lokalny-losowy-sekret

GOAT_URL_BASE=http://localhost:8080/

保存配置后,即可启动环境:

bash child/dev.sh

Goat 脚本将根据项目配置准备环境的其余部分。

最重要的原则

应用程序代码应定义它需要什么配置,而具体的值应来自应用程序运行所在的环境。

因此,同一份代码可以在本地、测试环境、CI、预发布环境和生产环境中运行,而无需直接修改源代码。

应将密钥视为环境数据,而非项目的一部分。