05 — Catatan teknik
Mengirim situs statis sebagai container
Build dua tahap dengan Node untuk situs dan Caddy untuk runtime, plus detail deployment yang membuatnya layak.
Situs statis tidak butuh container untuk bisa ada. Ia butuh container saat kamu ingin deployment berhenti bergantung pada apa yang kebetulan terpasang di host.
Pola yang saya pakai untuk situs ini adalah dua tahap: build dengan Node, sajikan dengan Caddy.
FROM node:24-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM caddy:2-alpine
COPY --from=build /app/dist /usr/share/caddy
EXPOSE 80
HEALTHCHECK --interval=30s --timeout=3s \
CMD wget -q --spider http://127.0.0.1/ || exit 1
Kenapa dua tahap
Build butuh Node, package manager, dan seluruh source tree. Runtime tidak butuh itu semua — ia butuh server HTTP dan file hasil build.
Memisahkan tahap berarti:
- Image akhir tidak punya runtime Node dan tidak punya
node_modules. - Alat build tidak pernah ikut ke server.
- Build ulang reproducible dari lockfile.
Hasilnya image kecil yang berperilaku sama di mesin saya, di VPS, dan di runner CI.
Kenapa Caddy
Caddy memberi saya file server statis dengan default yang wajar dan TLS otomatis saat diekspos langsung. Di depan reverse proxy ia tetap berguna: image kecil, konfigurasi sederhana, tanpa runtime tambahan.
Untuk situs statis satu halaman, alternatifnya memasang Nginx di image dan menulis file konfigurasi. Itu juga bekerja. Caddy hanya butuh konfigurasi lebih sedikit untuk pekerjaan yang sama, dan saya sudah memakainya sebagai lapisan proxy.
Menjalankannya
podman build -t portfolio .
podman run -d --name portfolio \
-p 8080:80 \
--restart unless-stopped \
portfolio
Dua detail lebih penting daripada perintahnya:
- Kunci pemetaan port di lapisan proxy. Container menyajikan HTTP di port 80; TLS dan hostname milik apa pun yang ada di depannya.
- Pasang restart policy. Container yang tidak hidup lagi setelah host reboot belum ter-deploy.
Healthcheck layak untuk satu baris tambahan. Ia mengubah “prosesnya berjalan” menjadi “situsnya menjawab”, dan itu pertanyaan yang sebenarnya kamu pedulikan.
Yang tidak diselesaikan ini
Meng-container-kan situs statis tidak memberi deployment tanpa downtime, rollback, atau monitoring. Itu keputusan terpisah:
- Rollback butuh image sebelumnya masih ada.
- Tanpa downtime butuh dua instance di belakang proxy, atau jendela restart singkat yang diterima.
- Monitoring butuh sesuatu di luar container untuk memeriksanya.
Container membuat artefaknya konsisten. Sisanya tetap operasi.