Créer des modèles de configuration avec envsubst et des heredocs
Générez la configuration d’exécution à partir de variables d’environnement avec envsubst et des heredocs entre guillemets.
Créer des modèles de configuration avec envsubst et des heredocs est une leçon DevOps Bootcamp gratuite sur CoddyKit. Ceci est la leçon 2 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage DevOps Bootcamp, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours DevOps Bootcamp comprend 4 leçons au total.
Pourquoi la génération de configuration à l’exécution est importante
Dans les flux DevOps et les workflows de conteneurs, les fichiers de configuration comme nginx.conf, prometheus.yml et docker-compose.yml doivent souvent changer selon les environnements — préproduction, production, DR. Coder les valeurs en dur crée de la divergence et expose les secrets.
La solution est la génération de configuration à l’exécution à partir d’un modèle : fournissez un modèle contenant des marqueurs, puis injectez les valeurs réelles au démarrage à partir des variables d’environnement. Votre image reste ainsi immuable et votre configuration peut être auditée.
- Aucun secret intégré aux images
- Le même artefact est promu entre les environnements
- La configuration est générée juste avant le démarrage du processus
Deux outils complémentaires rendent cette opération triviale dans Bash : envsubst et les documents heredoc entre apostrophes.
envsubst : le générateur de configuration en une seule ligne
envsubst est un petit utilitaire GNU qui lit l’entrée standard, remplace les marqueurs $VARIABLE et ${VARIABLE} par les valeurs correspondantes de l’environnement actuel, puis écrit le résultat sur la sortie standard.
Il est fourni avec le paquet gettext et est disponible dans pratiquement toutes les distributions Linux et les images de base Docker.
- Fonctionne avec tous les formats texte : NGINX, YAML, TOML, JSON, INI
- N’évalue pas la syntaxe shell — il remplace uniquement les références aux variables
- Sûr : il n’exécute pas les commandes présentes dans le modèle
#!/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; }Substitution sélective des variables
Par défaut, envsubst remplace chaque $VAR qu’il trouve. Cela peut écraser des variables NGINX comme $uri ou $host — il s’agit de véritables directives NGINX, et non de vos variables d’environnement.
Transmettez une liste explicite de variables comme premier argument afin de limiter la substitution à ces seuls noms :
envsubst '$VAR1 $VAR2'L’argument est une chaîne entre apostrophes simples (afin que le shell ne la développe pas) contenant les noms des variables à remplacer, séparés par des espaces ou des retours à la ligne.
#!/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}'
Fichiers modèles sur le disque
Pour les configurations réelles, stockez le modèle dans un fichier (par exemple nginx.conf.template) à côté de votre fichier Docker. Au démarrage du conteneur, exécutez envsubst pour produire le fichier de configuration final avant de lancer le démon.
Il s’agit du modèle de référence utilisé par l’image Docker officielle de NGINX.
#!/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.confHeredocs entre guillemets : modèles intégrés sans fichier temporaire
Un heredoc entre guillemets (utilisant << 'EOF' avec des guillemets simples autour du délimiteur) empêche l'interpréteur de commandes de développer les variables ou d'exécuter des substitutions de commande à l'intérieur du bloc. Le contenu est traité comme une chaîne littérale.
Les heredocs sont ainsi le moyen idéal d'écrire un modèle directement dans le script et de le transmettre directement à envsubst — sans fichier intermédiaire.
<< EOF(sans guillemets) — l'interpréteur de commandes développe immédiatement$VAR<< 'EOF'(entre guillemets) — le contenu est littéral ; le développement est différé jusqu'àenvsubst
#!/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 shellCombinaison des heredocs avec la redirection de sortie
Transmettez un heredoc entre guillemets à envsubst et redirigez le résultat vers un fichier dans une seule expression. C'est la manière la plus claire de générer des fichiers de configuration dans un script de point d'entrée.
Utilisez la substitution sélective ('${VAR1} ${VAR2}') lorsque le format cible (Prometheus, NGINX, etc.) possède sa propre syntaxe $variable à protéger.
#!/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}"Valeurs par défaut et validation avant la substitution
Ne partez jamais du principe que toutes les variables requises sont définies. Utilisez l'expansion des paramètres de Bash pour fournir des valeurs par défaut ou provoquer un échec explicite :
${VAR:-default}— utilisezdefaultsiVARn'est pas définie ou est vide${VAR:?error message}— interrompez l'exécution avec une erreur siVARn'est pas définie ou est vide
Définissez ces variables avant d'appeler envsubst afin que le modèle reçoive toujours une valeur concrète ou que le script s'arrête rapidement avec un message utile.
#!/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}"Génération de configurations en plusieurs sections avec plusieurs heredocs
Pour les configurations complexes organisées en sections logiques, vous pouvez générer chaque section indépendamment et les concaténer, ou utiliser un seul heredoc couvrant tout le fichier. Les deux approches fonctionnent — choisissez selon la lisibilité.
Lorsque les sections sont incluses sous condition (par exemple, un bloc TLS uniquement si un chemin de certificat est défini), l'approche avec plusieurs heredocs et des blocs if est plus claire.
#!/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"Modèle de point d'entrée Docker
Le modèle recommandé de point d'entrée Docker utilise un script d'interpréteur de commandes (docker-entrypoint.sh) pour générer les configurations au démarrage, puis transmettre le contrôle au processus principal avec exec. L'utilisation de exec remplace le processus de l'interpréteur de commandes par le démon, de sorte que les signaux (SIGTERM, SIGINT) parviennent directement au démon — ce qui est essentiel pour un arrêt progressif.
Les fichiers modèles sont ajoutés à l'image lors de la compilation ; les valeurs sont injectées à l'exécution avec docker run -e ou env: / envFrom: de Kubernetes.
#!/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}"Modèle Kubernetes ConfigMap + envsubst
Dans Kubernetes, les variables d'environnement sont injectées via env: ou envFrom: dans la spécification du Pod. Le point d'entrée de votre conteneur appelle envsubst pour matérialiser les configurations avant le démarrage du processus — aucun ConfigMap par environnement n'est nécessaire.
Cela conserve les valeurs spécifiques à l'environnement dans les secrets Kubernetes et les ConfigMaps (pour les données non sensibles), tandis que le modèle de configuration se trouve dans l'image. Une image, de nombreux environnements.
- Compilation :
COPY nginx.conf.template /etc/nginx/templates/ - Exécution : le point d'entrée exécute
envsubstet écrit/etc/nginx/nginx.conf - Kubernetes injecte :
APP_PORT,BACKEND_HOSTdepuis un Secret ou un ConfigMap
Débogage d'envsubst : recherche des variables manquantes ou non résolues
Lorsqu'une configuration générée contient littéralement ${VAR} au lieu d'une valeur, la variable n'a pas été exportée ou n'a pas été incluse dans la liste de substitution. Utilisez ces techniques pour déboguer :
printenv | sort— répertorier toutes les variables exportées- Comparez les espaces réservés du modèle avec les variables exportées à l'aide de
grep - Exécutez
envsubstet recherchez dans la sortie les motifs${restants - Utilisez
set -udans le script appelant afin que les références à des variables non définies dans le code Bash provoquent immédiatement l'arrêt
#!/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"Vérification des connaissances : substitution sélective avec envsubst
Examinez un modèle de configuration NGINX qui contient à la fois votre variable d'application ${APP_PORT} et la variable native de NGINX $uri. Vous exécutez la commande suivante :
envsubst < nginx.conf.template > nginx.conf
Quel est le résultat ?
Récapitulatif de la leçon : création de modèles de configurations avec envsubst et des heredocs
Vous disposez désormais d'une boîte à outils de niveau production pour générer des configurations à l'exécution en Bash :
- envsubst remplace les espaces réservés
${VAR}dans tout fichier texte en utilisant l'environnement actuel — sans script ni échappement particulier - Substitution sélective (
envsubst '${VAR1} ${VAR2}') protège les variables natives de NGINX, Prometheus et des outils similaires contre tout remplacement accidentel - Heredocs entre guillemets (
<< 'EOF') reportent le développement par l'interpréteur de commandes afin que le contenu du modèle parvienne intact àenvsubst— aucun fichier temporaire n'est nécessaire - Validez avant la substitution : utilisez
${VAR:?message}pour interrompre l'exécution lorsque des variables requises manquent et${VAR:-default}pour les variables facultatives - Modèle de point d'entrée Docker : générez les configurations au démarrage du conteneur, puis utilisez
execpour le démon afin que les signaux soient correctement pris en charge - Déboguez les espaces réservés non résolus en recherchant avec
greples motifs${restants dans la sortie avant le démarrage du processus
Ces modèles permettent de conserver vos images de conteneurs immuables, d'empêcher vos secrets d'entrer dans le contrôle de version et de garder vos configurations cohérentes dans tous les environnements.
Questions Fréquemment Posées
La leçon « Créer des modèles de configuration avec envsubst et des heredocs » est-elle gratuite ?
Oui — le texte complet de « Créer des modèles de configuration avec envsubst et des heredocs » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours DevOps Bootcamp, passe à CoddyKit PRO. Le cours DevOps Bootcamp comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Créer des modèles de configuration avec envsubst et des heredocs » ?
Générez la configuration d’exécution à partir de variables d’environnement avec envsubst et des heredocs entre guillemets. Tu pratiques DevOps Bootcamp avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer DevOps Bootcamp ?
Aucune expérience préalable n'est requise. DevOps Bootcamp sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 2 sur 4.
Combien de temps prend la leçon « Créer des modèles de configuration avec envsubst et des heredocs » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon DevOps Bootcamp ?
Oui. Chaque leçon DevOps Bootcamp inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Écrire des Dockerfiles légers et des points d’entrée Shell
- Créer des modèles de configuration avec envsubst et des heredocs
- Scripter des ressources cloud avec la CLI et jq
- Sondes d’état, barrières de disponibilité et boucles d’attente