Node.js und Logging – Teil 3: Umgebungsvariablen mit dotenv
Umgebungsvariablen per CLI setzen? Geht – macht aber keinen Spaß. In diesem Artikel zeige ich, wie du mit dotenv Ordnung in deine Node.js-Konfiguration bringst und warum .env niemals ins Repository gehört. Ein pragmatischer Schritt hin zu robusterer Konfiguration – und die Basis für besseres Logging.
Im vorherigen Artikel zum EnvVarService haben wir festgestellt, dass es mühsam ist, Umgebungsvariablen über die Kommandozeile zu definieren. Stattdessen beabsichtigen wir, die Werte in einer Datei festzulegen.
Vorbereitung
Als ersten und wichtigsten Schritt stellen wir sicher, dass wir die Datei nicht in unsere Codeversionierung einchecken. Deswegen ergänzen wir die Datei .gitignore um eine entsprechende Zeile:
# dotenv environment variables file
.env
Neben einfachen Konfigurationen können sich in der .env-Datei auch Secrets oder Tokens befinden, die Zugriff auf Dienste ermöglichen. Diese möchten wir niemals im Repository haben. Unabhängig davon, ob wir unser Repository als privat deklarieren. Es kann immer passieren, dass das Repository versehentlich als public deklariert wird.
Ein solches Missgeschick ist mir bereits passiert, als ich meine Infrastructure-as-Code-Anpassung, die die Repositories meiner Firma verwaltet, unbedacht umgesetzt habe. Dabei ist durch eine Refaktorisierung ein Parameter optional geworden, dessen Standardwert ich auf true gesetzt habe. Das Change-Log nur überflogen und schwupps – waren einige Repositories public.
Dotenv einbinden
Standardmäßig läuft eine Importsortierung über meinen Code. Damit dotenv funktioniert, muss der Aufruf als Erstes in der Applikation ausgeführt werden. Gelöst habe ich dies mit einer etwas kryptischen Namensgebung. In einer Datei namens __loadEnvVar.ts schreiben wir folgenden Code.
Kleiner Tipp: Neben dem Überschreiben kannst du mit debug:true zusätzliche Ausgaben erhalten, falls etwas nicht so klappt, wie erwartet.
import dotenv from 'dotenv'
// Load environment variables from .env file
// We override any existing environment variables
dotenv.config({override: true})
export {
}
Die Einbindung erfolgt in der index.ts an erster Stelle – deswegen die Unterstriche im Namen:
import '@/__loadEnvVars'
import createApp from '@/createApp'
import LogService from '@/services/LogService'
import EnvVarService from '@/services/EnvVarService'
const PORT = EnvVarService.app.serverPort
const NODE_ENV = EnvVarService.app.nodeEnv
const app = createApp()
app.listen(PORT, () => {
LogService.debug(`Server is started`, {port: PORT, nodeEnv: NODE_ENV})
})
Die .env-Datei
Im Root-Verzeichnis unserer Applikation können wir eine .env-Datei anlegen. Darin werden wir zukünftig die Umgebungsvariablen definieren.
# app
NODE_ENV=development
SERVER_PORT=4000
# logging
Die .env.dist-Datei
Ich habe es mir angewöhnt, neben der .env-Datei noch eine Datei mit der Endung .dist zu erstellen. Darin sind die Umgebungsvariablen aufgelistet, die die Applikation versteht und nutzt. Ich ergänze die jeweiligen Variablen um Kommentare, die erklären, was damit beabsichtigt wird. Wenn sinnvoll, ergänze ich noch Informationen zu den Wertebereichen.
# Define the node environment. Can be development or production
NODE_ENV=
# Define the port the server listens on
SERVER_PORT=
Fazit
Jetzt haben wir die notwendigen Services – für Logging und Umgebungsvariablen – implementiert und mit dotenv einen einfachen Weg zur Verwaltung von Konfigurationen. Im nächsten Artikel werden wir den LogService mit unseren Hilfsmitteln konfigurieren.