Konfigurationen mit envsubst und Heredocs templatisieren
Erzeugen Sie mithilfe von envsubst und quotierten Heredocs Laufzeitkonfigurationen aus Umgebungsvariablen.
Konfigurationen mit envsubst und Heredocs templatisieren ist eine kostenlose Linux Command Line & Bash Scripting Mastery-Lektion auf CoddyKit. Dies ist Lektion 2 von 4. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des Linux Command Line & Bash Scripting Mastery-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der Linux Command Line & Bash Scripting Mastery-Kurs umfasst insgesamt 4 Lektionen.
Warum Laufzeit-Templating für Konfigurationen wichtig ist
In DevOps- und Container-Workflows müssen sich Konfigurationsdateien wie nginx.conf, prometheus.yml und docker-compose.yml häufig zwischen Umgebungen unterscheiden — etwa zwischen Staging, Produktion und DR. Hartcodierte Werte führen zu Abweichungen und zur Offenlegung von Secrets.
Die Lösung ist Konfigurations-Templating zur Laufzeit: Liefern Sie ein Template mit Platzhaltern aus und setzen Sie beim Start die tatsächlichen Werte aus Umgebungsvariablen ein. So bleibt Ihr Image unveränderlich und Ihre Konfiguration überprüfbar.
- Keine Secrets im Image eingebettet
- Dasselbe Artefakt kann über mehrere Umgebungen hinweg bereitgestellt werden
- Die Konfiguration wird unmittelbar vor dem Start des Prozesses erzeugt
Zwei sich ergänzende Werkzeuge machen dies in Bash besonders einfach: envsubst und quotierte Heredocs.
envsubst: Der Konfigurationsgenerator in einer Zeile
envsubst ist ein kleines GNU-Dienstprogramm, das von stdin liest, Platzhalter der Form $VARIABLE und ${VARIABLE} durch ihre Werte aus der aktuellen Umgebung ersetzt und auf stdout schreibt.
Es wird mit dem Paket gettext ausgeliefert und ist praktisch in jeder Linux-Distribution und jedem Docker-Basis-Image verfügbar.
- Funktioniert mit jedem Textformat: NGINX, YAML, TOML, JSON, INI
- Wertet keine Shell-Syntax aus — es ersetzt nur Variablenreferenzen
- Sicher: Es führt keine Befehle innerhalb des Templates aus
#!/usr/bin/env bash
# Install check (usually already present)
which envsubst || apt-get install -y gettext-base
# Minimal demo
export APP_PORT=8080
export APP_HOST=api.example.com
echo 'server { listen ${APP_PORT}; server_name ${APP_HOST}; }' | envsubst
# Output: server { listen 8080; server_name api.example.com; }Selektive Variablenersetzung
Standardmäßig ersetzt envsubst jedes gefundene $VAR. Dadurch können NGINX-Variablen wie $uri oder $host überschrieben werden — dabei handelt es sich um echte NGINX-Direktiven und nicht um Ihre Umgebungsvariablen.
Übergeben Sie als erstes Argument eine explizite Variablenliste, um die Ersetzung auf genau diese Namen zu beschränken:
envsubst '$VAR1 $VAR2'Das Argument ist eine Zeichenkette in einfachen Anführungszeichen (damit die Shell sie nicht erweitert), die die zu ersetzenden Variablennamen enthält, getrennt durch Leerzeichen oder Zeilenumbrüche.
#!/usr/bin/env bash
export APP_PORT=8080
export APP_HOST=api.example.com
# NGINX template contains both our vars AND nginx vars ($uri, $host)
TEMPLATE='server {
listen ${APP_PORT};
server_name ${APP_HOST};
location / {
proxy_set_header Host $host;
proxy_pass http://backend$uri;
}
}'
# Only substitute APP_PORT and APP_HOST — leave $host and $uri untouched
echo "$TEMPLATE" | envsubst '${APP_PORT} ${APP_HOST}'
Template-Dateien auf der Festplatte
Speichern Sie echte Konfigurationen als Datei (z. B. nginx.conf.template) neben Ihrem Dockerfile. Führen Sie beim Start des Containers envsubst aus, um vor dem Start des Daemons die finale Konfigurationsdatei zu erzeugen.
Dies ist das kanonische Muster, das vom offiziellen NGINX-Docker-Image verwendet wird.
#!/usr/bin/env bash
# File: nginx.conf.template
# (In practice this lives on disk; we write it here for demo purposes)
cat > /tmp/nginx.conf.template << 'TMPL'
server {
listen ${NGINX_PORT};
server_name ${SERVER_NAME};
root /var/www/${APP_ENV};
location / {
proxy_pass http://app:${APP_PORT};
}
}
TMPL
export NGINX_PORT=80
export SERVER_NAME=myapp.example.com
export APP_ENV=production
export APP_PORT=3000
# Generate final config
envsubst '${NGINX_PORT} ${SERVER_NAME} ${APP_ENV} ${APP_PORT}' \
< /tmp/nginx.conf.template \
> /tmp/nginx.conf
cat /tmp/nginx.confQuoted-Heredocs: Inline-Templates ohne temporäre Datei
Ein Quoted-Heredoc (mit << 'EOF' und einfachen Anführungszeichen um das Trennzeichen) verhindert, dass die Shell Variablen expandiert oder Befehlsersetzungen innerhalb des Blocks ausführt. Der Inhalt wird als Literalzeichenkette behandelt.
Dadurch eignen sich Heredocs ideal, um ein Template direkt einzubetten und ohne Zwischendatei direkt an envsubst weiterzuleiten.
<< EOF(ohne Anführungszeichen) – die Shell expandiert$VARsofort<< 'EOF'(mit Anführungszeichen) – der Inhalt bleibt wörtlich erhalten; die Expansion wird anenvsubstverschoben
#!/usr/bin/env bash
export DB_HOST=postgres.internal
export DB_PORT=5432
export DB_NAME=myapp_prod
# Quoted heredoc: shell does NOT expand $DB_HOST etc. yet
envsubst << 'EOF'
[database]
host = ${DB_HOST}
port = ${DB_PORT}
dbname = ${DB_NAME}
EOF
# Output uses actual env var values — expansion done by envsubst, not the shellHeredocs mit Ausgabeumleitung kombinieren
Leiten Sie ein Quoted-Heredoc durch envsubst und schreiben Sie das Ergebnis in einem Ausdruck in eine Datei um. Dies ist das sauberste Idiom zum Erzeugen von Konfigurationsdateien in einem Entrypoint-Skript.
Verwenden Sie eine selektive Substitution ('${VAR1} ${VAR2}'), wenn das Zielformat (Prometheus, NGINX usw.) eine eigene $variable-Syntax besitzt, die geschützt werden muss.
#!/usr/bin/env bash
# entrypoint.sh — Docker container entrypoint
set -euo pipefail
export PROM_PORT=${PROM_PORT:-9090}
export SCRAPE_INTERVAL=${SCRAPE_INTERVAL:-15s}
export TARGET_HOST=${TARGET_HOST:-localhost:8080}
envsubst '${PROM_PORT} ${SCRAPE_INTERVAL} ${TARGET_HOST}' << 'EOF' > /etc/prometheus/prometheus.yml
global:
scrape_interval: ${SCRAPE_INTERVAL}
evaluation_interval: ${SCRAPE_INTERVAL}
scrape_configs:
- job_name: 'app'
static_configs:
- targets: ['${TARGET_HOST}']
EOF
echo "[entrypoint] Prometheus config written on port ${PROM_PORT}"
exec prometheus --config.file=/etc/prometheus/prometheus.yml --web.listen-address=":${PROM_PORT}"Standardwerte und Validierung vor der Substitution
Gehen Sie niemals davon aus, dass alle erforderlichen Variablen gesetzt sind. Verwenden Sie die Parameterexpansion von Bash, um Standardwerte bereitzustellen oder einen Fehler auszugeben:
${VAR:-default}– verwendetdefault, wennVARnicht gesetzt oder leer ist${VAR:?error message}– bricht mit einem Fehler ab, wennVARnicht gesetzt oder leer ist
Setzen Sie diese Werte vor dem Aufruf von envsubst, damit das Template immer einen konkreten Wert erhält oder das Skript frühzeitig mit einer hilfreichen Meldung beendet wird.
#!/usr/bin/env bash
set -euo pipefail
# Required — abort if missing
: "${DATABASE_URL:?DATABASE_URL must be set}"
: "${SECRET_KEY:?SECRET_KEY must be set}"
# Optional with defaults
export APP_PORT=${APP_PORT:-8000}
export LOG_LEVEL=${LOG_LEVEL:-info}
export WORKERS=${WORKERS:-4}
envsubst '${DATABASE_URL} ${SECRET_KEY} ${APP_PORT} ${LOG_LEVEL} ${WORKERS}' \
< /app/config/app.conf.template \
> /app/config/app.conf
echo "[init] Config generated — port=${APP_PORT} workers=${WORKERS} log=${LOG_LEVEL}"Mehrteilige Konfigurationen mit mehreren Heredocs erzeugen
Bei komplexen Konfigurationen, die aus logisch getrennten Abschnitten bestehen, können Sie jeden Abschnitt unabhängig erzeugen und anschließend zusammenfügen oder ein einzelnes Heredoc verwenden, das sich über die gesamte Datei erstreckt. Beide Ansätze funktionieren – wählen Sie je nach Lesbarkeit.
Wenn Abschnitte bedingt eingebunden werden (z. B. ein TLS-Block nur, wenn ein Zertifikatspfad gesetzt ist), ist der Ansatz mit mehreren Heredocs und if-Blöcken übersichtlicher.
#!/usr/bin/env bash
set -euo pipefail
export APP_HOST=${APP_HOST:-localhost}
export APP_PORT=${APP_PORT:-8080}
export TLS_CERT=${TLS_CERT:-}
export TLS_KEY=${TLS_KEY:-}
CONFIG_FILE=/tmp/app.conf
# Base section
envsubst '${APP_HOST} ${APP_PORT}' << 'BASE' > "$CONFIG_FILE"
[server]
host = ${APP_HOST}
port = ${APP_PORT}
BASE
# Conditional TLS section — only appended when cert is provided
if [[ -n "$TLS_CERT" && -n "$TLS_KEY" ]]; then
envsubst '${TLS_CERT} ${TLS_KEY}' << 'TLS' >> "$CONFIG_FILE"
[tls]
cert_file = ${TLS_CERT}
key_file = ${TLS_KEY}
TLS
echo "[init] TLS enabled"
else
echo "[init] TLS disabled (no cert/key provided)"
fi
cat "$CONFIG_FILE"Docker-Entrypoint-Muster
Das empfohlene Docker-Entrypoint-Muster verwendet ein Shell-Skript (docker-entrypoint.sh), um Konfigurationen beim Start zu erzeugen und anschließend mit exec an den Hauptprozess zu übergeben. Durch exec wird der Shell-Prozess durch den Daemon ersetzt, sodass Signale (SIGTERM, SIGINT) den Daemon direkt erreichen – entscheidend für ein ordnungsgemäßes Herunterfahren.
Template-Dateien werden beim Erstellen zum Image hinzugefügt; Werte werden zur Laufzeit über docker run -e oder Kubernetes env: / envFrom: injiziert.
#!/usr/bin/env bash
# docker-entrypoint.sh
set -euo pipefail
# Validate required env vars
for var in DATABASE_URL REDIS_URL SECRET_KEY; do
: "${!var:?$var is required}"
done
export APP_PORT=${APP_PORT:-8000}
export WORKERS=${WORKERS:-$(nproc)}
echo "[entrypoint] Generating configuration..."
envsubst '${DATABASE_URL} ${REDIS_URL} ${SECRET_KEY} ${APP_PORT} ${WORKERS}' \
< /app/config/settings.toml.template \
> /app/config/settings.toml
echo "[entrypoint] Starting server on port ${APP_PORT} with ${WORKERS} workers"
exec gunicorn app:application \
--bind "0.0.0.0:${APP_PORT}" \
--workers "${WORKERS}"Kubernetes-ConfigMap- und envsubst-Muster
In Kubernetes werden Umgebungsvariablen über env: oder envFrom: in der Pod-Spezifikation injiziert. Der Entrypoint Ihres Containers ruft envsubst auf, um Konfigurationen zu materialisieren, bevor der Prozess startet – eine ConfigMap pro Umgebung ist nicht erforderlich.
Dadurch bleiben umgebungsspezifische Werte in Kubernetes-Secrets und ConfigMaps (für nicht vertrauliche Daten), während das Konfigurations-Template im Image liegt. Ein Image, viele Umgebungen.
- Build:
COPY nginx.conf.template /etc/nginx/templates/ - Laufzeit: Der Entrypoint führt
envsubstaus und schreibt/etc/nginx/nginx.conf - K8s injiziert:
APP_PORT,BACKEND_HOSTaus einem Secret/einer ConfigMap
envsubst debuggen: Fehlende oder nicht aufgelöste Variablen finden
Wenn eine erzeugte Konfiguration anstelle eines Werts das Literal ${VAR} enthält, wurde die Variable entweder nicht exportiert oder nicht in die Substitutionsliste aufgenommen. Verwenden Sie zum Debuggen die folgenden Techniken:
printenv | sort– listet alle exportierten Variablen auf- Vergleichen Sie die Platzhalter im Template mit den exportierten Variablen mithilfe von
grep - Führen Sie
envsubstaus und durchsuchen Sie die Ausgabe mitgrepnach verbleibenden${-Mustern - Verwenden Sie
set -uim aufrufenden Skript, damit Verweise auf nicht gesetzte Variablen im Bash-Code sofort zum Abbruch führen
#!/usr/bin/env bash
set -euo pipefail
TEMPLATE=/tmp/app.conf.template
OUTPUT=/tmp/app.conf
# Write a demo template
cat > "$TEMPLATE" << 'EOF'
host=${DB_HOST}
port=${DB_PORT}
name=${DB_NAME}
EOF
export DB_HOST=db.internal
export DB_PORT=5432
# DB_NAME intentionally left unset
envsubst < "$TEMPLATE" > "$OUTPUT"
# Detect unresolved placeholders
if grep -qE '\$\{[A-Z_]+\}' "$OUTPUT"; then
echo "ERROR: unresolved placeholders found:"
grep -oE '\$\{[A-Z_]+\}' "$OUTPUT" | sort -u
exit 1
fi
echo "Config OK:"
cat "$OUTPUT"Wissenscheck: Selektive Substitution mit envsubst
Betrachten Sie ein NGINX-Konfigurationstemplate, das sowohl Ihre Anwendungsvariable ${APP_PORT} als auch die native NGINX-Variable $uri enthält. Sie führen den folgenden Befehl aus:
envsubst < nginx.conf.template > nginx.conf
Was ist das Ergebnis?
Lektionszusammenfassung: Konfigurationen mit envsubst und Heredocs templatisieren
Sie verfügen nun über ein produktionsreifes Werkzeugset zur Erzeugung von Laufzeitkonfigurationen in Bash:
- envsubst ersetzt Platzhalter wie
${VAR}in jeder Textdatei mithilfe der aktuellen Umgebung – ohne Skripting und ohne spezielle Maskierung - Selektive Substitution (
envsubst '${VAR1} ${VAR2}') schützt native Variablen in NGINX, Prometheus und ähnlichen Tools vor versehentlichem Ersetzen - Quoted-Heredocs (
<< 'EOF') verschieben die Expansion durch die Shell, sodass der Template-Inhalt unverändert beienvsubstankommt – temporäre Dateien sind nicht erforderlich - Vor der Substitution validieren: Verwenden Sie
${VAR:?message}, um bei fehlenden erforderlichen Variablen abzubrechen, und${VAR:-default}für optionale Variablen - Docker-Entrypoint-Muster: Erzeugen Sie Konfigurationen beim Start des Containers und führen Sie anschließend den Daemon mit
execaus, damit Signale korrekt verarbeitet werden - Nicht aufgelöste Platzhalter debuggen, indem Sie die Ausgabe vor dem Start des Prozesses mit
grepnach verbleibenden${-Mustern durchsuchen
Diese Muster halten Ihre Container-Images unveränderlich, Ihre Secrets aus der Quellcodeverwaltung heraus und Ihre Konfigurationen in allen Umgebungen konsistent.
Häufig gestellte Fragen
Ist die Lektion „Konfigurationen mit envsubst und Heredocs templatisieren“ kostenlos?
Ja — der vollständige Text von „Konfigurationen mit envsubst und Heredocs templatisieren“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des Linux Command Line & Bash Scripting Mastery-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der Linux Command Line & Bash Scripting Mastery-Kurs umfasst insgesamt 4 Lektionen.
Was lerne ich in „Konfigurationen mit envsubst und Heredocs templatisieren“?
Erzeugen Sie mithilfe von envsubst und quotierten Heredocs Laufzeitkonfigurationen aus Umgebungsvariablen. Du übst Linux Command Line & Bash Scripting Mastery mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.
Brauche ich Erfahrung, um Linux Command Line & Bash Scripting Mastery zu starten?
Keine Vorkenntnisse erforderlich. Linux Command Line & Bash Scripting Mastery auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 2 von 4.
Wie lange dauert die Lektion „Konfigurationen mit envsubst und Heredocs templatisieren“?
Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.
Kann ich in dieser Linux Command Line & Bash Scripting Mastery-Lektion Code schreiben und ausführen?
Ja. Jede Linux Command Line & Bash Scripting Mastery-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.
Alle Lektionen in diesem Kurs
- Schlanke Dockerfiles und Shell-Entrypoints schreiben
- Konfigurationen mit envsubst und Heredocs templatisieren
- Cloud-Ressourcen per CLI und jq skripten
- Health-Probes, Readiness-Gates und Warteschleifen