Umgebungsvariablen halten Geheimnisse aus dem Quellcode heraus und ermöglichen Konfigurationsänderungen ohne Redeployment. Die .env-Datei ist die Standardmethode zur lokalen Verwaltung geworden. Dieser Leitfaden behandelt Syntaxregeln, Framework-Setup, Sicherheit, umgebungsspezifische Dateien, Docker-Integration, häufige Fehler und Produktionsalternativen.
.env Syntaxregeln
Eine .env-Datei ist eine Klartextdatei mit einer Variable pro Zeile. Hier sind die Regeln, die jeder Entwickler kennen sollte:
Grundsyntax
Jede Zeile folgt dem KEY=VALUE-Muster. Keine Leerzeichen um das Gleichheitszeichen.
# .env
DATABASE_URL=postgres://localhost:5432/mydb
API_KEY=sk-1234567890abcdef
PORT=3000
DEBUG=trueAnführungszeichenregeln
Werte können ohne Anführungszeichen, in einfachen oder doppelten Anführungszeichen stehen. Das Verhalten unterscheidet sich:
# Unquoted — trailing whitespace trimmed
APP_NAME=My Application
# Single quotes — literal, no interpolation
PASSWORD='p@$$w0rd#123'
# Double quotes — escape sequences + interpolation
GREETING="Hello\nWorld"
FULL_URL="${BASE_URL}/api/v1"- Ohne Anführungszeichen: nachfolgende Leerzeichen werden entfernt, keine Escape-Sequenzen.
- Einfache Anführungszeichen: Wert wird wörtlich übernommen, keine Interpolation, kein Escaping.
- Doppelte Anführungszeichen: unterstützt Escape-Sequenzen (\n, \t) und Variableninterpolation.
Mehrzeilige Werte
Verwenden Sie doppelte Anführungszeichen und \n für Zeilenumbrüche oder tatsächliche Zeilenumbrüche in doppelten Anführungszeichen:
# Method 1: \n in double quotes
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIB...\n-----END RSA PRIVATE KEY-----"
# Method 2: actual newlines in double quotes
PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA...
-----END RSA PRIVATE KEY-----"Kommentare
Zeilen, die mit # beginnen, sind Kommentare. Inline-Kommentare funktionieren nur bei nicht-gequoteten Werten in einigen Parsern:
# This is a full-line comment
DATABASE_URL=postgres://localhost/mydb # inline comment (some parsers)
# Empty lines are ignored
API_KEY=abc123 # This may or may not work depending on the parserVariableninterpolation
Referenzieren Sie andere Variablen mit ${VAR}-Syntax (von den meisten Parsern in doppelt gequoteten Werten unterstützt):
BASE_URL=https://api.example.com
API_V1=${BASE_URL}/v1
API_V2=${BASE_URL}/v2
DB_HOST=localhost
DB_PORT=5432
DB_NAME=myapp
DATABASE_URL=postgres://${DB_HOST}:${DB_PORT}/${DB_NAME}Framework-Setup
Node.js (dotenv)
Der beliebteste .env-Loader für Node.js. Installation und Konfiguration:
# Install
npm install dotenv
# --- app.js (CommonJS) ---
require('dotenv').config();
console.log(process.env.DATABASE_URL);
# --- app.ts (ES Modules) ---
import 'dotenv/config';
console.log(process.env.DATABASE_URL);
# --- Or load from CLI ---
node -r dotenv/config app.js
node -r dotenv/config app.js dotenv_config_path=.env.localNext.js, Vite und Create React App laden .env-Dateien automatisch — kein Paket nötig.
Python (python-dotenv)
.env in Python-Projekten laden:
# Install
pip install python-dotenv
# --- app.py ---
from dotenv import load_dotenv
import os
load_dotenv() # loads .env from current directory
# load_dotenv('.env.local') # or specify a path
database_url = os.getenv('DATABASE_URL')
print(database_url)
# --- Django: manage.py or settings.py ---
from dotenv import load_dotenv
from pathlib import Path
env_path = Path('.') / '.env'
load_dotenv(dotenv_path=env_path)Go (godotenv)
.env in Go-Projekten laden:
// Install
// go get github.com/joho/godotenv
package main
import (
"fmt"
"log"
"os"
"github.com/joho/godotenv"
)
func main() {
err := godotenv.Load() // loads .env
if err != nil {
log.Fatal("Error loading .env file")
}
dbURL := os.Getenv("DATABASE_URL")
fmt.Println(dbURL)
}PHP (vlucas/phpdotenv)
Wird von Laravel und den meisten PHP-Frameworks verwendet:
// Install
// composer require vlucas/phpdotenv
<?php
require 'vendor/autoload.php';
$dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
$dotenv->load();
// Access variables
$dbUrl = $_ENV['DATABASE_URL'];
// or
$dbUrl = getenv('DATABASE_URL');
// Required variables (throws exception if missing)
$dotenv->required(['DATABASE_URL', 'API_KEY']);Ruby (dotenv Gem)
Wird von Rails und anderen Ruby-Projekten verwendet:
# Gemfile
gem 'dotenv-rails', groups: [:development, :test]
# Or for non-Rails Ruby:
gem 'dotenv'
# --- app.rb ---
require 'dotenv/load'
puts ENV['DATABASE_URL']
# --- Rails: .env is loaded automatically ---
# Access via ENV['DATABASE_URL'] anywhere in your appSicherheit: .env-Dateien niemals committen
Ihre .env-Datei enthält Geheimnisse (API-Schlüssel, Datenbankpasswörter, Tokens). Sie in die Versionskontrolle zu committen ist der Sicherheitsfehler Nr. 1.
.gitignore Muster
Fügen Sie diese Muster sofort zu Ihrer .gitignore-Datei hinzu:
# .gitignore
# Ignore all .env files
.env
.env.local
.env.*.local
.env.development
.env.production
# More aggressive pattern — ignore all .env variants
.env*
# But DO commit the example file
!.env.example.env.example verwenden
Committen Sie eine .env.example-Datei mit leeren Werten, damit Teammitglieder wissen, welche Variablen benötigt werden:
# .env.example — commit this file
# Copy to .env and fill in your values
DATABASE_URL=
API_KEY=
SMTP_HOST=
SMTP_PORT=587
SMTP_USER=
SMTP_PASS=
REDIS_URL=
JWT_SECRET=
# Optional
DEBUG=false
LOG_LEVEL=info.env bereits committet?
Wenn Sie versehentlich eine .env-Datei committet haben, entfernen Sie sie aus dem Tracking und rotieren Sie alle Geheimnisse:
# Step 1: Remove .env from Git tracking (keeps local file)
git rm --cached .env
# Step 2: Add to .gitignore
echo ".env" >> .gitignore
# Step 3: Commit the removal
git add .gitignore
git commit -m "Remove .env from tracking, add to .gitignore"
# Step 4: CRITICAL — Rotate ALL secrets in the .env file
# Every API key, password, and token that was exposed
# must be regenerated immediatelyUmgebungsspezifische Dateien
Die meisten Frameworks unterstützen mehrere .env-Dateien für verschiedene Umgebungen. Das Verständnis der Ladereihenfolge ist entscheidend.
Ladereihenfolge (Next.js / Vite / CRA)
Dateien werden in dieser Priorität geladen (spätere Dateien überschreiben frühere):
# Loading priority (highest to lowest):
# 1. Shell environment variables (always win)
# 2. .env.{NODE_ENV}.local (e.g. .env.production.local)
# 3. .env.local (NOT loaded in test)
# 4. .env.{NODE_ENV} (e.g. .env.production)
# 5. .env (default fallback)
# Example for NODE_ENV=production:
# .env → loaded first (base defaults)
# .env.production → overrides .env
# .env.local → overrides .env.production
# .env.production.local → overrides everything above.env.local wird immer von git ignoriert (zu .gitignore hinzufügen). Es wird NICHT während Tests geladen, um Tests deterministisch zu halten.
Welche Datei für was?
| File | Purpose | Git |
|---|---|---|
| .env | Default values, non-secret config | Commit |
| .env.example | Template with empty values | Commit |
| .env.local | Local secrets & overrides | Ignore |
| .env.development | Dev-specific (shared) | Commit |
| .env.production | Production-specific (non-secret) | Commit |
| .env.test | Test environment config | Commit |
| .env.production.local | Production secrets (local only) | Ignore |
Docker & Docker Compose Integration
env_file Direktive
Docker Compose kann .env-Dateien direkt in Container laden:
# docker-compose.yml (or compose.yml)
services:
web:
image: node:20-alpine
env_file:
- .env # base defaults
- .env.production # production overrides
ports:
- "3000:3000"
db:
image: postgres:16
env_file:
- .env.db # separate file for DB secrets
volumes:
- pgdata:/var/lib/postgresql/dataenvironment vs env_file
Sie können Umgebungsvariablen auch inline setzen. Hier ist der Unterschied:
# Using env_file (loads from file)
services:
web:
env_file:
- .env
# Using environment (inline)
services:
web:
environment:
- NODE_ENV=production
- PORT=3000
- DATABASE_URL=${DATABASE_URL} # from shell or .env
# Using environment (mapping syntax)
services:
web:
environment:
NODE_ENV: production
PORT: 3000- env_file: lädt aus Datei, hält compose.yml sauber, leicht pro Umgebung wechselbar.
- environment: in compose.yml sichtbar, gut für nicht-geheime Werte, unterstützt Variablensubstitution.
.env für Docker Compose Variablen
Docker Compose liest automatisch eine .env-Datei im Projektstammverzeichnis für Variablensubstitution in compose.yml:
# .env (in same directory as compose.yml)
POSTGRES_VERSION=16
NODE_VERSION=20
APP_PORT=3000
# compose.yml — uses .env for variable substitution
services:
web:
image: node:${NODE_VERSION}-alpine
ports:
- "${APP_PORT}:3000"
db:
image: postgres:${POSTGRES_VERSION}
environment:
POSTGRES_DB: myapp10 häufige .env-Fehler und Lösungen
Die häufigsten .env-Probleme, auf die Entwickler stoßen:
| # | Fehler | Ursache | Lösung |
|---|---|---|---|
| 1 | process.env.VAR ist undefined | dotenv nicht geladen oder nach Verwendung geladen | dotenv.config() ganz oben in der Einstiegsdatei aufrufen |
| 2 | Variablen in Produktion leer | .env-Datei nicht deployed; Abhängigkeit von Datei statt Plattform-Umgebungsvariablen | Umgebungsvariablen in der Hosting-Plattform setzen (Vercel, AWS, etc.) |
| 3 | .env-Werte enthalten Anführungszeichen | Parser behandelt Anführungszeichen als literale Zeichen | Parser-Dokumentation prüfen |
| 4 | Falsche .env-Datei geladen | Arbeitsverzeichnis weicht vom erwarteten Pfad ab | path-Option verwenden: dotenv.config({ path: ".env.local" }) |
| 5 | Mehrzeiliger Wert abgeschnitten | Wert nicht korrekt in doppelten Anführungszeichen | Mehrzeilige Werte in doppelte Anführungszeichen einschließen |
| 6 | Sonderzeichen beschädigen Wert | $ oder # als Interpolation/Kommentar interpretiert | Einfache Anführungszeichen verwenden oder mit \ escapen |
| 7 | BOM-Encoding-Fehler | Windows-Editor speichert .env mit UTF-8 BOM | Als UTF-8 ohne BOM speichern |
| 8 | Docker-Container-Umgebungsvariablen leer | env_file-Pfad falsch oder Datei nicht im Build-Kontext | Pfad relativ zum compose.yml-Speicherort überprüfen |
| 9 | Leerzeichen um = brechen Parsing | KEY = VALUE statt KEY=VALUE | Leerzeichen um das Gleichheitszeichen entfernen |
| 10 | Variablen im Browser nicht verfügbar (React/Next) | Erforderliches Präfix fehlt (NEXT_PUBLIC_ oder REACT_APP_) | Framework-erforderliches Präfix hinzufügen |
Produktionsalternativen
In der Produktion werden .env-Dateien nicht empfohlen. Verwenden Sie stattdessen diese Alternativen:
Plattform-Umgebungsvariablen
Jede große Hosting-Plattform bietet UI oder CLI zum Setzen von Umgebungsvariablen:
# Vercel
vercel env add DATABASE_URL production
vercel env ls
# AWS (Parameter Store)
aws ssm put-parameter \
--name "/myapp/prod/DATABASE_URL" \
--value "postgres://..." \
--type SecureString
# Heroku
heroku config:set DATABASE_URL=postgres://...
heroku config
# Railway
railway variables set DATABASE_URL=postgres://...
# Fly.io
fly secrets set DATABASE_URL=postgres://...Docker Secrets
Für Docker Swarm oder Compose verwenden Sie Secrets für sensible Daten:
# compose.yml with Docker secrets
services:
web:
image: myapp:latest
secrets:
- db_password
- api_key
environment:
DB_PASSWORD_FILE: /run/secrets/db_password
secrets:
db_password:
file: ./secrets/db_password.txt # for Compose
# external: true # for Swarm
api_key:
file: ./secrets/api_key.txt
# In your app, read from file:
# const secret = fs.readFileSync('/run/secrets/db_password', 'utf8').trim();Secret Manager (Vault, AWS Secrets Manager)
Für Enterprise-Anwendungen einen dedizierten Secret Manager verwenden:
# HashiCorp Vault
vault kv put secret/myapp/production \
DATABASE_URL="postgres://..." \
API_KEY="sk-..."
# Read in application
vault kv get -field=DATABASE_URL secret/myapp/production
# AWS Secrets Manager
aws secretsmanager create-secret \
--name "myapp/production/db" \
--secret-string '{"url":"postgres://...","password":"..."}'
# Read in Node.js with AWS SDK
import { SecretsManager } from '@aws-sdk/client-secrets-manager';
const client = new SecretsManager({ region: 'us-east-1' });
const { SecretString } = await client.getSecretValue({
SecretId: 'myapp/production/db'
});
const secrets = JSON.parse(SecretString);Secret Manager bieten Rotation, Audit-Logging, Zugriffskontrolle und Verschlüsselung im Ruhezustand — Funktionen, die .env-Dateien nicht bieten können.
Häufig gestellte Fragen
Sollte ich meine .env-Datei in Git committen?
Committen Sie niemals .env-Dateien mit Geheimnissen in die Versionskontrolle. Committen Sie stattdessen eine .env.example-Datei mit leeren Platzhalterwerten. Fügen Sie .env*-Muster zu Ihrer .gitignore hinzu.
Was ist der Unterschied zwischen .env, .env.local und .env.production?
.env enthält Standardwerte für alle Umgebungen. .env.local enthält lokale Überschreibungen und wird nicht committet. .env.production enthält produktionsspezifische Werte, die nur bei NODE_ENV=production geladen werden.
Warum ist process.env.MY_VAR in Node.js undefined?
Häufigste Ursachen: 1) Vergessen, require("dotenv").config() oben aufzurufen, 2) .env-Datei nicht im Stammverzeichnis, 3) Tippfehler im Variablennamen, 4) Bei ES-Modulen "import dotenv/config" verwenden.
Wie verwende ich .env-Variablen in Docker Compose?
Docker Compose liest automatisch eine .env-Datei im selben Verzeichnis wie compose.yml für ${VAR}-Variablensubstitution. Verwenden Sie env_file oder environment zum Weitergeben an Container.
Kann ich .env-Dateien in der Produktion verwenden?
Nicht empfohlen. In der Produktion verwenden Sie Plattform-Umgebungsvariablen, Docker Secrets oder einen Secret Manager wie HashiCorp Vault oder AWS Secrets Manager.
Wie exponiere ich .env-Variablen an den Browser in React oder Next.js?
In Next.js mit NEXT_PUBLIC_-Präfix. In Create React App REACT_APP_-Präfix. In Vite VITE_-Präfix. Nur präfixierte Variablen werden in das Client-Bundle eingebettet.