Okay, sekarang kita masuk bahagian yang saya rasa paling exciting dalam homelab — Docker! Kalau tadi kita belajar virtualisasi (komputer dalam komputer), Docker pula macam “kotak berasingan” untuk setiap aplikasi. Setiap kotak ada semua yang app tu perlukan, dan kotak-kotak ni tak kacau antara satu sama lain.
Apa yang anda akan belajar:
hello-world
Nota Beginner: Cara paling mudah memahami Docker ialah anggap setiap service sebagai satu folder yang ada satu fail docker-compose.yml dan satu tempat simpan data. Itu sahaja. Jangan overthink.
docker-compose.yml
ports
volumes
logs
Docker mengubah cara ramai orang memasang dan mengurus aplikasi. Dulu, nak install satu app kena install macam-macam dependency, configure banyak benda, dan kadang-kadang satu app boleh rosakkan app lain.
Dengan Docker, semua tu dah settle. Setiap app jalan dalam container sendiri, dengan dependency sendiri. Bersih, kemas, dan mudah diulang semula jika berlaku masalah.
Docker adalah platform container yang membungkus aplikasi bersama semua kebergantungannya ke dalam unit yang dipanggil container. Setiap container berjalan secara terpencil tetapi berkongsi kernel OS host.
Ini soalan yang ramai orang tanya. Mari kita tengok perbezaan dia:
Mesin Maya: Docker: ┌──────────────┐ ┌──────┐ ┌──────┐ ┌──────┐ │ Aplikasi A │ │App A │ │App B │ │App C │ ├──────────────┤ ├──────┤ ├──────┤ ├──────┤ │ OS Penuh │ │ Libs │ │ Libs │ │ Libs │ ├──────────────┤ └──────┘ └──────┘ └──────┘ │ Hypervisor │ ┌─────────────────────────┐ ├──────────────┤ │ Docker Engine │ │ OS Hos │ ├─────────────────────────┤ ├──────────────┤ │ OS Hos │ │ Perkakasan │ ├─────────────────────────┤ └──────────────┘ │ Perkakasan │ └─────────────────────────┘ Saiz: GB Saiz: MB Boot: Minit Boot: Saat
Nampak tak perbezaan dia? VM perlu satu OS penuh untuk setiap instance. Docker hanya perlu app dan library dia sahaja. Sebab tu Docker jauh lebih ringan dan laju.
Nota Beginner: Analogi mudah — Image macam resipi, Container macam masakan yang dah siap dimasak. Satu resipi boleh buat banyak masakan, dan setiap masakan berdiri sendiri.
Ikut langkah ni satu per satu. Copy paste je arahan di bawah.
# Buang versi lama sudo apt remove docker docker-engine docker.io containerd runc # Pasang kebergantungan sudo apt update sudo apt install -y ca-certificates curl gnupg # Tambah kunci GPG rasmi Docker 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 sudo chmod a+r /etc/apt/keyrings/docker.gpg # Tambah repositori echo \ "deb [arch=$(dpkg --print-architecture) \ signed-by=/etc/apt/keyrings/docker.gpg] \ https://download.docker.com/linux/ubuntu \ $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null # Pasang Docker sudo apt update sudo apt install -y docker-ce docker-ce-cli \ containerd.io docker-buildx-plugin docker-compose-plugin # Tambah pengguna ke kumpulan docker sudo usermod -aG docker $USER
Log keluar dan log masuk semula untuk perubahan kumpulan berkuat kuasa.
Nota Beginner: Arahan usermod -aG docker $USER membolehkan anda guna Docker tanpa sudo setiap kali. Penting untuk kemudahan. Tapi anda perlu log out dan log in balik (atau reboot) untuk ia berkuat kuasa.
usermod -aG docker $USER
sudo
# Periksa versi docker --version docker compose version # Jalankan container ujian docker run hello-world
Kalau anda nampak mesej “Hello from Docker!” — tahniah, Docker dah berjaya dipasang!
Docker Compose membolehkan anda mendefinisikan dan menjalankan aplikasi Docker berbilang container menggunakan fail YAML. Ini cara yang paling popular untuk deploy service dalam homelab.
# Contoh asas docker-compose.yml services: nama-perkhidmatan: image: nama-image:tag container_name: nama-kontena ports: - "port-hos:port-kontena" volumes: - ./data-tempatan:/data-kontena environment: - VARIABLE=nilai restart: unless-stopped networks: - rangkaian-nama networks: rangkaian-nama: driver: bridge
Tip dari saya — sentiasa guna restart: unless-stopped supaya container auto-start bila server reboot. Satu benda kecil tapi sangat penting.
restart: unless-stopped
Ini arahan yang anda akan guna setiap hari. Hafal je lima arahan pertama, yang lain boleh rujuk balik bila perlu.
# Mulakan semua perkhidmatan docker compose up -d # Hentikan semua perkhidmatan docker compose down # Lihat log docker compose logs -f # Lihat status docker compose ps # Mulakan semula perkhidmatan docker compose restart nama-perkhidmatan # Tarik imej terkini docker compose pull # Bina semula dan mulakan docker compose up -d --build
Nota Beginner: Flag -d bermaksud “detached” — container jalan di background. Flag -f pada logs bermaksud “follow” — log keluar secara live. Tekan Ctrl+C untuk keluar dari mod follow.
-d
-f
Ctrl+C
Ini struktur folder yang saya cadangkan. Ia kemas, mudah di-backup, dan mudah dipindahkan ke server lain.
/opt/docker/ ├── docker-compose.yml # Fail utama ├── .env # Pembolehubah persekitaran ├── traefik/ │ ├── traefik.yml │ └── acme.json ├── nextcloud/ │ └── data/ ├── vaultwarden/ │ └── data/ ├── pihole/ │ ├── etc-pihole/ │ └── etc-dnsmasq.d/ ├── gitea/ │ └── data/ ├── grafana/ │ └── data/ ├── homeassistant/ │ └── config/ └── portainer/ └── data/
Fail .env simpan pembolehubah yang digunakan dalam docker-compose.yml. Guna satu tempat untuk semua setting supaya senang diubah.
.env
# .env - Pembolehubah persekitaran PUID=1000 PGID=1000 TZ=Asia/Kuala_Lumpur DOMAIN=lab.local DATA_DIR=/opt/docker
Ini contoh stack homelab yang lengkap. Anda tak perlu deploy semua sekali — pilih mana yang anda perlukan dulu.
# docker-compose.yml - Stack Homelab Lengkap services: # ============================================ # Portainer - Pengurusan Docker # ============================================ portainer: image: portainer/portainer-ce:latest container_name: portainer ports: - "9443:9443" volumes: - /var/run/docker.sock:/var/run/docker.sock - ./portainer/data:/data restart: unless-stopped # ============================================ # Nextcloud - Storan Awan Peribadi # ============================================ nextcloud-db: image: mariadb:latest container_name: nextcloud-db environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASS} MYSQL_DATABASE: nextcloud MYSQL_USER: nextcloud MYSQL_PASSWORD: ${DB_PASS} volumes: - ./nextcloud/db:/var/lib/mysql restart: unless-stopped nextcloud: image: nextcloud:latest container_name: nextcloud ports: - "8080:80" environment: MYSQL_HOST: nextcloud-db MYSQL_DATABASE: nextcloud MYSQL_USER: nextcloud MYSQL_PASSWORD: ${DB_PASS} NEXTCLOUD_TRUSTED_DOMAINS: "nextcloud.${DOMAIN}" volumes: - ./nextcloud/data:/var/www/html depends_on: - nextcloud-db restart: unless-stopped # ============================================ # Vaultwarden - Pengurus Kata Laluan # ============================================ vaultwarden: image: vaultwarden/server:latest container_name: vaultwarden ports: - "8000:80" environment: DOMAIN: "https://vault.${DOMAIN}" SIGNUPS_ALLOWED: "true" volumes: - ./vaultwarden/data:/data restart: unless-stopped # ============================================ # Jellyfin - Server Media # ============================================ jellyfin: image: jellyfin/jellyfin:latest container_name: jellyfin ports: - "8096:8096" volumes: - ./jellyfin/config:/config - ./jellyfin/cache:/cache - /path/to/media:/media:ro restart: unless-stopped # ============================================ # Home Assistant - Automasi Rumah # ============================================ homeassistant: image: ghcr.io/home-assistant/home-assistant:stable container_name: homeassistant ports: - "8123:8123" volumes: - ./homeassistant/config:/config - /etc/localtime:/etc/localtime:ro restart: unless-stopped # ============================================ # Gitea - Git Hosting # ============================================ gitea: image: gitea/gitea:latest container_name: gitea ports: - "3000:3000" - "2222:22" environment: USER_UID: ${PUID} USER_GID: ${PGID} volumes: - ./gitea/data:/data - /etc/timezone:/etc/timezone:ro - /etc/localtime:/etc/localtime:ro restart: unless-stopped # ============================================ # Uptime Kuma - Pemantauan # ============================================ uptime-kuma: image: louislam/uptime-kuma:latest container_name: uptime-kuma ports: - "3001:3001" volumes: - ./uptime-kuma/data:/app/data restart: unless-stopped # ============================================ # Watchtower - Kemas Kini Automatik # ============================================ watchtower: image: containrrr/watchtower:latest container_name: watchtower volumes: - /var/run/docker.sock:/var/run/docker.sock environment: WATCHTOWER_CLEANUP: "true" WATCHTOWER_SCHEDULE: "0 0 4 * * *" TZ: ${TZ} restart: unless-stopped
Nota Beginner: Saya cadangkan mulakan dengan Portainer (untuk urus Docker secara visual) dan Uptime Kuma (untuk pantau service). Dua ni ringan dan sangat berguna dari awal lagi.
Ini arahan harian yang anda perlu tahu. Tak perlu hafal semua — bookmark page ni dan rujuk bila perlu.
# Senarai container berjalan docker ps # Senarai semua container (termasuk berhenti) docker ps -a # Lihat log container docker logs -f nama-kontena # Masuk ke dalam container docker exec -it nama-kontena /bin/bash # Statistik sumber container docker stats # Buang container dan imej yang tidak digunakan docker system prune -a # Periksa penggunaan storan Docker docker system df
Rangkaian Docker membolehkan container berkomunikasi antara satu sama lain dengan selamat.
# Cipta rangkaian khusus docker network create homelab-net # Senarai rangkaian docker network ls # Periksa rangkaian docker network inspect homelab-net
Konfigurasi rangkaian dalam docker-compose.yml:
services: app: networks: - frontend - backend networks: frontend: driver: bridge backend: driver: bridge internal: true # Tiada akses internet
Nota Beginner: Network internal: true bermaksud container dalam rangkaian tu tak boleh akses internet. Ini bagus untuk database — anda tak mahu database anda boleh “bercakap” dengan internet, kan?
internal: true
Volume adalah cara Docker simpan data yang kekal walaupun container dihapuskan. Ini sangat penting — tanpa volume, semua data hilang bila container dibuang.
# Cipta volume bernama docker volume create data-nextcloud # Senarai volumes docker volume ls # Buang volume yang tidak digunakan docker volume prune
Jenis mount:
volumes: # Bind mount (direktori host) - ./data:/app/data # Named volume (diuruskan Docker) - data-volume:/app/data # Read-only mount - ./config:/app/config:ro
Tip dari saya — guna bind mount (./data:/app/data) untuk homelab sebab senang di-backup. Anda nampak terus folder tu dalam filesystem host.
./data:/app/data
Keselamatan penting walaupun dalam homelab. Biasakan amalan ni dari awal supaya bila anda kerja dalam production nanti, dah jadi habit.
services: app: user: "1000:1000"
services: app: deploy: resources: limits: cpus: '2' memory: 1G
Gunakan imej rasmi dan dipercayai sahaja
Kemas kini imej secara berkala:
docker compose pull && docker compose up -d
# ELAKKAN ini melainkan benar-benar perlu volumes: - /var/run/docker.sock:/var/run/docker.sock
# .env DB_ROOT_PASS=kata_laluan_sangat_selamat DB_PASS=kata_laluan_pangkalan_data
Nota Beginner: Docker socket (docker.sock) memberi akses penuh kepada Docker Engine. Hanya service yang memang perlu (seperti Portainer atau Watchtower) patut dapat akses ini. Jangan bagi semua container akses socket.
docker.sock
Jangan risau kalau container tak jalan. Ini normal, terutama pada awalnya. Saya pun masih troubleshoot Docker sampai sekarang. Berikut adalah masalah biasa dan cara selesaikannya.
Container tidak dapat bermula:
# Periksa log — ini SENTIASA langkah pertama docker logs nama-kontena # Periksa konfigurasi docker inspect nama-kontena
Port sudah digunakan:
# Cari proses yang menggunakan port sudo lsof -i :8080 sudo ss -tlnp | grep 8080
Kehabisan ruang storan:
# Periksa penggunaan docker system df # Bersihkan docker system prune -a --volumes
Masalah kebenaran fail:
# Tetapkan pemilikan sudo chown -R 1000:1000 ./data # Atau gunakan PUID/PGID dalam environment
Nota Beginner: 90% masalah Docker boleh diselesaikan dengan membaca log (docker logs nama-kontena). Biasakan diri baca log — ia macam “doktor” yang beritahu anda apa yang tak kena.
docker logs nama-kontena
Dalam bab ini, kita telah belajar tentang:
Docker adalah salah satu kemahiran paling bernilai yang anda boleh belajar dalam homelab. Hampir semua syarikat IT moden guna container dalam satu bentuk atau yang lain.
Jangan rasa perlu kuasai semua sekali gus. Mulakan dengan satu service, fahamkan flow dia, dan tambah service lain bila dah selesa. Satu langkah pada satu masa!
Seterusnya, kita akan masuk bahagian Docker lanjutan — reverse proxy, health check, backup, dan macam-macam lagi yang akan buat setup anda lebih mantap.