DevOps Bootcamp · Pelajaran

Membuat Template Konfigurasi dengan envsubst dan heredoc

Hasilkan konfigurasi saat runtime dari variabel environment menggunakan envsubst dan heredoc yang diberi tanda kutip.

Pelajaran 2 dari 413 langkah

Membuat Template Konfigurasi dengan envsubst dan heredoc adalah pelajaran DevOps Bootcamp gratis di CoddyKit. Ini adalah pelajaran 2 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar DevOps Bootcamp, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus DevOps Bootcamp mencakup 4 pelajaran total.

Mengapa Pembuatan Template Konfigurasi Saat Runtime Penting

Dalam alur kerja DevOps dan container, berkas konfigurasi seperti nginx.conf, prometheus.yml, dan docker-compose.yml sering kali perlu berubah antarlingkungan — staging, produksi, DR. Menetapkan nilai secara langsung dalam kode menyebabkan perbedaan konfigurasi dan terbukanya rahasia.

Solusinya adalah pembuatan template konfigurasi saat runtime: sertakan template dengan placeholder, lalu masukkan nilai sebenarnya saat startup dari variabel lingkungan. Dengan demikian, image Anda tetap tidak berubah dan konfigurasi mudah diaudit.

  • Tidak ada rahasia yang disematkan dalam image
  • Artefak yang sama dapat dipromosikan ke berbagai lingkungan
  • Konfigurasi dibuat sesaat sebelum proses dimulai

Dua alat yang saling melengkapi membuatnya mudah dilakukan dalam Bash: envsubst dan heredoc yang diberi tanda kutip.

envsubst: Pembuat Konfigurasi Satu Baris

envsubst adalah utilitas GNU kecil yang membaca stdin, mengganti placeholder $VARIABLE dan ${VARIABLE} dengan nilainya dari lingkungan saat ini, lalu menulis hasilnya ke stdout.

Utilitas ini disertakan dalam paket gettext dan tersedia di hampir semua distro Linux serta image basis Docker.

  • Berfungsi dengan format teks apa pun: NGINX, YAML, TOML, JSON, INI
  • Tidak mengevaluasi sintaks shell — hanya mengganti referensi variabel
  • Aman: tidak akan menjalankan perintah di dalam template
#!/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; }

Substitusi Variabel Selektif

Secara default, envsubst mengganti setiap $VAR yang ditemukannya. Hal ini dapat mengubah variabel NGINX seperti $uri atau $host — keduanya adalah direktif NGINX sebenarnya, bukan variabel lingkungan Anda.

Berikan daftar variabel eksplisit sebagai argumen pertama untuk membatasi substitusi hanya pada nama-nama tersebut:

envsubst '$VAR1 $VAR2'

Argumen tersebut berupa string dengan tanda kutip tunggal (agar tidak diperluas oleh shell) yang berisi nama variabel yang ingin Anda ganti, dipisahkan oleh spasi atau baris baru.

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

Berkas Template di Disk

Untuk konfigurasi nyata, simpan template sebagai berkas (misalnya, nginx.conf.template) bersama Dockerfile Anda. Saat container dimulai, jalankan envsubst untuk menghasilkan berkas konfigurasi akhir sebelum meluncurkan daemon.

Ini adalah pola standar yang digunakan oleh image NGINX resmi.

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

Heredoc Berpetik: Templat Sebaris Tanpa Berkas Sementara

heredoc berpetik (menggunakan << 'EOF' dengan tanda petik tunggal di sekitar pembatas) mencegah shell memperluas variabel atau menjalankan substitusi perintah di dalam blok. Konten diperlakukan sebagai teks harfiah.

Dengan demikian, heredoc menjadi cara yang sempurna untuk menulis templat sebaris dan langsung menyalurkannya ke envsubst — tanpa memerlukan berkas perantara.

  • << EOF (tanpa petik) — shell segera memperluas $VAR
  • << 'EOF' (dengan petik) — konten bersifat harfiah; perluasan ditunda hingga 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

Menggabungkan Heredoc dengan Pengalihan Keluaran

Salurkan heredoc berpetik melalui envsubst dan alihkan hasilnya ke sebuah berkas dalam satu ekspresi. Ini adalah pola penulisan paling rapi untuk membuat berkas konfigurasi dalam skrip titik masuk.

Gunakan substitusi selektif ('${VAR1} ${VAR2}') jika format tujuan (Prometheus, NGINX, dan sebagainya) memiliki sintaks $variable sendiri yang harus dilindungi.

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

Nilai Bawaan dan Validasi Sebelum Substitusi

Jangan pernah berasumsi bahwa semua variabel yang diperlukan telah ditetapkan. Gunakan perluasan parameter Bash untuk menyediakan nilai bawaan atau menghentikan eksekusi dengan pesan yang jelas:

  • ${VAR:-default} — gunakan default jika VAR tidak ditetapkan atau kosong
  • ${VAR:?error message} — batalkan eksekusi dengan galat jika VAR tidak ditetapkan atau kosong

Tetapkan variabel-variabel ini sebelum memanggil envsubst agar templat selalu menerima nilai konkret atau skrip segera berhenti dengan pesan yang membantu.

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

Membuat Konfigurasi Multi-Bagian dengan Beberapa Heredoc

Untuk konfigurasi kompleks yang dibangun dari beberapa bagian logis, Anda dapat membuat setiap bagian secara terpisah lalu menggabungkannya, atau menggunakan satu heredoc yang mencakup seluruh berkas. Keduanya dapat digunakan — pilih berdasarkan keterbacaan.

Jika bagian-bagian disertakan secara kondisional (misalnya, blok TLS hanya jika jalur sertifikat telah ditetapkan), pendekatan dengan beberapa heredoc dan blok if lebih rapi.

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

Pola Titik Masuk Docker

Pola titik masuk Docker yang disarankan menggunakan skrip shell (docker-entrypoint.sh) untuk membuat konfigurasi saat startup, lalu menyerahkan kendali kepada proses utama dengan exec. Penggunaan exec menggantikan proses shell dengan proses layanan, sehingga sinyal (SIGTERM, SIGINT) langsung diterima oleh proses layanan — hal yang sangat penting untuk penghentian yang baik.

Berkas templat ditambahkan ke citra saat citra dibangun; values disuntikkan saat dijalankan dari docker run -e atau 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}"

Pola ConfigMap + envsubst Kubernetes

Di Kubernetes, variabel lingkungan disuntikkan melalui env: atau envFrom: dalam spesifikasi Pod. Titik masuk kontainer Anda memanggil envsubst untuk mewujudkan konfigurasi sebelum proses dimulai — tidak diperlukan ConfigMap untuk setiap lingkungan.

Dengan cara ini, nilai khusus lingkungan tetap berada dalam Rahasia dan ConfigMaps Kubernetes (untuk data yang tidak sensitif), sementara templat konfigurasi berada di dalam citra. Satu citra, banyak lingkungan.

  • Pembangunan: COPY nginx.conf.template /etc/nginx/templates/
  • Saat dijalankan: titik masuk menjalankan envsubst, lalu menulis /etc/nginx/nginx.conf
  • K8s menyuntikkan: APP_PORT, BACKEND_HOST dari Rahasia/ConfigMap

Men-debug envsubst: Menemukan Variabel yang Hilang atau Belum Terselesaikan

Jika konfigurasi yang dibuat berisi ${VAR} secara harfiah, bukan sebuah nilai, berarti variabel tersebut belum diekspor atau tidak disertakan dalam daftar substitusi. Gunakan teknik-teknik berikut untuk men-debug:

  • printenv | sort — mencantumkan semua variabel yang diekspor
  • Bandingkan placeholder dalam templat dengan variabel yang diekspor menggunakan grep
  • Jalankan envsubst dan gunakan grep pada keluarannya untuk mencari pola ${ yang masih tersisa
  • Gunakan set -u dalam skrip pemanggil agar referensi variabel yang belum ditetapkan dalam kode Bash segera menghentikan eksekusi
#!/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"

Pemeriksaan Pengetahuan: Substitusi Selektif envsubst

Pertimbangkan templat konfigurasi NGINX yang berisi variabel aplikasi Anda, ${APP_PORT}, sekaligus variabel bawaan NGINX, $uri. Anda menjalankan perintah berikut:

envsubst < nginx.conf.template > nginx.conf

Apa hasilnya?

Ringkasan Pelajaran: Membuat Templat Konfigurasi dengan envsubst dan Heredoc

Sekarang Anda memiliki perangkat siap produksi untuk membuat konfigurasi saat runtime dalam Bash:

  • envsubst mengganti placeholder ${VAR} dalam berkas teks apa pun menggunakan lingkungan saat ini — tanpa skrip dan tanpa pelolosan khusus
  • Substitusi selektif (envsubst '${VAR1} ${VAR2}') melindungi variabel bawaan dalam NGINX, Prometheus, dan alat serupa agar tidak terganti secara tidak sengaja
  • Heredoc berpetik (<< 'EOF') menunda perluasan shell sehingga konten templat sampai ke envsubst tanpa perubahan — tidak diperlukan berkas sementara
  • Validasikan sebelum melakukan substitusi: gunakan ${VAR:?message} untuk menghentikan eksekusi jika variabel wajib tidak ada dan ${VAR:-default} untuk variabel opsional
  • Pola titik masuk Docker: buat konfigurasi saat kontainer dimulai, lalu gunakan exec untuk proses layanan agar sinyal ditangani dengan benar
  • Debug placeholder yang belum terselesaikan dengan mencari pola ${ yang masih tersisa dalam keluaran menggunakan grep sebelum proses dimulai

Pola-pola ini menjaga citra kontainer Anda tetap tidak berubah, menjaga rahasia agar tidak masuk ke kontrol sumber, serta memastikan konfigurasi konsisten di setiap lingkungan.

Gratis untuk memulai

Belajar DevOps Bootcamp dengan tutor AI — gratis

Tulis dan jalankan kode asli di browser kamu, dapatkan bantuan instan dari tutor AI 24/7, dan lanjutkan di mana kamu tinggalkan di web atau aplikasi.

Kursus
142
Pelajaran
568

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Membuat Template Konfigurasi dengan envsubst dan heredoc” gratis?

Ya — teks lengkap “Membuat Template Konfigurasi dengan envsubst dan heredoc” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus DevOps Bootcamp, upgrade ke CoddyKit PRO. Kursus DevOps Bootcamp mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Membuat Template Konfigurasi dengan envsubst dan heredoc”?

Hasilkan konfigurasi saat runtime dari variabel environment menggunakan envsubst dan heredoc yang diberi tanda kutip. Kamu berlatih DevOps Bootcamp dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai DevOps Bootcamp?

Tidak diperlukan pengalaman sebelumnya. DevOps Bootcamp di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 2 dari 4.

Berapa lama pelajaran “Membuat Template Konfigurasi dengan envsubst dan heredoc” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran DevOps Bootcamp ini?

Ya. Setiap pelajaran DevOps Bootcamp menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. Menulis Dockerfile dan Entrypoint Shell yang Ringkas
  2. Membuat Template Konfigurasi dengan envsubst dan heredoc
  3. Membuat Skrip Resource Cloud dengan CLI dan jq
  4. Probe Kesehatan, Gerbang Kesiapan, dan Loop Tunggu
← Kembali ke DevOps Bootcamp