Dari Image Publik ke Image Kustom
Di Seri 1, kita telah memahami bahwa Image Docker adalah template read-only yang menjadi dasar dari setiap kontainer. Langkah berikutnya dalam perjalanan kontainerisasi Anda adalah beralih dari sekadar menarik image publik (seperti Nginx atau Postgres) menjadi menciptakan image kustom yang berisi kode aplikasi spesifik Anda.
Proses ini didikte oleh satu file teks sederhana bernama Dockerfile. Dockerfile adalah resep yang berisi serangkaian instruksi yang Docker Engine akan eksekusi secara berurutan untuk membangun image baru Anda.
Selain membangun image kustom, aplikasi modern hampir selalu terdiri dari beberapa layanan (misalnya, web server, database, cache). Mengelola semua kontainer ini secara manual sangatlah merepotkan. Untuk itu, kita akan memperkenalkan Docker Compose, tool yang memungkinkan definisi dan orkestrasi aplikasi multi-kontainer menggunakan satu file YAML yang sederhana.
Artikel ini akan menjadi panduan mendalam Anda untuk:
Menulis Dockerfile yang aman dan optimal.
Mengoptimalkan proses build menggunakan teknik Multi-stage builds.
Mengelola aplikasi kompleks dengan Docker Compose.
Memastikan data penting (data database, konfigurasi) tetap persisten melalui Volumes.
📝 Dockerfile: Struktur dan Perintah Kunci
Dockerfile terdiri dari serangkaian instruksi yang dieksekusi secara berurutan. Setiap instruksi dalam Dockerfile menghasilkan lapisan (layer) baru dalam image Docker.
1. Perintah Wajib dan Sering Digunakan
| Perintah | Tujuan | Contoh Penggunaan |
FROM | Mendefinisikan Base Image (lapisan awal). | FROM node:20-alpine |
WORKDIR | Mengatur direktori kerja default untuk perintah berikutnya. | WORKDIR /app |
COPY | Menyalin file dan folder dari Host ke Image. | COPY . . (Menyalin semua dari Host ke /app) |
RUN | Mengeksekusi perintah selama proses build (untuk instalasi dependency). | RUN npm install |
EXPOSE | Menginformasikan port mana yang digunakan kontainer saat runtime. | EXPOSE 3000 |
CMD | Perintah default yang akan dieksekusi saat kontainer dijalankan. | CMD ["node", "server.js"] |
ENTRYPOINT | Mengatur perintah utama kontainer (sering digunakan bersama CMD). | ENTRYPOINT ["/usr/sbin/nginx"] |
2. Membangun Image (docker build)
Setelah Dockerfile ditulis, Anda dapat membangun image menggunakan perintah docker build.
# Sintaks Dasar:
docker build -t [nama_image]:[tag] [path_ke_Dockerfile]
# Contoh: Membangun dari direktori saat ini (.) dan memberi tag "aplikasi-web" versi 1.0
docker build -t aplikasi-web:1.0 .
Catatan: Jangan lupa membuat file
.dockerignoredi direktori yang sama. File ini berfungsi seperti.gitignore, mencegah file besar dan tidak relevan (misalnyanode_modulesatau log) disalin ke build context, yang secara signifikan mempercepat proses build.
⚡ Optimasi Dockerfile: Caching dan Multi-Stage Builds
Image Docker yang optimal harus kecil, cepat dibangun, dan aman. Dua teknik berikut sangat penting untuk mencapai hal ini:
1. Optimasi Caching (Memanfaatkan Layering)
Docker menggunakan build cache berdasarkan urutan instruksi. Jika sebuah instruksi dan file pendukungnya tidak berubah, Docker akan menggunakan layer yang sudah ada (cache) alih-alih mengeksekusi ulang instruksi tersebut.
Prinsip Optimasi Caching:
Pindahkan instruksi yang jarang berubah ke atas (awal) Dockerfile.
Pindahkan instruksi yang sering berubah ke bawah (akhir) Dockerfile.
Contoh Praktik Buruk vs Terbaik:
| Praktik Buruk | Praktik Terbaik (Cache Optimal) | Alasan |
COPY . . | COPY package.json . | Jika kita menyalin semua file dulu, perubahan pada satu file kode akan membatalkan cache untuk RUN npm install. |
RUN npm install | RUN npm install | Memisahkan COPY package.json (yang jarang berubah) dari COPY . . (yang sering berubah) memastikan npm install (perintah yang mahal) hanya dijalankan ulang ketika dependency berubah, bukan ketika kode berubah. |
COPY . . | COPY . . |
2. Multi-Stage Builds (Image Kecil dan Aman)
Banyak aplikasi membutuhkan tool besar (compiler, dependency developer) hanya untuk proses build, tetapi tidak dibutuhkan saat runtime. Multi-Stage Builds memungkinkan Anda menggunakan satu stage (“stage build“) yang besar untuk kompilasi, kemudian membuang tool tersebut dan hanya menyalin hasil aplikasi final ke stage baru (“stage runtime“) yang sangat kecil dan ringan.
# Stage 1: Build Stage (Besar, berisi compiler dan dependency)
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json .
RUN npm install
COPY . .
RUN npm run build # Menghasilkan file statik/executable di /app/dist
# Stage 2: Production/Runtime Stage (Kecil, hanya berisi runtime)
FROM node:20-slim
WORKDIR /app
# HANYA salin hasil kompilasi dari Stage 1
COPY --from=builder /app/dist /app/dist
# Salin dependency runtime (jika ada)
# ...
EXPOSE 8080
CMD ["node", "/app/dist/server.js"]
Keuntungan: Image akhir
node:20-slimjauh lebih kecil dan secara implisit lebih aman karena tidak menyertakan tool developer yang tidak dibutuhkan.
💾 Manajemen Data: Volumes dan Bind Mounts
Kontainer secara default bersifat sementara (ephemeral). Semua data yang ditulis di dalam Kontainer akan hilang saat Kontainer dihapus. Oleh karena itu, data penting (terutama data database) harus disimpan secara persisten. Docker menyediakan dua mekanisme utama:
1. Docker Volumes (Pilihan Terbaik untuk Data Persisten)
Volume adalah direktori khusus pada sistem file Host yang dikelola sepenuhnya oleh Docker. Ini adalah metode yang direkomendasikan untuk menyimpan data database dan data penting lainnya karena:
Dikelola dan dilacak dengan baik oleh Docker.
Isolasi dari sistem file Host yang mendasarinya.
# 1. Membuat Volume bernama 'data_db_postgres'
docker volume create data_db_postgres
# 2. Menjalankan Kontainer dan Melekatkan Volume (-v)
docker run -d --name my_postgres \
-e POSTGRES_PASSWORD=rahasia \
-v data_db_postgres:/var/lib/postgresql/data \
postgres:16
data_db_postgres:/var/lib/postgresql/dataartinya data PostgreSQL di dalam kontainer akan disimpan secara persisten di Volume Host.
2. Bind Mounts (Pilihan Terbaik untuk Pengembangan)
Bind Mounts memungkinkan Anda untuk melekatkan file atau direktori spesifik dari Host ke Kontainer. Ini sangat berguna selama fase pengembangan.
# Menjalankan kontainer dan secara langsung melekatkan kode sumber
docker run -d --name dev_app \
-p 3000:3000 \
-v /path/di/mesin/anda/kode:/app \
aplikasi-web:1.0
Keuntungan Pengembangan: Perubahan yang Anda buat pada kode di Host Anda akan langsung tercermin di dalam Kontainer (tanpa perlu membangun ulang image), karena keduanya berbagi lokasi file yang sama.
Matriks Perbandingan Volumes vs Bind Mounts
| Kriteria | Docker Volumes | Bind Mounts |
| Penggunaan Utama | Data Persisten (Database, Cache). | Pengembangan Lokal (Kode Sumber). |
| Lokasi Data | Dikelola oleh Docker, di lokasi tersembunyi. | Path spesifik yang Anda tentukan di Host. |
| Aman & Portabel | Ya, sangat portabel antar OS Host. | Tidak seportabel Volume. |
| Kepentingan Dikelola Docker | Tinggi. | Rendah (Anda mengelola lokasi Host). |
🧩 Docker Compose: Mengorkestrasi Layanan Lokal
Aplikasi multi-tier (misalnya, web app yang terhubung ke database dan Redis) tidak dapat dikelola hanya dengan perintah docker run berulang kali. Docker Compose adalah tool untuk mendefinisikan dan menjalankan aplikasi multi-kontainer menggunakan satu file docker-compose.yml (atau compose.yml).
1. Struktur File docker-compose.yml
File Compose mendefinisikan:
Services: Layanan aplikasi (misalnya,
web,db,cache).Networks: Jaringan internal untuk komunikasi antar layanan.
Volumes: Volume data persisten.
# Contoh docker-compose.yml
version: '3.8'
services:
web:
build: . # Menggunakan Dockerfile di direktori saat ini
ports:
- "80:8000"
volumes:
- ./app:/app # Bind Mount untuk development
depends_on:
- db # Memastikan db berjalan sebelum web dimulai
db:
image: postgres:16-alpine
restart: always
environment:
POSTGRES_USER: user_app
POSTGRES_PASSWORD: secret_password
POSTGRES_DB: app_db
volumes:
- postgres_data:/var/lib/postgresql/data # Volume untuk data persisten
volumes:
postgres_data: # Definisi volume yang akan dibuat
2. Perintah Kunci Docker Compose
docker compose up: Membangun image (jika perlu), membuat jaringan, volume, dan menjalankan semua layanan.Code snippetdocker compose up -d # Menjalankan di background (detached)docker compose ps: Menampilkan status semua layanan yang berjalan.docker compose logs: Menampilkan log dari semua layanan.docker compose down: Menghentikan dan menghapus kontainer, jaringan, dan volume (kecuali yang eksternal).Code snippetdocker compose down docker compose down --volumes # Menghapus kontainer DAN volumes data
Perhatian: Selalu berhati-hati saat menggunakan
docker compose down --volumesdi lingkungan produksi (jika ada data penting di sana).
💻 Kesimpulan: Pengemasan Profesional dengan Docker
Seri 2 telah melengkapi Anda dengan keterampilan penting untuk membangun, mengemas, dan mengelola aplikasi multi-kontainer di lingkungan lokal. Penguasaan Dockerfile yang efisien melalui Multi-stage builds dan optimalisasi caching memastikan image Anda ringan dan cepat, sementara Docker Compose mengubah setup yang rumit menjadi satu command sederhana. Kunci sukses di sini adalah memastikan Persistensi Data melalui Volumes.
Langkah Anda selanjutnya adalah membawa aplikasi yang sudah terkontainerisasi ini ke tahap skalabilitas global. Docker Compose hanya cocok untuk pengembangan lokal atau server tunggal. Untuk mencapai ketersediaan tinggi, self-healing, dan skalabilitas ribuan kontainer, kita membutuhkan orkestrator yang jauh lebih kuat: Kubernetes.
Berikut adalah command esensial yang harus Anda jadikan panduan untuk build dan compose:
# DOCKERFILE & COMPOSE ESSENTIALS SERI 2: BUILD & ORKESTRASI LOKAL
# ----------------------------------------------------
# 1. Build Image Kustom
docker build -t [nama_aplikasi]:[tag] .
# 2. Membuat dan Menjalankan Aplikasi Multi-Kontainer
docker compose up -d
# 3. Melihat Log Semua Layanan
docker compose logs -f
# 4. Menghentikan dan Membersihkan Lingkungan Lokal
docker compose down
# 5. Mengakses Shell Kontainer (untuk troubleshooting)
docker exec -it [nama_kontainer_atau_id] sh
# ----------------------------------------------------
# SELANJUTNYA: Pengenalan dan Arsitektur Kubernetes di Seri 3.
Anda kini siap melompat dari satu server lokal ke cluster terdistribusi.

