Docker dan Kubernetes untuk Pemula: Dari Satu Container sampai Cluster
Kenapa aplikasi bisa jalan mulus di laptop tapi error di server, dan gimana Docker sama Kubernetes bantu beresin masalah itu. Lengkap dengan contoh Dockerfile, Compose, dan YAML Kubernetes yang bisa langsung kamu coba.

Kalimat "di laptop saya jalan kok" mungkin salah satu kalimat paling sering muncul di tugas kelompok anak Informatika. Aplikasinya sama, kodenya sama, tapi begitu dipindah ke laptop teman atau ke server, tiba-tiba error. Biasanya penyebabnya sepele, misalnya versi Python yang beda atau library yang belum ke-install.
Docker lahir buat masalah ini. Kubernetes muncul belakangan, waktu orang mulai menjalankan ratusan container sekaligus dan butuh sesuatu yang bisa ngatur semuanya. Di tulisan ini kita bahas keduanya pelan-pelan, dari konsep sampai perintah yang bisa langsung kamu coba.
Sumber masalahnya: lingkungan yang beda
Coba bayangin kamu bikin aplikasi Python di laptop. Di laptop kamu terpasang Python 3.12 dan numpy versi terbaru. Server kampus ternyata masih pakai Python 3.9 dengan numpy versi lama. Kode yang sama bisa berperilaku beda, atau malah gagal jalan sama sekali.
![]()
Ide container sederhana: aplikasi dibungkus bareng runtime dan library yang dia butuhkan. Bungkusan itu yang dikirim ke mana-mana. Jadi yang jalan di server adalah bungkusan yang persis sama dengan yang kamu tes di laptop.
Container itu beda sama virtual machine
Banyak yang awalnya ngira container itu VM versi kecil. Mirip, tapi cara kerjanya beda jauh.
Virtual machine meniru satu komputer utuh. Tiap VM punya sistem operasi sendiri di dalamnya, jadi kalau kamu jalanin tiga VM, ada tiga OS tamu yang makan RAM dan butuh waktu buat booting.
Container nggak bawa OS sendiri. Semua container di satu mesin berbagi kernel milik OS host, dan yang dibungkus cuma aplikasi plus library-nya. Hasilnya container jauh lebih ringan dan bisa nyala dalam hitungan detik, jadi satu server sanggup menampung banyak container sekaligus.
![]()
Konsekuensinya, container Linux butuh kernel Linux. Docker Desktop di Windows dan macOS sebenarnya diam-diam menjalankan VM Linux kecil di belakang layar supaya container Linux tetap bisa jalan.
Tiga istilah yang wajib nempel: Dockerfile, image, container
Ini bagian yang paling sering ketuker, jadi kita beresin dulu.
Dockerfile adalah resep. Isinya langkah-langkah buat menyiapkan lingkungan aplikasi kamu: pakai base image apa, file mana yang disalin, perintah apa yang dijalankan.
Image adalah hasil masakan dari resep itu. Image tersusun dari beberapa layer read-only, dan langkah seperti RUN atau COPY di Dockerfile masing-masing menghasilkan layer baru. Karena berlapis, Docker bisa pakai ulang layer yang nggak berubah, jadi build kedua dan seterusnya jauh lebih cepat.
Container adalah image yang lagi dijalankan. Dari satu image kamu bisa nyalain banyak container. Masing-masing dapat lapisan tipis yang bisa ditulisi, jadi perubahan di satu container nggak ngaruh ke container lain.
![]()
Image yang sudah jadi bisa di-push ke registry, misalnya Docker Hub atau GitHub Container Registry. Server tinggal pull image itu lalu menjalankannya. Nggak perlu install apa-apa lagi selain Docker.
Bikin Dockerfile pertama
Misalnya kita punya aplikasi Node.js kecil yang perlu di-build dulu sebelum dijalankan. Dockerfile yang rapi biasanya pakai multi-stage build: satu tahap buat build, satu tahap lagi buat image akhir yang ramping.
# Tahap 1: build
FROM node:22-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Tahap 2: image akhir
FROM node:22-slim
WORKDIR /app
ENV NODE_ENV=production
COPY package*.json ./
RUN npm ci --omit=dev
COPY --from=build /app/dist ./dist
USER node
EXPOSE 3000
CMD ["node", "dist/server.js"]Ada beberapa hal yang sengaja diatur di situ. package*.json disalin duluan sebelum kode lain, supaya layer npm ci tetap di-cache selama dependency nggak berubah. Tahap kedua cuma ambil folder dist dari tahap build, jadi tool build dan devDependencies nggak ikut masuk ke image akhir. USER node bikin aplikasi jalan sebagai user biasa, bukan root.
Jangan lupa bikin .dockerignore biar file yang nggak perlu nggak ikut terkirim waktu build:
node_modules
dist
.git
.envBaris .env itu penting. Kalau kelupaan, file rahasia kamu bisa ikut ke dalam image dan kebawa ke registry.
Sekarang build dan jalankan:
docker build -t catatan-app:1.0 .
docker run -d -p 8080:3000 --name catatan catatan-app:1.0Opsi -p 8080:3000 artinya port 8080 di komputer kamu diteruskan ke port 3000 di dalam container. Buka http://localhost:8080 dan aplikasinya muncul. Beberapa perintah yang bakal sering kamu pakai:
docker ps # lihat container yang jalan
docker logs -f catatan # ikuti log aplikasi
docker stop catatan # hentikan container
docker rm catatan # hapus containerData jangan disimpan di dalam container
Container itu gampang dibuang dan dibikin ulang. Masalahnya, kalau database kamu nyimpan data di dalam container, datanya ikut hilang waktu container dihapus.
Solusinya pakai volume. Volume dikelola Docker dan tetap ada walaupun container-nya dihapus:
docker volume create data-db
docker run -d -v data-db:/var/lib/postgresql/data \
-e POSTGRES_PASSWORD=ganti-ini postgres:17Ada juga bind mount, yaitu folder di komputer kamu yang ditempel langsung ke dalam container, misalnya -v "$(pwd)":/app. Bind mount enak buat development karena perubahan kode langsung kelihatan di container. Buat data aplikasi di server, volume biasanya pilihan yang lebih aman.
Docker Compose buat lebih dari satu container
Aplikasi beneran jarang cuma satu container. Paling nggak ada aplikasi web dan database. Ngetik docker run panjang untuk masing-masing jelas capek, jadi kita pakai Docker Compose.
Bikin file compose.yaml:
services:
web:
build: .
ports:
- "8080:3000"
environment:
DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/catatan
depends_on:
- db
db:
image: postgres:17
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: ${DB_PASSWORD}
POSTGRES_DB: catatan
volumes:
- data-db:/var/lib/postgresql/data
volumes:
data-db:Nilai ${DB_PASSWORD} diambil dari file .env di folder yang sama, jadi password nggak perlu ditulis langsung di file Compose. Perhatikan juga alamat database-nya cukup db. Compose bikin jaringan internal, dan tiap service bisa saling panggil pakai nama service-nya.
Perintahnya sekarang docker compose dengan spasi. Versi lama docker-compose pakai tanda hubung sudah nggak dikembangkan lagi.
docker compose up -d --build # build lalu jalankan semua service
docker compose logs -f web # lihat log service web
docker compose down # matikan semuanya (volume tetap aman)Website yang lagi kamu baca ini juga jalan dengan cara mirip. Frontend dan backend-nya dibungkus jadi image dan dijalankan pakai Docker Compose di satu VPS kecil. Sebelumnya tiap bagian jalan sebagai service biasa langsung di server. Setelah pindah ke container, cara update-nya jadi seragam: build image baru, ganti container lama, dan kalau ada yang salah, balik ke image sebelumnya.
Lalu Kubernetes buat apa?
Compose sangat cukup selama semuanya muat di satu mesin. Ceritanya beda kalau aplikasi kamu harus jalan di banyak server sekaligus. Misalnya ada yang perlu mengatur container mana jalan di server mana, menyalakan ulang container yang mati, menambah jumlah container waktu traffic naik, dan mengganti versi aplikasi tanpa bikin website down.
Kubernetes (sering disingkat K8s) adalah sistem yang ngerjain semua itu. Kamu cukup bilang kondisi yang kamu mau, misalnya "aplikasi web harus selalu ada 3 salinan", dan Kubernetes terus-menerus mencocokkan kondisi cluster dengan keinginan kamu.
![]()
Satu cluster Kubernetes terdiri dari dua bagian besar. Control plane adalah otaknya: API server menerima semua perintah, scheduler memilih node untuk tiap Pod, controller manager menjaga supaya kondisi cluster sesuai keinginan, dan etcd menyimpan seluruh state cluster. Node adalah mesin pekerja. Di tiap node ada kubelet yang menerima tugas dari control plane, plus container runtime yang benar-benar menjalankan container.
Beberapa objek yang bakal sering kamu temui:
- Pod adalah unit terkecil di Kubernetes. Isinya satu container atau lebih yang selalu jalan bareng di node yang sama.
- Deployment berisi deskripsi aplikasi kamu, termasuk image yang dipakai dan jumlah replika. Deployment bikin ReplicaSet, dan ReplicaSet yang menjaga jumlah Pod tetap sesuai.
- Service memberi alamat tetap untuk sekumpulan Pod. Pod bisa mati dan diganti dengan alamat IP baru, tapi Service tetap di alamat yang sama dan membagi traffic ke Pod yang sehat.
Contoh YAML yang bisa langsung dicoba
Simpan sebagai web.yaml. Image-nya pakai image yang tadi sudah kamu push ke registry:
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
spec:
replicas: 3
selector:
matchLabels:
app: web
template:
metadata:
labels:
app: web
spec:
containers:
- name: web
image: ghcr.io/username/catatan-app:1.0
ports:
- containerPort: 3000
---
apiVersion: v1
kind: Service
metadata:
name: web
spec:
selector:
app: web
ports:
- port: 80
targetPort: 3000Bagian yang paling sering bikin error adalah label. selector.matchLabels di Deployment harus cocok dengan labels di template Pod, dan selector di Service juga harus nunjuk label yang sama. Kalau beda satu huruf aja, Deployment ditolak atau Service nggak nemu Pod mana pun.
Terapkan dan cek hasilnya:
kubectl apply -f web.yaml
kubectl get pods
kubectl get deployment,service
kubectl port-forward service/web 8080:80Coba hapus salah satu Pod pakai kubectl delete pod <nama-pod>, lalu jalankan kubectl get pods lagi. Dalam beberapa detik muncul Pod pengganti, karena ReplicaSet melihat jumlahnya kurang dari tiga.
Menambah replika dan update versi juga cuma satu perintah:
kubectl scale deployment web --replicas=5
kubectl set image deployment/web web=ghcr.io/username/catatan-app:1.1
kubectl rollout status deployment/web
kubectl rollout undo deployment/web # kalau versi baru bermasalahWaktu update, Kubernetes mengganti Pod sedikit demi sedikit (rolling update), jadi selalu ada Pod yang melayani request.
"Kubernetes udah nggak pakai Docker", maksudnya?
Kamu mungkin pernah baca berita ini. Sejak versi 1.24, Kubernetes menghapus dockershim, yaitu komponen penghubung yang dulu dipakai Kubernetes untuk ngobrol dengan Docker Engine. Sekarang Kubernetes bicara ke container runtime lewat CRI (Container Runtime Interface), biasanya containerd atau CRI-O.
Buat kamu sebagai developer, dampaknya hampir nggak ada. Image yang kamu build pakai Docker mengikuti standar OCI, jadi tetap bisa dijalankan containerd di dalam Kubernetes. Kamu tetap bisa build pakai Docker di laptop dan menjalankannya di cluster.
Kapan pakai yang mana
Docker saja cocok buat belajar, menjalankan satu aplikasi, atau mencoba tool tanpa harus meng-install-nya langsung di laptop. Mau coba PostgreSQL versi tertentu? Satu docker run dan selesai.
Docker Compose cocok kalau aplikasi kamu terdiri dari beberapa service dan semuanya jalan di satu mesin. Ini mencakup kebanyakan tugas kuliah, proyek tugas akhir, dan website kecil sampai menengah. Website ini contohnya: satu VPS, beberapa container, dan Kubernetes jelas berlebihan untuk skala segini.
Kubernetes masuk akal kalau aplikasi harus jalan di beberapa server dan tetap hidup walaupun salah satu server bermasalah, atau kalau kapasitasnya perlu naik-turun otomatis mengikuti traffic. Ada harganya juga: konsep yang harus dipahami jauh lebih banyak, dan cluster-nya sendiri perlu dirawat.
Langkah selanjutnya
- Install Docker Desktop (Windows/macOS) atau Docker Engine (Linux), lalu jalankan
docker run hello-world. - Bungkus satu proyek kuliah kamu jadi image, lengkap dengan Dockerfile dan
.dockerignore. - Tambahkan database pakai Docker Compose dan pastikan datanya tetap ada setelah
docker compose down. - Coba Kubernetes di laptop pakai kind, minikube, atau k3s. Kalau pakai kind dan image-nya cuma ada di laptop, masukkan dulu ke cluster dengan
kind load docker-image catatan-app:1.0lalu pakai nama image yang sama di YAML. - Baca dokumentasi resminya di docs.docker.com dan tutorial dasar di kubernetes.io.
Komentar (0)
Login dengan Google untuk berkomentarBelum ada komentar. Jadilah yang pertama!