1. Pengenalan Docker
Docker adalah platform open-source yang memungkinkan developer untuk mengemas aplikasi beserta seluruh dependensinya ke dalam satu unit yang disebut container. Diperkenalkan oleh Solomon Hykes pada tahun 2013 melalui perusahaan Docker Inc., platform ini telah mengubah cara developer membangun, mengirim, dan menjalankan aplikasi secara drastis.
Sebelum Docker, masalah klasik yang sering dihadapi tim developer adalah "works on my machine" â aplikasi berjalan sempurna di komputer developer, tetapi gagal di lingkungan production. Docker memecahkan masalah ini dengan memastikan bahwa aplikasi berjalan di lingkungan yang konsisten di mana pun â dari laptop developer hingga server production.
Mengapa Docker Penting?
| Keunggulan | Penjelasan |
|---|---|
| Konsistensi | Aplikasi berjalan sama di semua environment â development, staging, production |
| Isolasi | Setiap container terisolasi, tidak saling mengganggu satu sama lain |
| Portabilitas | Container bisa dipindahkan antar server tanpa perubahan kode |
| Ringan | Container berbagi host OS kernel, jauh lebih ringan dari VM |
| Cepat | Container bisa dimulai dalam hitungan detik, bukan menit |
| Skalabel | Mudah menambah atau mengurangi container sesuai beban |
| Ekosistem Luas | Docker Hub menyediakan jutaan image siap pakai |
ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â DOCKER ECOSYSTEM â â â â ââââââââââââ ââââââââââââââââ âââââââââââââââââââââ â â â Docker â â Docker â â Docker Hub â â â â CLI âââââºâ Daemon ââââââ (Registry) â â â â (Client) â â (dockerd) â â - Official imgs â â â ââââââââââââ ââââââââ¬ââââââââ â - Community imgs â â â â âââââââââââââââââââââ â â ⌠â â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â â â HOST OPERATING SYSTEM â â â â ââââââââââââââ ââââââââââââââ ââââââââââââââ â â â â â Container 1â â Container 2â â Container 3â â â â â â ââââââââââ â â ââââââââââ â â ââââââââââ â â â â â â â Node.jsâ â â â Python â â â â Go â â â â â â â â App â â â â App â â â â App â â â â â â â ââââââââââ â â ââââââââââ â â ââââââââââ â â â â â â + libs â â + libs â â + libs â â â â â ââââââââââââââ ââââââââââââââ ââââââââââââââ â â â â âââââââââââââ¬âââââââââââââââ â â â â SHARED KERNEL â â â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââ â ââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââââ
Konsep dasar Docker melibatkan tiga komponen utama:
- Docker Engine â runtime yang menjalankan container (terdiri dari daemon dan CLI)
- Docker Image â template read-only yang berisi kode aplikasi dan dependencies
- Docker Container â instance yang berjalan dari sebuah image
2. Containers vs Virtual Machines
Banyak developer pemula bingung antara container dan virtual machines (VM). Meskipun keduanya bertujuan untuk mengisolasi aplikasi, cara kerjanya sangat berbeda dan masing-masing memiliki kelebihan tersendiri.
Apa itu Virtual Machine?
Virtual Machine mensimulasikan seluruh komputer â termasuk hardware virtual, operating system, dan aplikasi. Setiap VM menjalankan OS sendiri (guest OS) di atas hypervisor yang berjalan di host OS. Ini membuat VM sangat berat karena setiap instance membawa overhead OS lengkap.
Apa itu Container?
Container berbagi kernel host OS dan hanya mengisolasi aplikasi beserta dependensinya. Container menggunakan fitur Linux kernel seperti namespaces dan cgroups untuk isolasi dan pembatasan resource. Ini membuat container jauh lebih ringan dan cepat dibanding VM.
Perbandingan Detail
| Aspek | Container (Docker) | Virtual Machine |
|---|---|---|
| Ukuran | ð¢ MB (ringan) | ðŽ GB (berat) |
| Startup Time | ð¢ Detik | ðŽ Menit |
| Isolasi | ð¡ Process-level | ð¢ Hardware-level |
| OS | Berbagi host kernel | OS sendiri per VM |
| Resource Usage | ð¢ Rendah | ðŽ Tinggi |
| Portability | ð¢ Sangat portable | ð¡ Terbatas |
| Keamanan | ð¡ Cukup aman | ð¢ Lebih aman |
| Density | Ratusan per host | Puluhan per host |
| Contoh Tool | Docker, Podman | VMware, VirtualBox, KVM |
VIRTUAL MACHINE CONTAINER ââââââââââââ ââââââââââââ ââââââââââââ ââââââââââââ â App A â â App B â â App A â â App B â â Libs â â Libs â â Libs â â Libs â â Guest â â Guest â âââââââââââ†âââââââââââ†â OS â â OS â â Container Runtime â âââââââââââ†âââââââââââ†ââââââââââââââââââââââââââ†â Hypervisor â â Host OS + Kernel â ââââââââââââââââââââââââââ†ââââââââââââââââââââââââââ†â Host OS + Hardware â â Hardware â âââââââââââââââââââââââââââ âââââââââââââââââââââââââââ VM = Banyak OS kernel Container = Satu shared kernel â Berat, lambat start â Ringan, cepat start
Container dan VM bukan saling menggantikan â mereka bisa digunakan bersama. Banyak perusahaan besar menjalankan Docker containers di dalam VM untuk mendapatkan keuntungan dari keduanya: isolasi hardware VM dan efisiensi container.
3. Instalasi Docker
Docker tersedia untuk berbagai platform. Berikut panduan instalasi untuk masing-masing sistem operasi:
Linux (Ubuntu/Debian)
# Update package index sudo apt update # Install dependencies sudo apt install -y ca-certificates curl gnupg # Tambah Docker GPG key sudo install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \ sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg # Tambah Docker repository echo "deb [arch=$(dpkg --print-architecture) \ signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(lsb_release -cs) stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # Install Docker Engine sudo apt update sudo apt install -y docker-ce docker-ce-cli containerd.io \ docker-buildx-plugin docker-compose-plugin # Tambah user ke grup docker (agar tidak perlu sudo) sudo usermod -aG docker $USER # Verifikasi instalasi docker --version docker run hello-world
macOS & Windows
Untuk macOS dan Windows, gunakan Docker Desktop â aplikasi GUI yang sudah termasuk Docker Engine, Docker CLI, Docker Compose, dan Kubernetes:
- Download Docker Desktop dari
https://www.docker.com/products/docker-desktop - Install dan jalankan aplikasi
- Buka terminal dan jalankan
docker --versionuntuk verifikasi
Verifikasi Instalasi
# Cek versi Docker docker --version # Output: Docker version 27.0.3, build 7d4bcd8 # Cek info sistem Docker docker info # Jalankan container test docker run --rm hello-world # Output: Hello from Docker! # This message shows that your installation appears # to be working correctly.
4. Dockerfile: Membuat Image Sendiri
Dockerfile adalah file teks berisi instruksi langkah demi langkah untuk membangun Docker image. Setiap instruksi menciptakan satu layer pada image, dan Docker menggunakan caching untuk mempercepat proses build jika layer sebelumnya tidak berubah.
Struktur Dasar Dockerfile
# Dockerfile untuk aplikasi Node.js sederhana # BeebaneLabs - Docker Tutorial # 1. Base image - gunakan image resmi yang ringan FROM node:20-alpine # 2. Metadata (opsional tapi disarankan) LABEL maintainer="developer@beebanelabs.com" LABEL description="Aplikasi Node.js sederhana dengan Docker" # 3. Set working directory di dalam container WORKDIR /app # 4. Copy package files dulu (manfaatkan layer caching) COPY package*.json ./ # 5. Install dependencies RUN npm ci --only=production # 6. Copy source code aplikasi COPY . . # 7. Set environment variable ENV NODE_ENV=production ENV PORT=3000 # 8. Expose port yang digunakan aplikasi EXPOSE 3000 # 9. Perintah untuk menjalankan aplikasi CMD ["node", "server.js"]
Instruksi Penting Dockerfile
| Instruksi | Fungsi | Contoh |
|---|---|---|
FROM | Base image yang digunakan | FROM python:3.12-slim |
RUN | Menjalankan perintah saat build | RUN apt-get install -y curl |
COPY | Menyalin file dari host ke image | COPY . /app |
WORKDIR | Set direktori kerja | WORKDIR /app |
ENV | Set environment variable | ENV PORT=3000 |
EXPOSE | Deklarasi port yang digunakan | EXPOSE 8080 |
CMD | Perintah default saat container start | CMD ["node", "app.js"] |
ENTRYPOINT | Perintah utama (tidak bisa di-override mudah) | ENTRYPOINT ["python"] |
ARG | Variable build-time | ARG VERSION=1.0 |
HEALTHCHECK | Cek kesehatan container | HEALTHCHECK CMD curl localhost |
Contoh Dockerfile untuk Python
# Dockerfile untuk aplikasi Flask/Python
FROM python:3.12-slim
WORKDIR /app
# Install system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
gcc \
&& rm -rf /var/lib/apt/lists/*
# Copy requirements dan install Python dependencies
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
# Copy aplikasi
COPY . .
# Buat user non-root untuk keamanan
RUN adduser --disabled-password --gecos "" appuser
USER appuser
EXPOSE 5000
CMD ["python", "app.py"]
Build dan Run Image
# Build image dari Dockerfile docker build -t my-app:v1.0 . # Lihat daftar images docker images # REPOSITORY TAG IMAGE ID SIZE # my-app v1.0 abc123def456 150MB # Jalankan container dari image docker run -d -p 3000:3000 --name web-app my-app:v1.0 # Lihat container yang berjalan docker ps # Lihat log container docker logs web-app # Masuk ke dalam container (debug) docker exec -it web-app /bin/sh # Hentikan dan hapus container docker stop web-app docker rm web-app
Jangan pernah menjalankan container dengan --privileged atau sebagai root di production. Selalu buat user non-root seperti contoh Dockerfile Python di atas untuk keamanan yang lebih baik.
5. Docker Images
Docker image adalah template read-only yang digunakan untuk membuat container. Image terdiri dari beberapa layers yang saling bertumpuk â setiap instruksi di Dockerfile menciptakan satu layer. Docker menggunakan sistem layer ini untuk efisiensi: layer yang sama bisa di-share antar images.
Perintah Dasar Images
# Tarik image dari Docker Hub docker pull nginx:latest docker pull python:3.12-slim docker pull node:20-alpine # Lihat semua images lokal docker images docker image ls # Lihat detail image docker inspect nginx:latest # Lihat history layer image docker history nginx:latest # Beri tag baru pada image docker tag my-app:v1.0 my-app:latest docker tag my-app:v1.0 registry.example.com/my-app:v1.0 # Hapus image docker rmi nginx:latest docker image rm my-app:v1.0 # Hapus semua image yang tidak digunakan docker image prune -a
Multi-Stage Build
Teknik multi-stage build memungkinkan Anda menggunakan satu Dockerfile dengan beberapa FROM statement. Ini sangat berguna untuk mengurangi ukuran image final â Anda bisa menggunakan image besar untuk compile, lalu menyalin hanya hasilnya ke image yang lebih kecil:
# Stage 1: Build FROM golang:1.22-alpine AS builder WORKDIR /app COPY go.* ./ RUN go mod download COPY . . RUN CGO_ENABLED=0 go build -o /server . # Stage 2: Production (image kecil!) FROM alpine:3.19 RUN apk --no-cache add ca-certificates COPY --from=builder /server /server EXPOSE 8080 CMD ["/server"] # Hasil: image hanya ~15MB dibanding ~800MB jika pakai golang image
Memilih Base Image yang Tepat
| Base Image | Ukuran | Kapan Digunakan |
|---|---|---|
alpine | ~5 MB | Saat butuh image sekecil mungkin |
slim variants | ~50-100 MB | Balance antara ukuran dan fitur |
debian:bookworm | ~120 MB | Saat butuh banyak system packages |
distroless | ~20 MB | Production â tanpa shell, paling aman |
ubuntu | ~80 MB | Familiar, dukungan komunitas luas |
6. Docker Volumes
Secara default, data di dalam container bersifat ephemeral â hilang saat container dihapus. Docker Volumes memungkinkan Anda menyimpan data secara persisten di luar container. Ini sangat penting untuk database, file upload, dan data yang perlu bertahan setelah container restart.
Tiga Cara Menyimpan Data
| Tipe | Lokasi | Kapan Digunakan |
|---|---|---|
| Named Volume | Dikelola Docker di /var/lib/docker/volumes/ | Produksi â paling disarankan |
| Bind Mount | Path spesifik di host machine | Development â akses file langsung |
| tmpfs Mount | RAM (memory) | Data sensitif sementara |
Perintah Volumes
# === NAMED VOLUME === # Buat volume baru docker volume create my-data # Lihat semua volumes docker volume ls # Inspect volume docker volume inspect my-data # Gunakan volume saat menjalankan container docker run -d \ --name postgres-db \ -v my-data:/var/lib/postgresql/data \ -e POSTGRES_PASSWORD=secret \ postgres:16 # === BIND MOUNT === # Mount direktori lokal ke container docker run -d \ --name web-server \ -v $(pwd)/html:/usr/share/nginx/html:ro \ -p 8080:80 \ nginx:latest # :ro = read-only, :rw = read-write (default) # === TMPFS MOUNT === docker run -d \ --name secure-app \ --tmpfs /app/temp:rw,size=100m \ my-app:v1.0
Volume dengan Dockerfile
# Deklarasi volume di Dockerfile FROM postgres:16 VOLUME /var/lib/postgresql/data # Data di /var/lib/postgresql/data akan disimpan # di volume anonymous secara otomatis
Backup dan Restore Volume
# Backup volume ke file tar docker run --rm \ -v my-data:/source:ro \ -v $(pwd):/backup \ alpine tar czf /backup/my-data-backup.tar.gz -C /source . # Restore volume dari file tar docker run --rm \ -v my-data:/target \ -v $(pwd):/backup \ alpine tar xzf /backup/my-data-backup.tar.gz -C /target # Hapus volume yang tidak digunakan docker volume prune
Untuk development, bind mount sangat nyaman karena perubahan file langsung terlihat di container. Untuk production, selalu gunakan named volume atau external storage service untuk keamanan dan performa yang lebih baik.
7. Docker Networking
Docker menyediakan sistem networking yang memungkinkan container berkomunikasi satu sama lain dan dengan dunia luar. Memahami Docker networking sangat penting saat membangun aplikasi multi-container yang terdiri dari beberapa layanan.
Tipe Jaringan Docker
| Tipe | Deskripsi | Kapan Digunakan |
|---|---|---|
| bridge | Jaringan default â container bisa berkomunikasi via IP | Single-host, app multi-container |
| host | Container berbagi jaringan host langsung | Performa tinggi, tanpa isolasi jaringan |
| none | Tidak ada jaringan sama sekali | Container yang tidak butuh internet |
| overlay | Jaringan antar mesin (Swarm mode) | Multi-host, production cluster |
| macvlan | Container dapat MAC address sendiri | App legacy yang butuh MAC langsung |
Perintah Dasar Networking
# Lihat semua jaringan docker network ls # Buat jaringan custom (bridge) docker network create my-network # Jalankan container di jaringan tertentu docker run -d --name app --network my-network my-app:v1.0 docker run -d --name db --network my-network postgres:16 # Container dalam jaringan yang sama bisa saling # mengakses menggunakan nama container sebagai hostname # Misal: app bisa akses db via "db:5432" # Hubungkan container yang sudah berjalan ke jaringan docker network connect my-network existing-container # Putuskan container dari jaringan docker network disconnect my-network existing-container # Inspect jaringan docker network inspect my-network # Hapus jaringan docker network rm my-network
Port Mapping
# Mapping port host:container docker run -d -p 8080:80 nginx # Akses: http://localhost:8080 -> container port 80 # Mapping ke semua interface docker run -d -p 0.0.0.0:3000:3000 my-app # Mapping ke interface tertentu docker run -d -p 127.0.0.1:5432:5432 postgres # Docker pilih port random di host docker run -d -P nginx # Cek port: docker port# Mapping beberapa port sekaligus docker run -d -p 80:80 -p 443:443 nginx
âââââââââââââââââââââââââââââââââââââââââââââââââââ â HOST MACHINE â â â â ââââââââââââââââââââââââââââââââââââââââââââ â â â bridge network (my-network) â â â â â â â â ââââââââââââ ââââââââââââââââ â â â â â web-app ââââââºâ postgres-db â â â â â â :3000 â â :5432 â â â â â ââââââ¬ââââââ ââââââââââââââââ â â â â â â â â âââââââââŒââââââââââââââââââââââââââââââââââââ â â â â â ⌠â â âââââââââââââââ â â â Port 3000 ââââ Internet Traffic â â âââââââââââââââ â âââââââââââââââââââââââââââââââââââââââââââââââââââ Web-app dan postgres-db saling akses via nama container
8. Docker Compose
Docker Compose adalah tool untuk mendefinisikan dan menjalankan aplikasi multi-container. Dengan satu file YAML (docker-compose.yml), Anda bisa mendefinisikan semua layanan, jaringan, dan volumes yang dibutuhkan aplikasi Anda. Compose sangat memudahkan setup development dan deployment.
Contoh docker-compose.yml Lengkap
# docker-compose.yml
# Aplikasi Web + Database + Redis
version: "3.8"
services:
# === Aplikasi Web (Node.js) ===
web:
build:
context: .
dockerfile: Dockerfile
container_name: web-app
ports:
- "3000:3000"
environment:
- NODE_ENV=production
- DATABASE_URL=postgresql://user:password@db:5432/myapp
- REDIS_URL=redis://cache:6379
volumes:
- ./uploads:/app/uploads
depends_on:
db:
condition: service_healthy
cache:
condition: service_started
networks:
- app-network
restart: unless-stopped
# === Database PostgreSQL ===
db:
image: postgres:16-alpine
container_name: postgres-db
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: myapp
volumes:
- postgres-data:/var/lib/postgresql/data
- ./init.sql:/docker-entrypoint-initdb.d/init.sql
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U user -d myapp"]
interval: 10s
timeout: 5s
retries: 5
networks:
- app-network
restart: unless-stopped
# === Redis Cache ===
cache:
image: redis:7-alpine
container_name: redis-cache
command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru
volumes:
- redis-data:/data
networks:
- app-network
restart: unless-stopped
# === Nginx Reverse Proxy ===
nginx:
image: nginx:alpine
container_name: nginx-proxy
ports:
- "80:80"
- "443:443"
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf:ro
- ./ssl:/etc/nginx/ssl:ro
depends_on:
- web
networks:
- app-network
restart: unless-stopped
volumes:
postgres-data:
redis-data:
networks:
app-network:
driver: bridge
Perintah Docker Compose
# Jalankan semua layanan (foreground) docker compose up # Jalankan di background (detached) docker compose up -d # Build ulang image sebelum start docker compose up --build # Hentikan semua layanan docker compose down # Hentikan dan hapus volumes (HATI-HATI: data hilang!) docker compose down -v # Lihat status layanan docker compose ps # Lihat log layanan tertentu docker compose logs web docker compose logs -f db # -f = follow (live) # Jalankan perintah di dalam container docker compose exec web npm run migrate docker compose exec db psql -U user -d myapp # Scale layanan tertentu docker compose up -d --scale web=3 # Restart satu layanan docker compose restart web
Gunakan depends_on dengan health check untuk memastikan layanan dependency benar-benar siap sebelum layanan utama dimulai. Tanpa ini, aplikasi bisa gagal karena database belum siap menerima koneksi.
9. Docker Hub
Docker Hub adalah registry publik terbesar untuk Docker images. Di Docker Hub, Anda bisa menemukan jutaan image siap pakai â dari database, web server, bahasa pemrograman, hingga aplikasi lengkap. Docker Hub juga mendukung automated builds yang bisa membangun image langsung dari repository GitHub atau Bitbucket.
Perintah Docker Hub
# Login ke Docker Hub docker login # Masukkan username dan password # Tarik image dari Docker Hub docker pull nginx:latest docker pull postgres:16-alpine docker pull python:3.12-slim # Cari image di Docker Hub docker search mysql docker search redis # Push image ke Docker Hub # 1. Tag image dengan format username/repo:tag docker tag my-app:v1.0 username/my-app:v1.0 docker tag my-app:v1.0 username/my-app:latest # 2. Push ke Docker Hub docker push username/my-app:v1.0 docker push username/my-app:latest # Logout dari Docker Hub docker logout
Private Registry
Selain Docker Hub, Anda juga bisa menggunakan private registry untuk keamanan lebih:
# Jalankan registry lokal (untuk development) docker run -d -p 5000:5000 --name registry registry:2 # Tag dan push ke registry lokal docker tag my-app:v1.0 localhost:5000/my-app:v1.0 docker push localhost:5000/my-app:v1.0 # Tarik dari registry lokal docker pull localhost:5000/my-app:v1.0 # Cloud registries: # - AWS ECR: aws ecr # - Google GCR: gcr.io # - Azure ACR: azurecr.io # - GitHub GHCR: ghcr.io # - GitLab: registry.gitlab.com
10. Best Practices Docker
Mengikuti best practices saat bekerja dengan Docker sangat penting untuk keamanan, performa, dan maintainability. Berikut adalah panduan lengkap yang harus Anda ikuti:
1. Gunakan Multi-Stage Build
# â JELEK â image besar dengan semua build tools FROM node:20 WORKDIR /app COPY . . RUN npm install RUN npm run build CMD ["node", "dist/server.js"] # â BAIK â multi-stage, image kecil FROM node:20-alpine AS builder WORKDIR /app COPY package*.json ./ RUN npm ci COPY . . RUN npm run build FROM node:20-alpine WORKDIR /app COPY --from=builder /app/dist ./dist COPY --from=builder /app/node_modules ./node_modules EXPOSE 3000 CMD ["node", "dist/server.js"]
2. Gunakan .dockerignore
node_modules .git .gitignore .env .env.local *.md docker-compose*.yml Dockerfile .dockerignore coverage .nyc_output dist build *.log .vscode .idea
3. Best Practices Lainnya
| Praktik | Alasan |
|---|---|
| Gunakan image versi spesifik | node:20.11-alpine lebih stabil dari node:latest |
| Jangan pakai root user | Serangan container escape bisa akses host |
| Minimalkan layers | Gabungkan RUN commands untuk kurangi ukuran |
| Copy requirements dulu | Manfaatkan layer caching saat dependency tidak berubah |
| Gunakan HEALTHCHECK | Docker bisa monitor kesehatan container |
| Scan image untuk vulnerabilities | Gunakan docker scout atau Trivy |
| Jangan simpan secrets di image | Gunakan environment variable atau Docker secrets |
| Gunakan restart policy | restart: unless-stopped untuk high availability |
| Set resource limits | Batasi CPU dan memory agar container tidak rakus |
# Scan image untuk vulnerabilities
docker scout cves my-app:v1.0
# Batasi resource container
docker run -d \
--name my-app \
--memory="512m" \
--cpus="1.5" \
--restart=unless-stopped \
my-app:v1.0
# Lihat resource usage container
docker stats
# Bersihkan semua resource tidak terpakai
docker system prune -a --volumes
# Lihat ukuran image
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
11. Quiz: Uji Pemahamanmu!
Setelah membaca tutorial di atas, jawablah 5 pertanyaan berikut untuk menguji pemahamanmu tentang Docker: