DevOps-bootcamp · Oppitunti

Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla

Luo ajonaikaiset määritykset ympäristömuuttujista envsubstilla ja lainatuilla heredoc-rakenteilla.

Oppitunti 2/413 vaihetta

Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla on ilmainen DevOps-bootcamp-oppitunti CoddyKitissä. Tämä on oppitunti 2/4. Voit lukea tästä oppimispolusta kokonaan mitkä tahansa 3 oppituntia ilmaiseksi — sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä käytännön harjoittelun sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. Oppitunti kuuluu DevOps-bootcamp-oppimispolkuun, ja edistymisesi synkronoituu verkon ja CoddyKit-sovelluksen välillä. DevOps-bootcamp-kurssilla on yhteensä 4 oppituntia.

Miksi ajonaikainen asetusten mallintaminen on tärkeää

DevOps- ja konttityönkuluissa asetustiedostoja, kuten nginx.conf, prometheus.yml ja docker-compose.yml, on usein muutettava ympäristöjen välillä: staging-, tuotanto- ja DR-ympäristöissä. Arvojen kovakoodaaminen aiheuttaa ympäristöjen ajautumista erilleen ja altistaa salaisuuksien vuotamiselle.

Ratkaisu on ajonaikainen asetusten mallintaminen: toimittakaa mallipohja paikkamerkkeineen ja lisätkää todelliset arvot käynnistyksen yhteydessä ympäristömuuttujista. Näin image pysyy muuttumattomana ja asetukset ovat tarkastettavissa.

  • Salaisuuksia ei upoteta imageen
  • Sama artefakti voidaan viedä eri ympäristöihin
  • Asetukset muodostetaan juuri ennen prosessin käynnistymistä

Kaksi toisiaan täydentävää työkalua tekee tästä helppoa Bashissa: envsubst ja lainausmerkeillä suojatut heredoc-rakenteet.

envsubst: asetusten muodostaminen yhdellä komennolla

envsubst on pieni GNU-apuohjelma, joka lukee vakiosyötettä, korvaa $VARIABLE- ja ${VARIABLE}-paikkamerkit nykyisen ympäristön arvoilla ja kirjoittaa tuloksen vakiotulosteeseen.

Se toimitetaan gettext-paketin mukana ja on saatavilla lähes kaikissa Linux-jakeluissa ja Docker-perusimageissa.

  • Toimii missä tahansa tekstimuodossa: NGINX, YAML, TOML, JSON ja INI
  • Ei suorita shell-syntaksia, vaan korvaa ainoastaan muuttujaviittaukset
  • Turvallinen: se ei suorita mallipohjassa olevia komentoja
#!/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; }

Valikoiva muuttujien korvaaminen

Oletusarvoisesti envsubst korvaa jokaisen löytämänsä $VAR-muuttujan. Tämä voi sotkea NGINX-muuttujat, kuten $uri tai $host, jotka ovat todellisia NGINX-direktiivejä eivätkä ympäristömuuttujia.

Välittäkää muuttujat eksplisiittisenä luettelona ensimmäisenä argumenttina, jotta korvaaminen rajoittuu vain kyseisiin nimiin:

envsubst '$VAR1 $VAR2'

Argumentti on yksinkertaisilla lainausmerkeillä rajattu merkkijono, jolloin shell ei laajenna sitä. Merkkijono sisältää korvattavien muuttujien nimet välilyönneillä tai rivinvaihdoilla eroteltuina.

#!/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}'

Mallipohjatiedostot levyllä

Todellisia asetuksia varten tallentakaa mallipohja tiedostona (esimerkiksi nginx.conf.template) Dockerfile-tiedoston rinnalle. Suorittakaa kontin käynnistyessä envsubst, jotta lopullinen asetustiedosto muodostetaan ennen taustapalvelun käynnistämistä.

Tämä on virallisessa NGINX Docker -imagessa käytetty vakiintunut malli.

#!/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.conf

Lainausmerkeillä rajatut heredoc-lohkot: upotetut mallipohjat ilman väliaikaistiedostoa

Lainausmerkeillä rajattu heredoc (jossa käytetään koodia << 'EOF' ja erotin on yksinkertaisissa lainausmerkeissä) estää komentotulkkia laajentamasta muuttujia tai suorittamasta komentokorvauksia lohkon sisällä. Sisältö käsitellään literaalisena merkkijonona.

Näin heredoc-lohkot ovat erinomainen tapa kirjoittaa mallipohja suoraan skriptiin ja ohjata se putkella suoraan ohjelmalle envsubst — välitiedostoa ei tarvita.

  • << EOF (ilman lainausmerkkejä) — komentotulkki laajentaa $VAR-muuttujan heti
  • << 'EOF' (lainausmerkeillä rajattu) — sisältö on literaalista; laajennus siirtyy ohjelmalle 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 shell

Heredoc-lohkojen yhdistäminen tulosteen uudelleenohjaukseen

Ohjatkaa lainausmerkeillä rajattu heredoc-lohko ohjelman envsubst läpi ja uudelleenohjatkaa tulos tiedostoon yhdellä lausekkeella. Tämä on selkein tapa luoda asetustiedostoja entrypoint-skriptissä.

Käyttäkää valikoivaa korvaamista ('${VAR1} ${VAR2}'), kun kohdemuodolla, kuten Prometheuksella tai NGINXillä, on oma suojattava $variable-syntaksinsa.

#!/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}"

Oletusarvot ja tarkistus ennen korvaamista

Älkää koskaan olettako, että kaikki pakolliset muuttujat on asetettu. Käyttäkää Bashin parametrilaajennusta oletusarvojen antamiseen tai ilmoittakaa virheestä heti:

  • ${VAR:-default} — käyttäkää arvoa default, jos VAR on asettamatta tai tyhjä
  • ${VAR:?error message} — keskeyttäkää virheilmoitukseen, jos VAR on asettamatta tai tyhjä

Asettakaa nämä ennen ohjelman envsubst kutsumista, jotta mallipohja saa aina konkreettisen arvon tai skripti pysähtyy heti hyödyllisen viestin kanssa.

#!/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}"

Moniosioisten asetustiedostojen luominen useilla heredoc-lohkoilla

Monimutkaisissa, loogisista osioista koostuvissa asetustiedostoissa voitte luoda kunkin osion erikseen ja yhdistää ne tai käyttää yhtä koko tiedoston kattavaa heredoc-lohkoa. Molemmat tavat toimivat — valitkaa luettavuuden kannalta sopivampi.

Kun osioita sisällytetään ehtojen perusteella, esimerkiksi TLS-lohko vain, jos sertifikaatin polku on asetettu, usean heredoc-lohkon käyttäminen yhdessä if-lohkojen kanssa on selkeämpää.

#!/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"

Dockerin entrypoint-malli

Suositeltu Dockerin entrypoint-malli käyttää shell-skriptiä (docker-entrypoint.sh) asetustiedostojen luomiseen käynnistyksen yhteydessä ja siirtää sitten hallinnan pääprosessille komennolla exec. exec korvaa shell-prosessin daemonilla, joten signaalit (SIGTERM, SIGINT) saavuttavat daemonin suoraan — tämä on välttämätöntä hallitulle sammutukselle.

Mallipohjatiedostot lisätään levykuvaan koontivaiheessa; arvot syötetään suoritusaikana komennolla docker run -e tai Kubernetesin määrityksillä 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}"

Kubernetesin ConfigMap- ja envsubst-malli

Kubernetesissa ympäristömuuttujat syötetään Pod-määrityksen kohdissa env: tai envFrom:. Säilön entrypoint kutsuu ohjelmaa envsubst asetustiedostojen muodostamiseksi ennen prosessin käynnistymistä — ympäristökohtaisia ConfigMap-resursseja ei tarvita.

Näin ympäristökohtaiset arvot säilyvät Kubernetesin Secrets- ja ConfigMaps-resursseissa (ei-arkaluonteisia tietoja varten), kun taas asetusten mallipohja sijaitsee levykuvassa. Yksi levykuva, monta ympäristöä.

  • Koonti: COPY nginx.conf.template /etc/nginx/templates/
  • Suoritusaikana: entrypoint suorittaa ohjelman envsubst ja kirjoittaa tiedoston /etc/nginx/nginx.conf
  • K8s syöttää: APP_PORT- ja BACKEND_HOST-arvot Secret- tai ConfigMap-resurssista

envsubst-ohjelman vianmääritys: puuttuvien tai ratkaisemattomien muuttujien etsiminen

Kun luotu asetustiedosto sisältää arvon sijaan literaalisen merkkijonon ${VAR}, muuttujaa ei ole viety ympäristöön tai sitä ei ole sisällytetty korvausluetteloon. Käyttäkää vianmääritykseen seuraavia tekniikoita:

  • printenv | sort — luettelee kaikki viedyt muuttujat
  • Verratkaa mallipohjan paikkamerkkejä vietyihin muuttujiin komennolla grep
  • Suorittakaa ohjelma envsubst ja etsikää tulosteesta jäljelle jääviä ${-alkuisia merkkijonoja
  • Käyttäkää kutsuvassa skriptissä komentoa set -u, jotta asettamattomiin muuttujiin viittaaminen Bash-koodissa keskeyttää suorituksen heti
#!/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"

Tietotesti: envsubst-ohjelman valikoiva korvaaminen

Tarkastelkaa NGINX-asetusten mallipohjaa, joka sisältää sekä sovelluksen muuttujan ${APP_PORT} että NGINXin oman muuttujan $uri. Suoritatte seuraavan komennon:

envsubst < nginx.conf.template > nginx.conf

Mikä on tulos?

Oppitunnin yhteenveto: asetusten mallintaminen envsubst-ohjelmalla ja heredoc-lohkoilla

Nyt käytössänne on tuotantokäyttöön soveltuva työkalupakki asetusten luomiseen suoritusaikana Bashissa:

  • envsubst korvaa ${VAR}-paikkamerkit missä tahansa tekstitiedostossa nykyisen ympäristön avulla — ilman skriptausta tai erityistä merkkien suojausta
  • Valikoiva korvaaminen (envsubst '${VAR1} ${VAR2}') suojaa NGINXin, Prometheuksen ja vastaavien työkalujen omia muuttujia tahattomalta korvaamiselta
  • Lainausmerkeillä rajatut heredoc-lohkot (<< 'EOF') siirtävät shellin laajennuksen myöhemmäksi, joten mallipohjan sisältö välittyy ohjelmalle envsubst muuttumattomana — väliaikaistiedostoja ei tarvita
  • Validoikaa ennen korvaamista: käyttäkää komentoa ${VAR:?message} pakollisten muuttujien puuttuessa keskeyttämiseen ja komentoa ${VAR:-default} valinnaisille muuttujille
  • Dockerin entrypoint-malli: luokaa asetustiedostot säilön käynnistyessä ja suorittakaa sitten daemon komennolla exec, jotta signaalit käsitellään oikein
  • Selvittäkää ratkaisemattomat paikkamerkit etsimällä tulosteesta jäljelle jääviä ${-alkuisia merkkijonoja ennen prosessin käynnistymistä

Näiden mallien avulla levykuvat pysyvät muuttumattomina, salaisuudet poissa lähdekoodinhallinnasta ja asetukset yhdenmukaisina kaikissa ympäristöissä.

Aloita maksutta

Opi DevOps-bootcamp tekoälytuutorin avulla — ilmaiseksi

Kirjoita ja suorita oikeaa koodia selaimessa, saa välitöntä apua tekoälytuutorilta ympäri vuorokauden ja jatka siitä, mihin jäit, verkossa tai sovelluksessa.

Kurssit
142
Oppitunnit
568

Usein kysytyt kysymykset

Onko oppitunti ”Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla” ilmainen?

Kyllä — voit lukea täällä verkossa kokonaan ilmaiseksi mitkä tahansa DevOps-bootcamp-oppimispolun 3 oppituntia, myös oppitunnin “Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla”. Sen jälkeen CoddyKit PRO avaa kaikki oppitunnit sekä interaktiiviset harjoitukset sisäänrakennetulla koodieditorilla ja ympäri vuorokauden toimivalla tekoälytuutorilla. DevOps-bootcamp-kurssilla on yhteensä 4 oppituntia.

Mitä opin oppitunnilla ”Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla”?

Luo ajonaikaiset määritykset ympäristömuuttujista envsubstilla ja lainatuilla heredoc-rakenteilla. Harjoittelet DevOps-bootcamp-aihetta koodilla, jonka suoritat suoraan selaimessa. Ympäri vuorokauden käytettävissä oleva tekoälytuutori vastaa kysymyksiisi oppitunnin aikana.

Tarvitsenko kokemusta aloittaakseni DevOps-bootcamp-opiskelun?

Aiempi kokemus ei ole tarpeen. CoddyKitin DevOps-bootcamp-oppimispolku sopii vasta-alkajista edistyneisiin, joten voit aloittaa tästä tai alusta ja edetä omaan tahtiisi. Tämä on oppitunti 2/4.

Kuinka kauan ”Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla”-oppitunnin suorittaminen kestää?

Useimmat CoddyKitin oppitunnit kestävät noin 5–10 minuuttia. Jokainen oppitunti on lyhyt ja interaktiivinen, joten edistyt tasaisesti ja voit jatkaa siitä, mihin jäit – sekä verkossa että sovelluksessa.

Voinko kirjoittaa ja suorittaa koodia tällä DevOps-bootcamp-oppitunnilla?

Kyllä. Jokainen DevOps-bootcamp-oppitunti sisältää sisäänrakennetun koodieditorin, joten voit kirjoittaa ja suorittaa oikeaa koodia suoraan selaimessa ja saada välitöntä palautetta tekoälyltä – paikallista asennusta ei tarvita.

Kaikki tämän kurssin oppitunnit

  1. Keveiden Dockerfile-tiedostojen ja shell-entripointien kirjoittaminen
  2. Määritysten mallintaminen envsubstilla ja heredoc-rakenteilla
  3. Pilviresurssien skriptaus CLI-työkaluilla ja jq:lla
  4. Kuntotarkistukset, valmiusportit ja odotussilmukat
← Takaisin: DevOps-bootcamp