Belajar Microservices - Container Networking & Compose
Episode 16 of 28

Belajar Microservices - Container Networking & Compose

Merapikan infrastruktur lokal tokokita: memahami Docker network dan DNS antar service, menulis compose yang benar dengan depends_on, healthcheck, dan named volumes, serta mengamankan image container dengan multi-stage build dan non-root user

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Sampai episode ini kita menjalankan service lewat bun dev di host dan dependency infra di Docker Compose. Sekarang mari memindahkan seluruh layanan ke container — seperti itulah mereka akan hidup di Kubernetes nanti. Ini episode jembatan: networking dan compose yang benar di sini menjadi fondasi manifest K8s di episode 17.

Mengapa episode ini penting? Karena kebanyakan masalah "works on my machine" di microservices lahir dari networking dan env yang tidak terkendali. Container yang saling salah DNS, env yang hardcode, image yang membengkak — semua bisa dicegah dengan disiplin yang kita susun sekarang.

Docker Network

Docker menyediakan bridge network per Compose project secara otomatis. Di dalam network itu, tiap container bisa diakses lewat nama service sebagai DNS:

DNS dalam satu bridge network
auth-service:3001      → 127.0.0.1:5432? Tidak — `postgres:5432`
order-service → call → product-service:3002 (bukan localhost:3002)

Aturan penting: jangan expose port internal ke host kecuali yang harus dijangkau luar (api-gateway, database untuk psql lokal, Mailpit UI). Port 5432 PostgreSQL tetap di-publish agar psql lokal nyaman, tetapi port service internal seperti 3002 cukup di dalam network.

Prinsip port
Dalam network:  semua layanan saling bicara via nama service.
Ke host:        hanya api-gateway (3000), PG (5432:psql), Mailpit (8025).

Compose yang Benar untuk Banyak Service

depends_on + Healthcheck

depends_on saja hanya menunggu container start, bukan ready. Pasangkan dengan healthcheck agar order yang benar benar-benar berarti:

infra/compose.yaml (contoh dua layanan)
services:
  postgres:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: tokokita
      POSTGRES_PASSWORD: tokokita
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U tokokita"]
      interval: 5s
      timeout: 3s
      retries: 10
 
  auth-service:
    build:
      context: ../services/auth-service
    environment:
      DATABASE_URL: postgres://tokokita:tokokita@postgres:5432/tokokita
      REDIS_URL: redis://redis:6379
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    ports:
      - "3001:3001"

Dengan condition: service_healthy, auth-service baru dimulai setelah PostgreSQL benar-benar siap menerima koneksi.

Named Volumes dan Versi Pin

  • Semua data persisten (PG data, MinIO files) lewat named volume agar tidak ikut terhapus saat docker compose down.
  • Pin versi image (postgres:16-alpine, redis:7-alpine, redpandadata/redpanda:v24.x) — jangan latest yang bisa bergeser diam-diam dan merusak reproduksibilitas.

Env via .env, Bukan Hardcode

Semua nilai rahasia (password, secret) lewat variabel env; .env dipakai Compose untuk interpolasi; nilai dev default boleh di .env, jangan di commit (gunakan .env.example sebagai template). Secret sungguhan di produksi lewat secrets management (episode 19 dan 23).

Keamanan Image Container

Multi-Stage Build

Image production sebaiknya hanya berisi runtime — bukan toolchain build. Penghematannya nyata:

services/auth-service/Dockerfile
FROM oven/bun:1 AS deps
WORKDIR /app
COPY package.json bun.lockb ./
RUN bun install --frozen-lockfile
 
FROM oven/bun:1 AS build
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN bun build src/index.ts --target=bun --outfile=dist/index.js
 
FROM oven/bun:1 AS runtime
WORKDIR /app
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
USER bun
EXPOSE 3001
CMD ["bun", "run", "dist/index.js"]

Tiga tahap: deps (install), build (bundling TypeScript), runtime (hanya hasil build + node_modules). Runtime pun tidak menyimpan source code — hanya artefak.

Non-Root User

Konvensi keamanan dasar: jangan jalankan container sebagai root. Itulah USER bun di Dockerfile — image oven/bun menyediakan user bun yang non-root.

.dockerignore

Jangan salin .git, node_modules, .next, atau .env* ke konteks build — selain mempercepat build, ini mencegah secret ikut ke image:

services/auth-service/.dockerignore
node_modules
dist
.env*
.git
Dockerfile

Warning

Bahaya latest: image yang sama mungkin berisi bug fix (bagus) atau breaking change (buruk) tanpa terduga. Satu aturan yang tak bisa ditawar: pinned version di compose dan manifest. Untuk image produksi tokokita selanjutnya selalu pakai tag semver (misal ghcr.io/tokokita/auth-service:v1.4.2), bukan latest — akan dikonsistenkan di episode 23 saat CI/CD.

Verifikasi Jaringan Lokal

Setelah compose lengkap:

Cek network dan koneksi antar service
docker compose up --build -d
docker compose ps
docker network ls
# dari dalam container auth-service, cek DNS product-service
docker compose exec auth-service ping -c 1 postgres

Tip

Kalau sebuah layanan "tidak bisa connect ke database", cek urutan: DNS salah? (pakai nama service, bukan localhost) — port salah? — healthcheck belum selesai? — secret/env salah? Sembilan dari sepuluh kasus di compose adalah salah satu dari empat ini. Gunakan docker compose logs <service> dan docker compose exec <service> env untuk diagnosa cepat.

Penutup

Episode 16 merapikan infrastruktur container:

  • Bridge network + DNS: service saling bicara via nama service; hanya gateway & tooling yang di-expose ke host.
  • depends_on + healthcheck: menunggu container ready, bukan sekadar start.
  • Named volumes + pinned image versions + env via .env (jangan di-commit).
  • Image aman: multi-stage build, non-root user (USER bun), .dockerignore.

Di episode 17 selanjutnya, kita deploy tokokita ke Kubernetes — manifest Deployment, Service, HPA, PVC untuk PostgreSQL, ConfigMap & Secret, probes, ingress yang hanya mengekspos gateway, serta strategi rolling update yang aman. Sampai jumpa di episode 17!

Belajar Microservices - Container Networking & Compose | Belajar Microservices