NGINX in Containers
NGINX in Docker and Containerized Runtime
Memahami NGINX official image, config mounting, env substitution, non-root container, read-only filesystem, health check, reload, graceful shutdown, dan sidecar pattern.
Part 022 — NGINX in Docker and Containerized Runtime
1. Tujuan Part Ini
Menjalankan NGINX di container bukan sekadar:
docker run nginx
Dalam enterprise production system, NGINX di container harus dipahami sebagai komponen runtime yang punya lifecycle, filesystem, signal handling, config injection, secret handling, logging, health check, security context, resource limit, dan deployment semantics.
Part ini membahas NGINX saat berjalan di Docker/Kubernetes/container runtime, terutama untuk konteks:
reverse proxy di depan Java/JAX-RS service
NGINX sidecar
NGINX ingress controller
static asset container
local integration testing
platform-managed proxy
cloud/on-prem/hybrid deployment
Target utamanya adalah mampu mereview containerized NGINX secara production-ready.
2. Mental Model: NGINX Container Is Not a Mini VM
Container bukan VM kecil. Container adalah proses dengan filesystem, namespace, cgroup, network namespace, dan lifecycle yang dikontrol orchestrator.
Untuk NGINX, implikasinya:
PID 1 matters
signal handling matters
stdout/stderr logging matters
read-only filesystem matters
mounted config matters
mounted secret matters
resource limit matters
health check matters
rolling update matters
graceful shutdown matters
Jika NGINX berjalan baik di VM, belum tentu perilakunya aman di Kubernetes.
Contoh perbedaan penting:
| Area | VM/Bare Metal | Container/Kubernetes |
|---|---|---|
| Config file | Local disk/server management | Image, ConfigMap, mounted volume, generated config |
| Log | File di /var/log/nginx | stdout/stderr atau sidecar collector |
| Secret | File permission/manual deploy | Secret volume, cert-manager, CSI, external secret |
| Reload | systemctl/service reload | signal ke process, controller reload, rollout |
| Health | manual/systemd | liveness/readiness/startup probe |
| Resource | host-level | cgroup request/limit |
| Shutdown | admin controlled | orchestrator sends SIGTERM |
3. Official NGINX Image Mental Model
Official NGINX image biasanya menyediakan:
nginx binary
base OS image
default nginx.conf
default server config
entrypoint scripts
log symlink to stdout/stderr
html root default
Common layout:
/etc/nginx/nginx.conf
/etc/nginx/conf.d/default.conf
/usr/share/nginx/html
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/cache/nginx
/var/run
Dalam production, default config jarang cukup.
Checklist saat memakai image:
Apakah base image diset eksplisit dengan tag version?
Apakah default server dihapus/diganti?
Apakah config dipin lewat image atau mounted volume?
Apakah running user root atau non-root?
Apakah image discan vulnerability?
Apakah log keluar ke stdout/stderr?
Apakah temp/cache directory writable?
4. Version Pinning
Anti-pattern:
FROM nginx:latest
Masalah:
build tidak reproducible
minor/patch behavior bisa berubah tanpa review
security scan sulit ditelusuri
rollback tidak deterministik
Lebih baik:
FROM nginx:1.27-alpine
Atau sesuai standard internal:
FROM <internal-registry>/base/nginx:<approved-version>
Prinsip:
production image harus dapat direbuild dan menghasilkan behavior yang dapat diprediksi.
Internal verification:
Cek image tag di Dockerfile/Helm values.
Cek apakah image berasal dari registry internal.
Cek vulnerability scan policy.
Cek upgrade cadence NGINX.
5. Config Packaging Strategy
Ada beberapa cara memasukkan config NGINX ke container.
Option 1: Bake Config into Image
FROM nginx:1.27-alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY conf.d/ /etc/nginx/conf.d/
Benefit:
immutable artifact
config terversi bersama image
lebih mudah direproduksi
Risk:
perubahan config butuh rebuild image
kurang fleksibel untuk environment-specific override
secret tidak boleh dibake ke image
Option 2: Mount Config as Volume
Di Kubernetes biasanya memakai ConfigMap.
volumeMounts:
- name: nginx-config
mountPath: /etc/nginx/conf.d
volumes:
- name: nginx-config
configMap:
name: nginx-config
Benefit:
config mudah diganti via GitOps/ConfigMap
cocok untuk environment-specific routing
Risk:
config drift jika tidak dikelola GitOps
reload behavior harus jelas
invalid config dapat membuat pod gagal
mount path bisa menimpa default config tanpa sengaja
Option 3: Generate Config at Startup
Menggunakan template dan environment substitution.
nginx.conf.template -> envsubst -> nginx.conf -> nginx -g 'daemon off;'
Benefit:
satu image untuk banyak environment
simple variable substitution
Risk:
runtime error baru terlihat saat startup
secret bisa bocor via env
template logic sulit direview jika terlalu kompleks
6. Environment Substitution
NGINX config native tidak membaca environment variable langsung di semua context seperti aplikasi biasa.
Pattern umum:
envsubst '${UPSTREAM_HOST} ${UPSTREAM_PORT}' \
< /etc/nginx/templates/default.conf.template \
> /etc/nginx/conf.d/default.conf
nginx -g 'daemon off;'
Template:
upstream app_backend {
server ${UPSTREAM_HOST}:${UPSTREAM_PORT};
}
server {
listen 8080;
location /api/ {
proxy_pass http://app_backend;
}
}
Risiko:
missing env menghasilkan config invalid atau target kosong
nilai env tidak tervalidasi
escaping buruk bisa menghasilkan config injection
startup script terlalu pintar dan sulit diaudit
Production advice:
Validasi config setelah template dirender.
Jangan simpan private key atau secret sensitif sebagai env jika bisa memakai Secret volume.
Gunakan allowlist variable yang disubstitusi.
Fail fast jika variable wajib tidak ada.
7. Config Validation in Container
Sebelum NGINX start atau reload:
nginx -t
Di Dockerfile/CI:
docker run --rm <image> nginx -t
Dengan custom config:
docker run --rm \
-v "$PWD/nginx.conf:/etc/nginx/nginx.conf:ro" \
<image> nginx -t
Di Kubernetes/GitOps pipeline:
render Helm chart
extract ConfigMap
run nginx -t against rendered config
fail CI if invalid
Prinsip:
Invalid NGINX config tidak boleh pertama kali ditemukan oleh production pod.
8. Running NGINX in Foreground
Di container, NGINX harus berjalan di foreground.
Umum:
nginx -g 'daemon off;'
Jika daemon mode aktif, container dapat exit atau lifecycle menjadi tidak jelas.
Mental model:
container hidup selama main process hidup
main process harus NGINX master process atau entrypoint yang benar-benar menunggu NGINX
Anti-pattern:
service nginx start
sleep infinity
Masalah:
orchestrator tidak melihat process NGINX sebenarnya
signal handling buruk
crash NGINX bisa tersembunyi
shutdown tidak graceful
9. PID 1 and Signal Handling
Dalam container, process utama menjadi PID 1. PID 1 punya perilaku khusus terhadap signal dan child process.
Untuk NGINX, signal penting:
SIGTERM -> graceful shutdown request dari orchestrator
SIGQUIT -> graceful shutdown NGINX
SIGHUP -> reload config
SIGUSR1 -> reopen logs
Dalam Kubernetes, saat pod dihentikan:
Kubernetes mengirim SIGTERM
menunggu terminationGracePeriodSeconds
jika belum selesai, SIGKILL
Jika entrypoint script tidak meneruskan signal ke NGINX, shutdown bisa tidak graceful.
Checklist:
Apakah NGINX process menerima SIGTERM?
Apakah entrypoint memakai exec?
Apakah ada preStop hook?
Apakah terminationGracePeriodSeconds cukup untuk long-lived connection?
Entrypoint pattern:
#!/bin/sh
set -eu
nginx -t
exec nginx -g 'daemon off;'
exec penting agar NGINX menggantikan shell process dan menerima signal langsung.
10. Graceful Shutdown
Graceful shutdown berarti NGINX berhenti menerima connection baru dan memberi waktu connection aktif selesai.
Dalam Kubernetes, graceful shutdown dipengaruhi oleh:
readiness probe
preStop hook
terminationGracePeriodSeconds
cloud load balancer deregistration delay
Ingress controller behavior
upstream Java service readiness
long-lived WebSocket/SSE connections
Problem umum:
pod menerima SIGTERM
readiness belum berubah menjadi false
load balancer masih mengirim traffic
NGINX mulai shutdown
client melihat connection reset/502
Mitigation pattern:
mark pod not ready
wait short drain period
then stop NGINX gracefully
Contoh conceptual Kubernetes lifecycle:
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 10; nginx -s quit"]
terminationGracePeriodSeconds: 60
Catatan:
Nilai sleep dan grace period harus diverifikasi dengan platform behavior, bukan dicopy.
11. Reload Inside Container
Reload config:
nginx -s reload
Atau:
kill -HUP <nginx-master-pid>
Reload NGINX biasanya zero-downtime secara konsep:
master load config baru
jika valid, worker baru dibuat
worker lama menyelesaikan request aktif
worker lama keluar
Tetapi dalam container/Kubernetes, reload perlu governance:
Siapa yang trigger reload?
Bagaimana config change dideteksi?
Apakah ConfigMap update otomatis terlihat di volume?
Apakah reload terjadi setelah file benar-benar update?
Apakah invalid config dicegah?
Apakah controller melakukan reload sendiri?
Untuk NGINX Ingress Controller, jangan menganggap kita mengelola reload manual. Controller biasanya generate config dan reload berdasarkan Ingress/ConfigMap changes.
12. Read-Only Filesystem
Security hardening umum:
securityContext:
readOnlyRootFilesystem: true
Tetapi NGINX butuh lokasi writable untuk:
pid file
cache/temp files
client body temp
proxy temp
fastcgi/uwsgi/scgi temp jika dipakai
Jika root filesystem read-only, perlu mount writable untuk path tertentu.
Contoh conceptual:
volumeMounts:
- name: nginx-cache
mountPath: /var/cache/nginx
- name: nginx-run
mountPath: /var/run
volumes:
- name: nginx-cache
emptyDir: {}
- name: nginx-run
emptyDir: {}
Failure mode:
open() "/var/run/nginx.pid" failed
mkdir() "/var/cache/nginx/client_temp" failed
permission denied
read-only file system
pod crashloop
13. Non-Root Container
Running as root meningkatkan risiko blast radius jika container compromise.
Kubernetes hardening:
securityContext:
runAsNonRoot: true
runAsUser: 101
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
Issue utama:
port <1024 butuh privilege
file ownership untuk config/cache/temp
pid path permission
log path permission
Solusi umum:
listen di port non-privileged seperti 8080
Service/Ingress/LB expose port 80/443 di luar container
chown writable directories di image build
mount volume dengan permission sesuai
Contoh:
server {
listen 8080;
}
Jangan memaksa container root hanya agar bisa bind port 80.
14. Linux Capabilities
Untuk bind port 80/443 sebagai non-root, kadang orang menambahkan capability:
capabilities:
add:
- NET_BIND_SERVICE
Namun dalam Kubernetes, sering lebih aman:
container listen 8080/8443
Service expose 80/443
Prinsip:
Kurangi privilege jika tidak benar-benar dibutuhkan.
Internal verification:
Cek apakah container berjalan root.
Cek capability tambahan.
Cek apakah privileged mode dipakai.
Cek apakah port rendah sebenarnya diperlukan di dalam container.
15. Health Check
NGINX container perlu health check yang memeriksa readiness, bukan hanya process alive.
Basic endpoint:
server {
listen 8080;
location = /healthz {
access_log off;
return 200 "ok\n";
}
}
Kubernetes probe:
readinessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 10
timeoutSeconds: 2
livenessProbe:
httpGet:
path: /healthz
port: 8080
periodSeconds: 30
timeoutSeconds: 2
Tetapi health check harus sesuai peran NGINX.
Jika NGINX adalah reverse proxy, ada dua jenis health:
NGINX process health
upstream reachability health
Jangan selalu mencampur keduanya.
Jika readiness bergantung pada upstream, maka outage backend bisa membuat NGINX pod unready dan memicu cascading traffic instability.
Design question:
Apakah proxy harus tetap ready saat upstream down untuk mengembalikan 503 yang jelas?
Atau harus dikeluarkan dari LB jika upstream tidak reachable?
Jawabannya bergantung pada arsitektur.
16. Logging to stdout/stderr
Dalam container, log idealnya keluar ke stdout/stderr agar collector platform mengambilnya.
Pattern umum:
access_log /dev/stdout main;
error_log /dev/stderr warn;
Atau official image bisa men-symlink file log ke stdout/stderr.
Anti-pattern:
log hanya ke file lokal container
log hilang saat pod restart
log tidak dikumpulkan collector
log volume penuh
Untuk production:
Gunakan structured log jika memungkinkan.
Jangan log PII/sensitive token.
Pastikan request_id/correlation_id ada.
Pastikan request_time dan upstream_response_time tersedia.
17. ConfigMap Volume Behavior
Di Kubernetes, ConfigMap volume dapat update secara eventual, bukan instant transactional reload.
Important behavior:
ConfigMap object update tidak otomatis berarti NGINX reload.
Mounted file bisa berubah setelah delay.
NGINX tidak membaca config baru sampai reload.
SubPath mount biasanya tidak menerima update otomatis seperti directory mount.
Common failure:
ConfigMap berubah
pod tidak reload
traffic masih memakai config lama
operator mengira perubahan sudah live
Atau:
ConfigMap berubah
reload otomatis terjadi
config invalid
pod crash/reload loop
Production pattern:
Config changes lewat GitOps.
Render dan validate di CI.
Rollout restart atau controller-managed reload jelas.
Rollback jelas.
18. Secret Volume and TLS Key Handling
TLS private key tidak boleh dibake ke image.
Pattern:
volumes:
- name: tls-secret
secret:
secretName: nginx-tls
volumeMounts:
- name: tls-secret
mountPath: /etc/nginx/tls
readOnly: true
NGINX config:
ssl_certificate /etc/nginx/tls/tls.crt;
ssl_certificate_key /etc/nginx/tls/tls.key;
Considerations:
certificate rotation membutuhkan reload
file permission harus cocok dengan runAsUser
secret exposure harus diaudit
external secret/cert-manager ownership harus jelas
Internal verification:
Cek apakah TLS secret dikelola cert-manager, cloud cert manager, Vault, atau manual.
Cek rotation runbook.
Cek apakah NGINX reload saat secret berubah.
Cek apakah private key pernah masuk image/repo/log.
19. Container Resource Request and Limit
NGINX container perlu resource request/limit yang realistis.
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "1"
memory: "512Mi"
Tapi angka harus berdasarkan traffic shape.
Resource dipengaruhi oleh:
RPS
active connections
TLS termination
compression
buffering
large payload
structured logging
WAF module
HTTP/2 streams
WebSocket/SSE
Risk CPU limit terlalu rendah:
CPU throttling
p99 latency naik
NGINX terlihat healthy tapi lambat
Risk memory limit terlalu rendah:
OOMKilled
pod restart
connection reset
sporadic 502/503
Risk ephemeral storage tidak diperhatikan:
temp file penuh
pod evicted
large upload/download gagal
20. Sidecar Pattern
NGINX sidecar berarti NGINX berjalan dalam pod yang sama dengan aplikasi.
Pattern:
client -> Service -> Pod
-> NGINX container -> Java container localhost:8080
Use case:
TLS termination lokal
static asset serving di samping app
legacy app path rewrite
local auth/filtering
protocol adaptation sederhana
membatasi exposure aplikasi
Benefit:
NGINX dan app deploy bersama
localhost communication
config per-service
blast radius lebih kecil daripada global ingress config
Risk:
resource contention dengan Java container
observability lebih kompleks
sidecar crash memengaruhi app pod
config duplication antar service
security boundary tidak sama dengan separate proxy
scaling NGINX mengikuti scaling app, bukan traffic edge
Untuk Java/JAX-RS service, sidecar berguna jika ada kebutuhan proxy lokal yang sangat spesifik. Tetapi jangan menggunakan sidecar untuk menggantikan platform ingress tanpa alasan kuat.
21. Init Container for Config Preparation
Init container bisa dipakai untuk menyiapkan config sebelum NGINX start.
Contoh use case:
fetch template dari internal source
render config
validate generated config
copy certificate bundle
prepare static asset
Pattern:
init container writes to shared emptyDir
NGINX container mounts same emptyDir read-only
Risk:
startup dependency bertambah
failure init container membuat pod tidak start
logic konfigurasi tersembunyi dari reviewer
config generation sulit direproduksi lokal
Prinsip:
Init container boleh dipakai, tetapi config generation harus deterministic dan tervalidasi.
22. Local Testing with Docker Compose
Docker Compose berguna untuk menguji NGINX di depan Java/JAX-RS service secara lokal.
Contoh:
services:
nginx:
image: nginx:1.27-alpine
ports:
- "8080:8080"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
depends_on:
- app
app:
image: local-jaxrs-app:dev
expose:
- "8080"
NGINX config:
events {}
http {
upstream app_backend {
server app:8080;
}
server {
listen 8080;
location /api/ {
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_pass http://app_backend;
}
}
}
Compose tidak sama dengan Kubernetes, tetapi berguna untuk menguji:
proxy_pass
header forwarding
path rewrite
body size
basic timeout
local TLS
large upload/download
WebSocket/SSE behavior dasar
Jangan menganggap Compose sudah memvalidasi cloud LB, Kubernetes Service, IngressClass, NetworkPolicy, atau DNS production.
23. Docker Networking Pitfalls
Dalam Docker Compose:
service name menjadi DNS hostname
localhost dari NGINX container berarti NGINX container sendiri, bukan host dan bukan app container
Common mistake:
proxy_pass http://localhost:8080;
Jika aplikasi berada di container lain, ini salah.
Benar:
proxy_pass http://app:8080;
Dalam Kubernetes sidecar, localhost bisa benar jika NGINX dan Java container berada dalam pod yang sama.
same pod -> same network namespace -> localhost bisa menunjuk container lain di pod
separate pod -> gunakan Service DNS
Mental model:
Makna localhost bergantung pada network namespace.
24. Container Image Hardening
Checklist hardening:
[ ] Pin image version.
[ ] Gunakan registry internal jika diwajibkan.
[ ] Jalankan vulnerability scanning.
[ ] Drop unnecessary Linux capabilities.
[ ] runAsNonRoot jika memungkinkan.
[ ] readOnlyRootFilesystem jika memungkinkan.
[ ] Writable mount hanya untuk path yang dibutuhkan.
[ ] Jangan bake secret ke image.
[ ] Jangan include debug tools berlebihan di production image kecuali policy mengizinkan.
[ ] Remove default config/server yang tidak dipakai.
[ ] Expose hanya port yang diperlukan.
[ ] Log ke stdout/stderr.
Trade-off:
Image minimal lebih aman, tetapi debugging production bisa lebih sulit.
Solusi biasanya debug pod terpisah, bukan memasukkan semua tool ke image NGINX production.
25. NGINX as Ingress Controller Container
Jika NGINX dipakai sebagai Ingress Controller, kita tidak hanya menjalankan NGINX biasa.
Ada controller process yang:
watch Kubernetes API
membaca Ingress/Service/Endpoint/Secret/ConfigMap
menghasilkan konfigurasi NGINX
melakukan reload
mengekspor metrics
menjalankan admission webhook jika ada
Karena itu, debugging ingress controller harus mencakup:
controller logs
nginx logs
generated nginx.conf
Kubernetes events
IngressClass
ConfigMap
annotations
webhook validation
RBAC permission
Service/EndpointSlice state
Jangan mengedit file config manual di pod ingress controller dan menganggap itu solusi permanen. Perubahan akan hilang saat controller reconcile atau pod restart.
26. Failure Modes in Containerized NGINX
Failure: CrashLoopBackOff
Kemungkinan:
invalid nginx.conf
missing mounted file
permission denied
read-only filesystem issue
port binding permission
missing env substitution variable
secret not mounted
Debug:
kubectl logs <pod>
kubectl describe pod <pod>
kubectl exec <pod> -- nginx -t
Failure: Pod Ready but Traffic Fails
Kemungkinan:
health endpoint tidak menguji proxy path
wrong upstream DNS
Service selector salah
NetworkPolicy block
proxy_pass ke localhost yang salah
TLS secret mismatch
Failure: ConfigMap Updated but Behavior Unchanged
Kemungkinan:
NGINX belum reload
subPath mount tidak update
controller belum reconcile
GitOps belum sync
pod lama masih serving traffic
Failure: 502 During Rollout
Kemungkinan:
SIGTERM tidak graceful
readiness/draining buruk
upstream Java pod belum ready
cloud LB masih mengirim traffic ke terminating pod
Failure: Permission Denied
Kemungkinan:
runAsNonRoot tanpa file ownership benar
read-only filesystem tanpa writable temp path
secret volume permission tidak cocok
listen port privileged
27. Java/JAX-RS Backend Considerations
NGINX container di depan Java service harus menjaga beberapa hal:
Host header
X-Forwarded-For
X-Forwarded-Host
X-Forwarded-Proto
Forwarded header
request body size
timeout alignment
streaming behavior
real client IP
base path/rewrite
redirect URL correctness
Jika NGINX sidecar dan Java container dalam pod yang sama:
NGINX dapat proxy ke localhost:8080
Java service tidak perlu expose langsung ke cluster jika Service hanya target NGINX port
resource contention harus dihitung
readiness harus mempertimbangkan dua container
Readiness design:
NGINX ready tapi Java not ready -> request bisa 502/503
Java ready tapi NGINX not ready -> pod tidak menerima traffic
keduanya harus punya probe yang masuk akal
28. AWS/Azure/On-Prem Container Runtime Considerations
AWS/EKS
Verifikasi:
EKS node OS/cgroup behavior
ALB/NLB target health check
security group to pod/node
IRSA jika controller butuh AWS API
ACM/cert-manager integration
CloudWatch logs/metrics
Azure/AKS
Verifikasi:
AKS node pool resource
Azure Load Balancer/Application Gateway health probe
Managed identity jika controller butuh Azure API
Key Vault/CSI secret integration
Azure Monitor log collection
On-Prem/Hybrid
Verifikasi:
container runtime standard
private registry
internal CA bundle
corporate proxy env
NO_PROXY for cluster internal services
firewall/load balancer health check path
air-gapped image distribution
29. PR Review Checklist
Gunakan checklist ini saat mereview Dockerfile, Helm chart, Kubernetes manifest, atau config containerized NGINX.
[ ] Apakah image version dipin?
[ ] Apakah default server/config yang tidak perlu dihapus?
[ ] Apakah config masuk lewat image, ConfigMap, template, atau generated controller? Apakah jelas?
[ ] Apakah nginx -t dijalankan di CI?
[ ] Apakah container berjalan foreground dengan daemon off?
[ ] Apakah entrypoint memakai exec agar signal diteruskan?
[ ] Apakah shutdown/drain behavior jelas?
[ ] Apakah readiness/liveness probe benar?
[ ] Apakah log ke stdout/stderr?
[ ] Apakah runAsNonRoot digunakan jika memungkinkan?
[ ] Apakah readOnlyRootFilesystem digunakan jika memungkinkan?
[ ] Apakah writable temp/cache/run path tersedia?
[ ] Apakah secret tidak dibake ke image?
[ ] Apakah TLS secret rotation membutuhkan reload?
[ ] Apakah resource request/limit realistis?
[ ] Apakah ephemeral storage dipertimbangkan untuk buffering/upload/download?
[ ] Apakah Docker networking/localhost usage benar?
[ ] Apakah sidecar pattern memang dibutuhkan?
[ ] Apakah rollback jelas?
30. Internal Verification Checklist
Untuk konteks CSG/team internal, verifikasi sebelum menyimpulkan arsitektur:
[ ] Apakah NGINX dijalankan sebagai standalone container, sidecar, ingress controller, atau platform-managed component?
[ ] Image NGINX berasal dari mana?
[ ] Apakah versi NGINX dipin?
[ ] Apakah memakai NGINX open source, NGINX Plus, ingress-nginx, atau NGINX Inc controller?
[ ] Di mana config utama berada: image, ConfigMap, Helm chart, Kustomize, atau generated controller?
[ ] Bagaimana config divalidasi sebelum deploy?
[ ] Bagaimana reload dilakukan?
[ ] Apakah ada rollout restart saat ConfigMap berubah?
[ ] Apakah container non-root?
[ ] Apakah root filesystem read-only?
[ ] Path mana yang writable?
[ ] Bagaimana TLS secret dipasang?
[ ] Bagaimana certificate rotation dilakukan?
[ ] Apakah log dikirim ke stdout/stderr dan dikumpulkan observability platform?
[ ] Apakah readiness/liveness probe menguji hal yang tepat?
[ ] Apakah resource limit pernah menyebabkan throttling/OOMKilled?
[ ] Apakah ada preStop hook dan terminationGracePeriodSeconds?
[ ] Apakah ada incident sebelumnya terkait 502 saat deploy/restart?
[ ] Apakah sidecar NGINX dipakai di service tertentu?
[ ] Apakah corporate proxy/NO_PROXY memengaruhi container startup atau outbound call?
31. Production Heuristics
Beberapa aturan praktis:
Jangan gunakan nginx:latest di production.
Jangan bake secret atau private key ke image.
Jangan mengandalkan file log lokal container.
Jangan menjalankan NGINX sebagai root hanya untuk bind port 80.
Jangan memakai ConfigMap update tanpa mekanisme reload yang jelas.
Jangan menganggap liveness sama dengan readiness.
Jangan membuat health check bergantung pada upstream tanpa memahami cascading effect.
Jangan mengedit config manual di ingress controller pod.
Jangan memakai sidecar jika problem sebenarnya milik platform ingress/gateway.
Jangan mengaktifkan read-only filesystem tanpa menyediakan writable temp/cache/run path.
32. Ringkasan
NGINX di container adalah kombinasi dari:
NGINX process model
container lifecycle
filesystem mount
secret/config injection
signal handling
health check
resource limit
logging model
orchestrator rollout behavior
security context
Senior engineer perlu melihat containerized NGINX bukan hanya dari config file, tetapi dari runtime contract:
bagaimana start
bagaimana validate config
bagaimana receive traffic
bagaimana log
bagaimana reload
bagaimana shutdown
bagaimana rotate secret
bagaimana recover
bagaimana rollback
NGINX container yang production-ready bukan yang "berhasil start", tetapi yang:
aman dioperasikan
mudah diobservasi
predictable saat rollout
jelas saat failure
minimal privilege
selaras dengan Java/JAX-RS backend
selaras dengan Kubernetes/cloud/on-prem traffic flow
You just completed lesson 22 in deepen practice. Use the series map if you want to review the broader track, or continue directly into the next lesson while the context is still warm.
Keep the momentum while the lesson is still fresh. Move backward for review or continue forward into the next concept.