Skabelondannelse af konfigurationer med envsubst og heredocs
Generér runtime-konfiguration fra miljøvariabler ved hjælp af envsubst og citerede heredocs.
Skabelondannelse af konfigurationer med envsubst og heredocs er en gratis Intensiv DevOps-uddannelse-lektion på CoddyKit. Dette er lektion 2 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Intensiv DevOps-uddannelse, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.
Hvorfor konfigurationsskabeloner ved kørsel er vigtige
I DevOps- og containerarbejdsforløb skal konfigurationsfiler som nginx.conf, prometheus.yml og docker-compose.yml ofte ændres mellem miljøer — test, produktion og katastrofeberedskab. Hårdkodede værdier skaber afvigelser og kan afsløre hemmeligheder.
Løsningen er konfigurationsskabeloner ved kørsel: medtag en skabelon med pladsholdere, og indsæt derefter de faktiske værdier ved opstart fra miljøvariabler. Det holder dit image uforanderligt og din konfiguration kontrollerbar.
- Ingen hemmeligheder indbygget i images
- Det samme artefakt fremmes på tværs af miljøer
- Konfigurationen genereres lige før processen starter
To komplementære værktøjer gør dette enkelt i Bash: envsubst og citerede heredocs.
envsubst: Konfigurationsgeneratoren på én linje
envsubst er et lille GNU-værktøj, der læser standardinput, erstatter pladsholdere som $VARIABLE og ${VARIABLE} med deres værdier fra det aktuelle miljø og skriver til standardoutput.
Det leveres med pakken gettext og findes i stort set alle Linux-distributioner og Docker-grundimages.
- Fungerer med alle tekstformater: NGINX, YAML, TOML, JSON og INI
- Evaluerer ikke shell-syntaks — erstatter kun variabelreferencer
- Sikkert: det udfører ikke kommandoer inde i skabelonen
#!/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; }Udvælgelse af variabler til erstatning
Som standard erstatter envsubst alle forekomster af $VAR. Det kan ødelægge NGINX-variabler som $uri eller $host — de er rigtige NGINX-direktiver, ikke dine miljøvariabler.
Angiv en eksplicit liste over variabler som det første argument for at begrænse erstatningen til netop disse navne:
envsubst '$VAR1 $VAR2'Argumentet er en streng i enkelt citationstegn (så shellen ikke udvider den), der indeholder de variabelnavne, du vil erstatte, adskilt af mellemrum eller linjeskift.
#!/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}'
Skabelonfiler på disken
For rigtige konfigurationer skal du gemme skabelonen som en fil (f.eks. nginx.conf.template) sammen med din Dockerfil. Ved containerens opstart skal du køre envsubst for at oprette den endelige konfigurationsfil, før dæmonen startes.
Dette er det kanoniske mønster, der bruges af det officielle NGINX-Docker-image.
#!/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.confCiterede heredocs: Inline-skabeloner uden en midlertidig fil
En citeret heredoc (med << 'EOF', hvor afgrænseren står i enkeltcitationstegn) forhindrer skallen i at udvide variabler eller udføre kommandosubstitutioner i blokken. Indholdet behandles som en bogstavelig streng.
Det gør heredocs til den perfekte måde at skrive en skabelon inline på og sende den direkte gennem envsubst — uden behov for en mellemfil.
<< EOF(uden citationstegn) — skallen udvider$VARmed det samme<< 'EOF'(med citationstegn) — indholdet er bogstaveligt; udvidelsen udskydes tilenvsubst
#!/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 shellKombination af heredocs og outputomdirigering
Send en citeret heredoc gennem envsubst, og omdiriger resultatet til en fil i ét udtryk. Det er den reneste idiomatiske løsning til at generere konfigurationsfiler i et entrypoint-script.
Brug selektiv substitution ('${VAR1} ${VAR2}'), når målformatet (Prometheus, NGINX osv.) har sin egen $variable-syntaks, som skal beskyttes.
#!/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}"Standardværdier og validering før substitution
Gå aldrig ud fra, at alle påkrævede variabler er sat. Brug Bash-parameterudvidelse til at angive standardværdier eller få scriptet til at stoppe med en tydelig fejl:
${VAR:-default}— brugdefault, hvisVARikke er sat eller er tom${VAR:?error message}— afbryd med en fejl, hvisVARikke er sat eller er tom
Sæt disse værdier, før du kalder envsubst, så skabelonen altid modtager en konkret værdi, eller scriptet stopper tidligt med en hjælpsom meddelelse.
#!/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}"Generering af konfigurationer med flere sektioner ved hjælp af flere heredocs
For komplekse konfigurationer, der består af logiske sektioner, kan du generere hver sektion separat og sammenkæde dem eller bruge én heredoc, der dækker hele filen. Begge metoder fungerer — vælg ud fra læsbarheden.
Når sektioner inkluderes betinget (f.eks. kun en TLS-blok, hvis der er angivet en certifikatsti), er metoden med flere heredocs og if-blokke mere overskuelig.
#!/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-mønster
Det anbefalede Docker-entrypoint-mønster bruger et shell-script (docker-entrypoint.sh) til at generere konfigurationer ved opstart og derefter overlade styringen til hovedprocessen med exec. Når du bruger exec, erstattes shell-processen af dæmonen, så signaler (SIGTERM, SIGINT) når direkte frem til dæmonen — det er afgørende for en kontrolleret nedlukning.
Skabelonfiler føjes til imaget ved byggetidspunktet; værdier indsættes ved kørsel fra docker run -e eller Kubernetes env: / envFrom:.
#!/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}"Mønster for Kubernetes ConfigMap og envsubst
I Kubernetes indsættes miljøvariabler via env: eller envFrom: i Pod-specifikationen. Dit container-entrypoint kalder envsubst for at materialisere konfigurationer, før processen starter — der er ikke behov for en ConfigMap pr. miljø.
Det holder miljøspecifikke værdier i Kubernetes Secrets og ConfigMaps (til ikke-følsomme data), mens konfigurationsskabelonen ligger i imaget. Ét image, mange miljøer.
- Bygning:
COPY nginx.conf.template /etc/nginx/templates/ - Kørsel: entrypointet kører
envsubstog skriver/etc/nginx/nginx.conf - K8s indsætter:
APP_PORT,BACKEND_HOSTfra en Secret/ConfigMap
Fejlfinding af envsubst: Find manglende eller uløste variabler
Når en genereret konfiguration indeholder den bogstavelige tekst ${VAR} i stedet for en værdi, er variablen enten ikke eksporteret eller ikke medtaget på substitutionslisten. Brug disse teknikker til fejlfinding:
printenv | sort— vis alle eksporterede variabler- Sammenlign pladsholdere i skabelonen med eksporterede variabler ved hjælp af
grep - Kør
envsubst, og bruggreppå outputtet for at finde resterende mønstre med${ - Brug
set -ui det kaldende script, så referencer til ikke-satte variabler i Bash-kode straks afbryder scriptet
#!/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"Videnscheck: Selektiv substitution med envsubst
Forestil dig en NGINX-konfigurationsskabelon, der både indeholder din applikationsvariabel ${APP_PORT} og den indbyggede NGINX-variabel $uri. Du kører følgende kommando:
envsubst < nginx.conf.template > nginx.conf
Hvad bliver resultatet?
Opsummering af lektionen: Skabelonbaserede konfigurationer med envsubst og heredocs
Du har nu et værktøjssæt på produktionsniveau til generering af konfigurationer ved kørsel i Bash:
- envsubst erstatter pladsholdere som
${VAR}i enhver tekstfil ved hjælp af det aktuelle miljø — uden scripting og uden særlig escaping - Selektiv substitution (
envsubst '${VAR1} ${VAR2}') beskytter indbyggede variabler i NGINX, Prometheus og lignende værktøjer mod utilsigtet erstatning - Citerede heredocs (
<< 'EOF') udskyder shell-udvidelsen, så skabelonindholdet når frem tilenvsubstuændret — uden behov for midlertidige filer - Valider før substitution: Brug
${VAR:?message}til at afbryde ved manglende påkrævede variabler og${VAR:-default}til valgfrie variabler - Docker-entrypoint-mønster: Generér konfigurationer ved containerens opstart, og brug derefter
exectil dæmonen, så signaler håndteres korrekt - Fejlfind uløste pladsholdere ved at bruge
greppå outputtet for resterende mønstre med${, før processen starter
Disse mønstre holder dine containerimages uforanderlige, dine hemmeligheder ude af kildekodehåndteringen og dine konfigurationer ensartede på tværs af alle miljøer.
Lær Intensiv DevOps-uddannelse med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 142
- Lektioner
- 568
Ofte stillede spørgsmål
Er lektionen “Skabelondannelse af konfigurationer med envsubst og heredocs” gratis?
Ja — alle 3 lektioner i læringssporet Intensiv DevOps-uddannelse, inklusive “Skabelondannelse af konfigurationer med envsubst og heredocs”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Intensiv DevOps-uddannelse-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Skabelondannelse af konfigurationer med envsubst og heredocs”?
Generér runtime-konfiguration fra miljøvariabler ved hjælp af envsubst og citerede heredocs. Du øver dig i Intensiv DevOps-uddannelse med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Intensiv DevOps-uddannelse?
Der kræves ingen tidligere erfaring. Intensiv DevOps-uddannelse på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 2 af 4.
Hvor lang tid tager lektionen “Skabelondannelse af konfigurationer med envsubst og heredocs”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Intensiv DevOps-uddannelse-lektion?
Ja. Alle Intensiv DevOps-uddannelse-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- Skriv slanke Dockerfiles og shell-entrypoints
- Skabelondannelse af konfigurationer med envsubst og heredocs
- Scripting af cloudressourcer via CLI og jq
- Health probes, readiness gates og venteløkker