Available for Hire
ZB

Memuat...

Kembali ke Blog
Tutorial 6 menit baca ยท 1246 kata

Docker untuk Pemula: Dari Nol hingga Mahir

Tutorial Docker dari instalasi, konsep image dan container, menulis Dockerfile yang efisien, sampai menjalankan aplikasi multi-service dengan Docker Compose.

#docker #containerization #devops #tutorial

Docker adalah platform containerization yang menjalankan aplikasi beserta seluruh dependensinya dalam environment terisolasi. Bedanya dengan virtual machine, container tidak membawa sistem operasi sendiri. Container berbagi kernel dengan mesin host dan hanya mengemas apa yang dibutuhkan aplikasi. Itulah sebabnya container bisa menyala dalam hitungan detik, sementara VM butuh puluhan detik sampai menit.

Mengapa Docker?

Konsistensi. Kalimat โ€œdi laptop saya jalan kokโ€ muncul karena versi Node, versi library sistem, atau variabel environment di mesin developer berbeda dengan server. Container mengunci semua itu ke dalam image, sehingga yang jalan di laptop sama persis dengan yang jalan di production.

Portabilitas. Image yang sama bisa dijalankan di laptop, server on-premise, atau layanan cloud mana pun yang mendukung container.

Efisiensi. Karena tidak ada OS tamu, satu server bisa menampung jauh lebih banyak container dibanding VM dengan spesifikasi sama.

Isolasi. Dua aplikasi yang butuh versi PHP berbeda bisa hidup berdampingan tanpa saling ganggu.

Docker bukan solusi untuk semua hal. Untuk aplikasi kecil yang hanya butuh satu proses di satu server, Docker justru menambah lapisan kerumitan yang belum tentu terbayar.

Instalasi

Di Ubuntu atau Debian, paket docker.io dari repositori distro biasanya tertinggal beberapa versi. Untuk versi terbaru, pakai repositori resmi Docker. Kalau sekadar ingin cepat mencoba:

sudo apt update
sudo apt install docker.io
sudo systemctl enable --now docker

# Supaya tidak perlu sudo setiap kali
sudo usermod -aG docker $USER

Setelah menambahkan diri ke grup docker, keluar dan masuk lagi agar keanggotaan grup terbaca. Perlu dicatat, anggota grup docker praktis punya akses setara root di mesin itu, karena bisa me-mount direktori mana pun ke dalam container. Jangan tambahkan user yang tidak Anda percaya.

Verifikasi instalasi:

docker run --rm hello-world

Flag --rm menghapus container begitu selesai, supaya tidak menumpuk.

Konsep Dasar

Image adalah template read-only berisi filesystem aplikasi Anda. Image tersusun dari lapisan atau layer yang ditumpuk. Setiap instruksi di Dockerfile menghasilkan satu layer.

Container adalah instance dari image yang sedang berjalan. Di atas layer image yang read-only, Docker menambahkan satu layer tulis. Saat container dihapus, layer tulis itu ikut hilang. Inilah alasan data di dalam container tidak permanen.

Volume adalah mekanisme menyimpan data di luar container supaya tetap ada setelah container dihapus atau diganti.

Network menghubungkan antar container. Container dalam satu network bisa saling memanggil lewat nama service, tanpa perlu tahu alamat IP-nya.

Dockerfile adalah resep untuk membangun image.

Docker Compose menjalankan beberapa container sekaligus dari satu file konfigurasi.

Command yang Sering Dipakai

docker pull nginx:1.27          # Unduh image, sebut tag-nya
docker run -d -p 8080:80 nginx  # Jalankan, petakan port host:container
docker ps                       # Container yang sedang berjalan
docker ps -a                    # Termasuk yang sudah berhenti
docker logs -f <id>             # Ikuti log secara live
docker exec -it <id> sh         # Masuk ke shell di dalam container
docker stop <id>                # Hentikan dengan sopan
docker rm <id>                  # Hapus container
docker images                   # Daftar image lokal
docker system df                # Lihat pemakaian disk
docker system prune             # Bersihkan yang tidak terpakai

Dua kebiasaan yang menghemat banyak waktu. Pertama, selalu sebut tag versi. Menulis nginx saja diam-diam berarti nginx:latest, dan isi latest berubah seiring waktu, sehingga build yang tadinya berhasil bisa tiba-tiba gagal. Kedua, jalankan docker system prune secara berkala. Image dan build cache yang menumpuk gampang memakan puluhan gigabyte tanpa disadari.

Versi paling sederhana untuk aplikasi Node:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["npm", "start"]

Urutan di sini bukan kebetulan. Docker menyimpan cache per layer, dan sebuah layer dibangun ulang hanya jika layer itu atau layer di atasnya berubah. Karena package*.json disalin lebih dulu, npm ci tidak akan diulang selama daftar dependensi tidak berubah. Kalau Anda menulis COPY . . lebih dulu, setiap perubahan satu baris kode akan memicu install ulang seluruh dependensi.

Gunakan npm ci, bukan npm install, di dalam image. Perintah itu membaca package-lock.json secara ketat sehingga hasilnya konsisten.

Buat file .dockerignore supaya node_modules lokal, folder .git, dan file .env tidak ikut tersalin:

node_modules
.git
.env
dist
*.log

Tanpa .dockerignore, build context bisa membengkak jadi ratusan megabyte, dan node_modules dari host bisa menimpa hasil install di dalam image.

Multi-stage build

Untuk aplikasi yang butuh proses build, pisahkan tahap membangun dari tahap menjalankan. Image akhirnya hanya berisi hasil build, tanpa toolchain:

# Tahap build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

# Tahap jalan
FROM nginx:1.27-alpine
COPY --from=builder /app/dist /usr/share/nginx/html
EXPOSE 80

Selisihnya besar. Image yang membawa seluruh node_modules beserta toolchain bisa ratusan megabyte, sementara hasil akhir seperti di atas sering kali di bawah lima puluh megabyte.

Jangan jalan sebagai root

Secara bawaan proses di dalam container berjalan sebagai root. Kalau ada celah di aplikasi, penyerang langsung mendapat root di dalam container, dan itu titik awal yang bagus untuk mencoba keluar. Turunkan hak aksesnya:

FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
USER node
EXPOSE 3000
CMD ["node", "server.js"]

Image resmi Node sudah menyediakan user bernama node, jadi Anda tidak perlu membuatnya sendiri.

Menyimpan Data dengan Volume

Data di dalam container hilang saat container dihapus. Untuk database, itu jelas tidak bisa diterima:

docker run -d \
  --name db \
  -e POSTGRES_PASSWORD=rahasia \
  -v pgdata:/var/lib/postgresql/data \
  postgres:16

pgdata adalah named volume yang dikelola Docker. Isinya bertahan meski container db dihapus dan dibuat ulang.

Ada juga bind mount yang memetakan folder di host ke dalam container, berguna saat development supaya perubahan kode langsung terlihat:

docker run -d -v $(pwd):/app -p 3000:3000 my-app

Bind mount praktis untuk development, tapi hindari di production karena mengikat container ke struktur folder mesin host.

Docker Compose untuk Banyak Service

Aplikasi nyata jarang berdiri sendiri. Biasanya ada aplikasi, database, dan mungkin cache. Compose merangkum semuanya:

services:
  app:
    build: .
    ports:
      - "3000:3000"
    environment:
      DATABASE_URL: postgres://postgres:rahasia@db:5432/app
    depends_on:
      db:
        condition: service_healthy

  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: rahasia
      POSTGRES_DB: app
    volumes:
      - pgdata:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  pgdata:

Perhatikan DATABASE_URL memakai host db, bukan localhost. Di dalam network Compose, nama service otomatis menjadi nama host.

Perhatikan juga depends_on dipasangkan dengan condition: service_healthy. Tanpa healthcheck, depends_on hanya menunggu container database menyala, bukan menunggu Postgres siap menerima koneksi. Akibatnya aplikasi sering gagal di detik-detik pertama karena mencoba konek ke database yang belum siap.

Menjalankannya:

docker compose up -d       # Nyalakan semua di background
docker compose logs -f app # Ikuti log satu service
docker compose down        # Matikan dan hapus container
docker compose down -v     # Sekalian hapus volume, hati-hati

Kesalahan yang Sering Terjadi

Menaruh secret di dalam image. Apa pun yang disalin ke image tersimpan di layer dan bisa dibaca siapa pun yang punya image itu, bahkan kalau file-nya dihapus di layer berikutnya. Kirim secret lewat environment variable saat runtime atau lewat secret manager.

Menyimpan data penting tanpa volume. Satu kali docker compose down -v dan database Anda kosong.

Tidak membatasi resource. Satu container yang bocor memorinya bisa menjatuhkan seluruh server. Batasi dengan --memory dan --cpus.

Mengandalkan tag latest. Build yang tidak deterministik adalah sumber masalah yang sulit dilacak.

Langkah Selanjutnya

Setelah nyaman dengan Docker, arah berikutnya biasanya orkestrasi: menjalankan container di banyak mesin, lengkap dengan penyembuhan otomatis dan penskalaan. Kubernetes adalah pilihan paling umum, meski untuk kebutuhan yang lebih sederhana Docker Swarm atau layanan container terkelola dari penyedia cloud sering kali sudah cukup dan jauh lebih ringan untuk dirawat.

Bagikan artikel ini:

Suka artikel ini?

0 reactions