| 1 | --- |
| 2 | title: "Docker" |
| 3 | term: "apa-itu-docker" |
| 4 | category: "Cloud & Infrastructure" |
| 5 | tags: ["container", "virtualization", "devops", "deployment", "microservices"] |
| 6 | description: "Platform untuk develop, ship, dan run aplikasi dalam containers yang isolated, portable, dan lightweight." |
| 7 | englishTerm: "Docker" |
| 8 | relatedTerms: ["apa-itu-container", "apa-itu-kubernetes", "apa-itu-devops", "apa-itu-microservices", "apa-itu-virtualisasi"] |
| 9 | difficulty: "menengah" |
| 10 | lastmod: 2024-01-15 |
| 11 | published: true |
| 12 | --- |
| 13 | |
| 14 | ## Apa itu Docker? |
| 15 | |
| 16 | **Docker** adalah platform open-source untuk menjalankan aplikasi di dalam **container**. Container berisi aplikasi beserta dependency penting yang dibutuhkan, sehingga aplikasi yang sama bisa dijalankan di laptop developer, server staging, atau production dengan perilaku yang lebih konsisten. |
| 17 | |
| 18 | Analogi yang sering dipakai memang kontainer pengiriman barang, dan itu cukup membantu. Isi di dalamnya bisa berbeda-beda, tetapi bentuk pengemasannya tetap sama. Di software, ide dasarnya juga mirip: aplikasi dibungkus dengan cara yang lebih seragam supaya lebih mudah dipindahkan dan dijalankan. |
| 19 | |
| 20 | ## Masalah yang Dipecahkan Docker |
| 21 | |
| 22 | ### "It Works on My Machine" |
| 23 | |
| 24 | Sebelum Docker, masalah klasiknya sederhana: aplikasi berjalan mulus di laptop developer, tapi bermasalah saat pindah ke server. |
| 25 | |
| 26 | Beberapa penyebab yang sering muncul: |
| 27 | - Versi dependency berbeda |
| 28 | - Konfigurasi environment tidak sama |
| 29 | - OS atau library sistem tidak cocok |
| 30 | |
| 31 | Docker membantu dengan cara membungkus aplikasi bersama komponen yang dibutuhkan. Hasilnya bukan berarti semua masalah hilang, tetapi perbedaan antar-environment jadi jauh lebih kecil. |
| 32 | |
| 33 | ## Docker vs Virtual Machines |
| 34 | |
| 35 | | Aspek | Docker Container | Virtual Machine | |
| 36 | |-------|-----------------|-----------------| |
| 37 | | **Size** | MB (megabytes) | GB (gigabytes) | |
| 38 | | **Startup** | Detik | Menit | |
| 39 | | **Performance** | Near-native | Overhead significant | |
| 40 | | **Isolation** | Process-level | Hardware-level | |
| 41 | | **OS** | Share host kernel | Full OS per VM | |
| 42 | | **Resource Usage** | Efficient | Heavy | |
| 43 | |
| 44 | ### Visualisasi |
| 45 | |
| 46 | ``` |
| 47 | Virtual Machine: |
| 48 | ┌─────────────────────────┐ |
| 49 | │ App A │ App B │ |
| 50 | ├───────────┼─────────────┤ |
| 51 | │ Guest OS │ Guest OS │ |
| 52 | ├───────────┴─────────────┤ |
| 53 | │ Hypervisor │ |
| 54 | ├─────────────────────────┤ |
| 55 | │ Host OS │ |
| 56 | ├─────────────────────────┤ |
| 57 | │ Hardware │ |
| 58 | └─────────────────────────┘ |
| 59 | |
| 60 | Docker: |
| 61 | ┌─────────────────────────┐ |
| 62 | │ App A │ App B │ |
| 63 | ├───────────┼─────────────┤ |
| 64 | │ Container │ Container │ |
| 65 | ├───────────┴─────────────┤ |
| 66 | │ Docker Engine │ |
| 67 | ├─────────────────────────┤ |
| 68 | │ Host OS │ |
| 69 | ├─────────────────────────┤ |
| 70 | │ Hardware │ |
| 71 | └─────────────────────────┘ |
| 72 | ``` |
| 73 | |
| 74 | ## Konsep Penting Docker |
| 75 | |
| 76 | ### 1. Docker Image |
| 77 | |
| 78 | **Image** adalah template read-only yang berisi instruksi untuk membuat container. Seperti "blueprint" atau "snapshot" dari aplikasi. |
| 79 | |
| 80 | ```bash |
| 81 | # Download image dari Docker Hub |
| 82 | docker pull nginx:latest |
| 83 | docker pull node:18-alpine |
| 84 | docker pull postgres:15 |
| 85 | ``` |
| 86 | |
| 87 | ### 2. Docker Container |
| 88 | |
| 89 | **Container** adalah running instance dari image. Satu image bisa digunakan untuk membuat banyak containers. |
| 90 | |
| 91 | ```bash |
| 92 | # Jalankan container dari image |
| 93 | docker run -d -p 8080:80 nginx:latest |
| 94 | |
| 95 | # List running containers |
| 96 | docker ps |
| 97 | |
| 98 | # Stop container |
| 99 | docker stop <container_id> |
| 100 | ``` |
| 101 | |
| 102 | ### 3. Dockerfile |
| 103 | |
| 104 | File instruksi untuk build Docker image. Seperti "recipe" untuk membuat image. |
| 105 | |
| 106 | ```dockerfile |
| 107 | # Contoh Dockerfile untuk Node.js app |
| 108 | FROM node:18-alpine |
| 109 | |
| 110 | # Set working directory |
| 111 | WORKDIR /app |
| 112 | |
| 113 | # Copy package files |
| 114 | COPY package*.json ./ |
| 115 | |
| 116 | # Install dependencies |
| 117 | RUN npm ci --production |
| 118 | |
| 119 | # Copy source code |
| 120 | COPY . . |
| 121 | |
| 122 | # Expose port |
| 123 | EXPOSE 3000 |
| 124 | |
| 125 | # Set environment |
| 126 | ENV NODE_ENV=production |
| 127 | |
| 128 | # Command to run |
| 129 | CMD ["node", "server.js"] |
| 130 | ``` |
| 131 | |
| 132 | ### 4. Docker Compose |
| 133 | |
| 134 | Tool untuk define dan run multi-container applications. |
| 135 | |
| 136 | ```yaml |
| 137 | # docker-compose.yml |
| 138 | version: '3.8' |
| 139 | services: |
| 140 | web: |
| 141 | build: . |
| 142 | ports: |
| 143 | - "3000:3000" |
| 144 | environment: |
| 145 | - DATABASE_URL=postgres://db:5432/myapp |
| 146 | depends_on: |
| 147 | - db |
| 148 | - redis |
| 149 | |
| 150 | db: |
| 151 | image: postgres:15 |
| 152 | environment: |
| 153 | - POSTGRES_PASSWORD=secret |
| 154 | - POSTGRES_DB=myapp |
| 155 | volumes: |
| 156 | - postgres_data:/var/lib/postgresql/data |
| 157 | |
| 158 | redis: |
| 159 | image: redis:7-alpine |
| 160 | ports: |
| 161 | - "6379:6379" |
| 162 | |
| 163 | volumes: |
| 164 | postgres_data: |
| 165 | ``` |
| 166 | |
| 167 | ```bash |
| 168 | # Jalankan semua services |
| 169 | docker-compose up -d |
| 170 | |
| 171 | # Stop semua services |
| 172 | docker-compose down |
| 173 | ``` |
| 174 | |
| 175 | ## Docker Commands Essentials |
| 176 | |
| 177 | ### Image Management |
| 178 | |
| 179 | ```bash |
| 180 | # List images |
| 181 | docker images |
| 182 | |
| 183 | # Build image dari Dockerfile |
| 184 | docker build -t myapp:v1 . |
| 185 | |
| 186 | # Tag image |
| 187 | docker tag myapp:v1 username/myapp:v1 |
| 188 | |
| 189 | # Push ke registry |
| 190 | docker push username/myapp:v1 |
| 191 | |
| 192 | # Remove image |
| 193 | docker rmi myapp:v1 |
| 194 | ``` |
| 195 | |
| 196 | ### Container Management |
| 197 | |
| 198 | ```bash |
| 199 | # Run container |
| 200 | docker run -d --name myapp -p 8080:3000 myapp:v1 |
| 201 | |
| 202 | # Run dengan environment variables |
| 203 | docker run -d -e DATABASE_URL=postgres://... myapp:v1 |
| 204 | |
| 205 | # Run dengan volumes |
| 206 | docker run -d -v /host/path:/container/path myapp:v1 |
| 207 | |
| 208 | # Execute command di running container |
| 209 | docker exec -it myapp /bin/sh |
| 210 | |
| 211 | # View logs |
| 212 | docker logs myapp |
| 213 | docker logs -f myapp # Follow logs |
| 214 | |
| 215 | # Stop container |
| 216 | docker stop myapp |
| 217 | |
| 218 | # Start stopped container |
| 219 | docker start myapp |
| 220 | |
| 221 | # Remove container |
| 222 | docker rm myapp |
| 223 | |
| 224 | # Remove all stopped containers |
| 225 | docker container prune |
| 226 | ``` |
| 227 | |
| 228 | ### System Commands |
| 229 | |
| 230 | ```bash |
| 231 | # Show Docker info |
| 232 | docker info |
| 233 | |
| 234 | # Show disk usage |
| 235 | docker system df |
| 236 | |
| 237 | # Clean up unused resources |
| 238 | docker system prune -a |
| 239 | |
| 240 | # View container resource usage |
| 241 | docker stats |
| 242 | ``` |
| 243 | |
| 244 | ## Dockerfile Best Practices |
| 245 | |
| 246 | ### 1. Gunakan Official Base Images |
| 247 | |
| 248 | **Kurang tepat:** |
| 249 | ```dockerfile |
| 250 | FROM ubuntu |
| 251 | RUN apt-get update && apt-get install -y nodejs |
| 252 | ``` |
| 253 | |
| 254 | **Lebih baik:** |
| 255 | ```dockerfile |
| 256 | FROM node:18-alpine |
| 257 | ``` |
| 258 | |
| 259 | ### 2. Minimize Layers |
| 260 | |
| 261 | **Kurang efisien:** |
| 262 | ```dockerfile |
| 263 | RUN apt-get update |
| 264 | RUN apt-get install -y git |
| 265 | RUN apt-get install -y curl |
| 266 | ``` |
| 267 | |
| 268 | **Lebih efisien:** |
| 269 | ```dockerfile |
| 270 | RUN apt-get update && apt-get install -y \ |
| 271 | git \ |
| 272 | curl \ |
| 273 | && rm -rf /var/lib/apt/lists/* |
| 274 | ``` |
| 275 | |
| 276 | ### 3. Multi-Stage Builds |
| 277 | |
| 278 | Untuk mengurangi final image size: |
| 279 | |
| 280 | ```dockerfile |
| 281 | # Build stage |
| 282 | FROM node:18 AS builder |
| 283 | WORKDIR /app |
| 284 | COPY package*.json ./ |
| 285 | RUN npm ci |
| 286 | COPY . . |
| 287 | RUN npm run build |
| 288 | |
| 289 | # Production stage |
| 290 | FROM node:18-alpine |
| 291 | WORKDIR /app |
| 292 | COPY --from=builder /app/dist ./dist |
| 293 | COPY --from=builder /app/node_modules ./node_modules |
| 294 | COPY package*.json ./ |
| 295 | EXPOSE 3000 |
| 296 | CMD ["node", "dist/server.js"] |
| 297 | ``` |
| 298 | |
| 299 | ### 4. .dockerignore File |
| 300 | |
| 301 | Exclude files dari build context: |
| 302 | |
| 303 | ``` |
| 304 | # .dockerignore |
| 305 | node_modules |
| 306 | npm-debug.log |
| 307 | .git |
| 308 | .env |
| 309 | .DS_Store |
| 310 | dist |
| 311 | coverage |
| 312 | *.md |
| 313 | ``` |
| 314 | |
| 315 | ### 5. Security Best Practices |
| 316 | |
| 317 | ```dockerfile |
| 318 | # Don't run as root |
| 319 | FROM node:18-alpine |
| 320 | |
| 321 | # Create non-root user |
| 322 | RUN addgroup -g 1001 -S nodejs && \ |
| 323 | adduser -S nodejs -u 1001 |
| 324 | |
| 325 | WORKDIR /app |
| 326 | COPY --chown=nodejs:nodejs . . |
| 327 | RUN npm ci --production |
| 328 | |
| 329 | # Switch to non-root user |
| 330 | USER nodejs |
| 331 | |
| 332 | EXPOSE 3000 |
| 333 | CMD ["node", "server.js"] |
| 334 | ``` |
| 335 | |
| 336 | ## Docker Networking |
| 337 | |
| 338 | ### Bridge Network (Default) |
| 339 | |
| 340 | Containers di network yang sama bisa communicate by name. |
| 341 | |
| 342 | ```bash |
| 343 | # Create custom network |
| 344 | docker network create mynetwork |
| 345 | |
| 346 | # Run containers di network yang sama |
| 347 | docker run -d --name db --network mynetwork postgres |
| 348 | docker run -d --name app --network mynetwork myapp |
| 349 | |
| 350 | # App bisa connect ke db dengan: postgres://db:5432 |
| 351 | ``` |
| 352 | |
| 353 | ### Port Mapping |
| 354 | |
| 355 | ```bash |
| 356 | # Map container port ke host port |
| 357 | docker run -p 8080:3000 myapp # host:container |
| 358 | |
| 359 | # Multiple ports |
| 360 | docker run -p 8080:3000 -p 8081:3001 myapp |
| 361 | |
| 362 | # All ports |
| 363 | docker run -P myapp |
| 364 | ``` |
| 365 | |
| 366 | ## Docker Volumes |
| 367 | |
| 368 | Untuk persistent data storage: |
| 369 | |
| 370 | ### Named Volumes |
| 371 | |
| 372 | ```bash |
| 373 | # Create volume |
| 374 | docker volume create mydata |
| 375 | |
| 376 | # Use volume |
| 377 | docker run -v mydata:/app/data myapp |
| 378 | |
| 379 | # List volumes |
| 380 | docker volume ls |
| 381 | |
| 382 | # Inspect volume |
| 383 | docker volume inspect mydata |
| 384 | ``` |
| 385 | |
| 386 | ### Bind Mounts |
| 387 | |
| 388 | Mount host directory ke container: |
| 389 | |
| 390 | ```bash |
| 391 | # Development: Live reload |
| 392 | docker run -v $(pwd):/app myapp |
| 393 | |
| 394 | # Windows |
| 395 | docker run -v %cd%:/app myapp |
| 396 | ``` |
| 397 | |
| 398 | ## Real-World Use Cases |
| 399 | |
| 400 | ### 1. Development Environment |
| 401 | |
| 402 | ```yaml |
| 403 | # docker-compose.dev.yml |
| 404 | version: '3.8' |
| 405 | services: |
| 406 | app: |
| 407 | build: . |
| 408 | volumes: |
| 409 | - .:/app |
| 410 | - /app/node_modules |
| 411 | ports: |
| 412 | - "3000:3000" |
| 413 | environment: |
| 414 | - NODE_ENV=development |
| 415 | command: npm run dev |
| 416 | ``` |
| 417 | |
| 418 | ### 2. Microservices Architecture |
| 419 | |
| 420 | ```yaml |
| 421 | version: '3.8' |
| 422 | services: |
| 423 | frontend: |
| 424 | image: myapp/frontend |
| 425 | ports: |
| 426 | - "80:80" |
| 427 | |
| 428 | api-gateway: |
| 429 | image: myapp/api-gateway |
| 430 | ports: |
| 431 | - "8080:8080" |
| 432 | |
| 433 | user-service: |
| 434 | image: myapp/user-service |
| 435 | |
| 436 | product-service: |
| 437 | image: myapp/product-service |
| 438 | |
| 439 | order-service: |
| 440 | image: myapp/order-service |
| 441 | ``` |
| 442 | |
| 443 | ### 3. CI/CD Integration |
| 444 | |
| 445 | ```yaml |
| 446 | # .github/workflows/docker.yml |
| 447 | name: Docker Build and Push |
| 448 | on: |
| 449 | push: |
| 450 | branches: [main] |
| 451 | |
| 452 | jobs: |
| 453 | build: |
| 454 | runs-on: ubuntu-latest |
| 455 | steps: |
| 456 | - uses: actions/checkout@v2 |
| 457 | |
| 458 | - name: Build Docker image |
| 459 | run: docker build -t myapp:${{ github.sha }} . |
| 460 | |
| 461 | - name: Push to registry |
| 462 | run: | |
| 463 | echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin |
| 464 | docker push myapp:${{ github.sha }} |
| 465 | ``` |
| 466 | |
| 467 | ## Docker di Production |
| 468 | |
| 469 | ### Orchestration Tools |
| 470 | |
| 471 | Untuk manage containers di scale: |
| 472 | |
| 473 | 1. **Docker Swarm** - Built-in Docker orchestration |
| 474 | 2. **Kubernetes** - Pilihan yang paling sering dipakai untuk container orchestration |
| 475 | 3. **AWS ECS** - Amazon's container service |
| 476 | 4. **Google Cloud Run** - Serverless containers |
| 477 | |
| 478 | ### Health Checks |
| 479 | |
| 480 | ```dockerfile |
| 481 | HEALTHCHECK --interval=30s --timeout=3s \ |
| 482 | CMD curl -f http://localhost:3000/health || exit 1 |
| 483 | ``` |
| 484 | |
| 485 | ### Resource Limits |
| 486 | |
| 487 | ```bash |
| 488 | # Limit memory dan CPU |
| 489 | docker run -m 512m --cpus=1 myapp |
| 490 | ``` |
| 491 | |
| 492 | ## Docker untuk Developer Indonesia |
| 493 | |
| 494 | ### Keuntungan |
| 495 | |
| 496 | 1. **Environment lebih konsisten** - Dev, staging, dan production tidak terlalu jauh bedanya |
| 497 | 2. **Project lebih terisolasi** - Dependency antarproject tidak mudah saling bentrok |
| 498 | 3. **Setup lebih cepat** - Project baru bisa dijalankan tanpa instalasi manual yang panjang |
| 499 | 4. **Kolaborasi lebih rapi** - Tim memakai environment yang kurang lebih sama |
| 500 | 5. **Eksperimen lebih aman** - Mencoba database, message broker, atau service lain jadi lebih mudah |
| 501 | |
| 502 | ### Tantangan |
| 503 | |
| 504 | 1. **Perlu adaptasi di awal** - Konsep image, container, volume, dan network butuh waktu untuk dipahami |
| 505 | 2. **Butuh ruang penyimpanan** - Image dan volume bisa cepat membesar |
| 506 | 3. **Ada overhead di Windows atau macOS** - Biasanya lewat Docker Desktop |
| 507 | 4. **Debugging networking kadang membingungkan** - Terutama saat baru mulai |
| 508 | |
| 509 | ### Tips Mulai dengan Docker |
| 510 | |
| 511 | 1. **Mulai dari satu service** - Jangan langsung memindahkan seluruh sistem sekaligus |
| 512 | 2. **Pakai official image** - Lebih aman untuk belajar dan biasanya dokumentasinya lebih rapi |
| 513 | 3. **Pelajari Docker Compose** - Sangat membantu saat aplikasi punya beberapa service |
| 514 | 4. **Coba di project yang sudah Anda kenal** - Lebih mudah memahami perubahan perilakunya |
| 515 | 5. **Ikuti komunitas** - Banyak kasus sehari-hari justru lebih cepat dipahami dari diskusi developer lain |
| 516 | |
| 517 | ## Alternatif Docker |
| 518 | |
| 519 | - **Podman** - Daemonless, rootless containers |
| 520 | - **LXC/LXD** - System containers |
| 521 | - **rkt** - Alternative container runtime (deprecated) |
| 522 | - **containerd** - Core container runtime (Docker menggunakan ini) |
| 523 | |
| 524 | ## Docker dengan smbCloud |
| 525 | |
| 526 | smbCloud mendukung deployment berbasis Docker tanpa alur setup yang panjang. |
| 527 | |
| 528 | ```bash |
| 529 | # smbCloud auto-detect Dockerfile |
| 530 | $ cat Dockerfile |
| 531 | FROM node:18-alpine |
| 532 | WORKDIR /app |
| 533 | COPY . . |
| 534 | RUN npm install |
| 535 | CMD ["npm", "start"] |
| 536 | |
| 537 | $ git push smb main |
| 538 | # smbCloud build image dan deploy otomatis |
| 539 | ``` |
| 540 | |
| 541 | **Keunggulan**: |
| 542 | - Tidak perlu menyiapkan Docker registry sendiri untuk alur dasar |
| 543 | - Image bisa dibangun langsung dari `Dockerfile` |
| 544 | - Container dapat diskalakan lewat fitur platform |
| 545 | - Monitoring dasar sudah tersedia |
| 546 | |
| 547 | ## Troubleshooting Common Issues |
| 548 | |
| 549 | ### Container Exits Immediately |
| 550 | |
| 551 | ```bash |
| 552 | # Check logs |
| 553 | docker logs <container_id> |
| 554 | |
| 555 | # Run interactively untuk debug |
| 556 | docker run -it myapp /bin/sh |
| 557 | ``` |
| 558 | |
| 559 | ### Port Already in Use |
| 560 | |
| 561 | ```bash |
| 562 | # Find process using port |
| 563 | lsof -i :8080 # Mac/Linux |
| 564 | netstat -ano | findstr :8080 # Windows |
| 565 | |
| 566 | # Kill process atau use different port |
| 567 | docker run -p 8081:3000 myapp |
| 568 | ``` |
| 569 | |
| 570 | ### Out of Disk Space |
| 571 | |
| 572 | ```bash |
| 573 | # Remove unused images |
| 574 | docker image prune -a |
| 575 | |
| 576 | # Remove unused volumes |
| 577 | docker volume prune |
| 578 | |
| 579 | # Clean everything |
| 580 | docker system prune -a --volumes |
| 581 | ``` |
| 582 | |
| 583 | ## Kesimpulan |
| 584 | |
| 585 | Docker membantu developer menjalankan aplikasi dengan lingkungan yang lebih konsisten. Itu sebabnya Docker sering dipakai untuk development, testing, CI/CD, sampai deployment. |
| 586 | |
| 587 | Kalau Anda baru belajar, tidak perlu langsung memikirkan cluster besar atau arsitektur rumit. Cukup mulai dari satu aplikasi, pahami `Dockerfile`, bedakan image dan container, lalu coba jalankan beberapa service dengan Compose. Setelah itu, konsep yang lebih lanjut biasanya terasa jauh lebih masuk akal. |