Belajar WebSocket - Docker & Containerization
Episode 27 of 34

Belajar WebSocket - Docker & Containerization

Episode ini membungkus server WebSocket dalam container: Dockerfile dengan multi-stage build, praktik terbaik Node.js, docker networking dan port mapping, Docker Compose dengan Redis, serta health check container.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Pendahuluan

Server WebSocket yang berjalan langsung di mesin adalah bom waktu: konfigurasi bergantung pada mesin, versi Node.js berbeda antar lingkungan, dan dependency bisa saja rusak. Containerisasi mengunci seluruh lingkungan menjadi satu image yang berjalan di mana saja.

Episode 27 membahas Docker & containerization: menulis Dockerfile untuk server WebSocket, memanfaatkan multi-stage build, memahami docker networking, merangkai Redis dan server dengan Docker Compose, serta memasang health check.

Dockerfile Dasar

Image Node.js

Mulai dengan image Node.js resmi dan struktur yang tepat.

Dockerfile server WebSocket
FROM node:22-alpine AS builder
WORKDIR /app
COPY package.json bun.lock ./
RUN npm install --omit=dev
COPY server.js ./
 
FROM node:22-alpine
WORKDIR /app
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/server.js ./server.js
EXPOSE 8080
USER node
CMD ["node", "server.js"]

node:22-alpine menghasilkan image kecil dan ringan. USER node menjalankan aplikasi sebagai pengguna non-root — praktik keamanan penting. Lapisan pertama memuat dependency, lapisan kedua hanya menyalin yang dibutuhkan.

Multi-Stage Build

FROM ... AS builder lalu COPY --from=builder membentuk multi-stage build: stage pertama menginstal dependency, stage kedua menghasilkan image final yang ramping. Image production tidak membawa tool build yang tidak perlu.

Docker Networking

Port Mapping

Container memiliki namespace jaringan sendiri. Ekspos port ke host dengan mapping.

Jalankan container dengan port
docker run -d --name ws-server -p 8080:8080 ws-server:latest

-p 8080:8080 memetakan port 8080 host ke port 8080 container. Tanpa mapping, port di dalam container tidak bisa diakses dari luar.

Network Isolation

Gunakan network khusus agar container berkomunikasi aman tanpa membuka port ke publik.

Buat network khusus
docker network create ws-net

Dengan docker network create ws-net dan menghubungkan container ke network itu, server bisa mengakses Redis lewat nama service tanpa memetakan port Redis ke host — hanya port WebSocket yang terbuka ke luar.

Docker Compose

Multi-Container Setup

Docker Compose merangkai semua service dalam satu file.

Docker Compose WebSocket + Redis
services:
  ws-server:
    build: .
    ports:
      - "8080:8080"
    environment:
      REDIS_URL: redis://redis:6379
    depends_on:
      redis:
        condition: service_healthy
    healthcheck:
      test: ["CMD", "node", "-e", "fetch('http://localhost:8080/healthz').then(r => process.exit(r.ok ? 0 : 1))"]
      interval: 10s
      timeout: 5s
      retries: 3
 
  redis:
    image: redis:7-alpine
    healthcheck:
      test: ["CMD", "redis-cli", "ping"]
      interval: 5s
      timeout: 3s

depends_on dengan condition: service_healthy memastikan server menunggu Redis sehat sebelum mulai. Variabel REDIS_URL: redis://redis:6379 memakai nama service, bukan IP — DNS internal Compose menanganinya.

Menjalankan Stack

Jalankan seluruh stack
docker compose up -d

docker compose up -d membangun image, membuat network, dan menjalankan semua service. Satu perintah membawa lingkungan production lengkap ke mesin lokal.

Health Check

Kenapa Health Check Penting

Health check membedakan "container hidup" dari "aplikasi berfungsi". Endpoint /healthz dari episode 15 menjadi dasar ini.

JSHealth check di aplikasi
http.createServer((req, res) => {
  if (req.url === "/healthz") {
    const sehat = wss.clients.size < 5000;
    res.writeHead(sehat ? 200 : 503);
    res.end(sehat ? "ok" : "penuh");
    return;
  }
  res.writeHead(404);
  res.end();
}).listen(8080);

wss.clients.size < 5000 membuat health check mencerminkan kapasitas nyata: server merespons 503 saat hampir penuh, sehingga orchestrator tahu kapan harus menambah instance.

Readiness vs Liveness

Dalam Kubernetes (episode 28), kedua probe ini berbeda: liveness memeriksa apakah aplikasi masih hidup (restart jika gagal), readiness memeriksa apakah siap menerima traffic (hentikan traffic jika gagal). Di Compose, healthcheck tunggal cukup untuk sebagian besar kasus.

Praktik Terbaik

  • Jangan jalankan container sebagai root.
  • Instal dependency production saja; build tool cukup di stage build.
  • Simpan konfigurasi di environment variable, bukan di image.
  • Batasi resource dengan mem_limit dan cpu_limit.
  • Log ke stdout agar Docker dan orchestrator bisa mengambilnya.

Penutup

Episode 27 mengubah server WebSocket yang rapuh menjadi image yang portabel: dependency terkunci, lingkungan terisolasi, dan stack lengkap (server plus Redis) berjalan dengan satu perintah.

Inti yang harus dibawa pulang:

  • Multi-stage build menghasilkan image yang ramping dan aman.
  • Jalankan container sebagai pengguna non-root.
  • Port mapping dan network khusus mengontrol apa yang terbuka ke luar.
  • Docker Compose merangkai server WebSocket dan Redis.
  • Health check memastikan aplikasi benar-benar sehat, bukan hanya hidup.
  • Simpan konfigurasi di environment variable, bukan di image.

Di episode 28 berikutnya kita membawa stack ke orkestrasi: Kubernetes deployment — Deployment, Service, Ingress dengan session affinity, HPA, serta service mesh.

Belajar WebSocket - Docker & Containerization | Belajar WebSocket