Docker di Raspberry Pi: Bikin Server IoT Anti Ribet

Pernah install Node-RED, InfluxDB, dan Grafana di satu Raspberry Pi, lalu semuanya berantakan karena bentrok versi Python atau Node.js? Atau SD card kamu corrupt dan semua konfigurasi hilang tanpa jejak? Docker menyelesaikan dua masalah itu sekaligus. Dengan container, setiap aplikasi jalan di kotaknya sendiri — terisolasi, mudah dipindah, dan bisa dihapus tanpa meninggalkan sampah di sistem.
Di artikel ini kita akan bahas dulu konsep container sampai benar-benar paham — termasuk pertanyaan yang sering bikin bingung: apakah komputer bisa langsung menjalankan container tanpa Docker? — lalu lanjut ke instalasi Docker di Raspberry Pi, menjalankan container pertama, sampai membangun stack IoT lengkap pakai Docker Compose.
Tiga Cara Komputer Menjalankan Aplikasi
Sebelum menyentuh terminal, kita samakan dulu gambaran besarnya. Anggap Raspberry Pi kamu adalah sebidang tanah, dan aplikasi-aplikasi yang mau kamu jalankan adalah penghuninya. Ada tiga model hunian yang mungkin.
1. Tanpa Docker — semua tinggal di satu rumah dengan dapur bersama
Ini yang kamu lakukan selama ini: sudo apt install, lalu aplikasi terpasang langsung di sistem.
Bayangkan satu rumah besar dengan satu dapur bersama. Semua penghuni masak di kompor yang sama, pakai panci yang sama, dan berbagi satu rak bumbu. Selama penghuninya cuma dua orang dengan selera mirip, aman-aman saja.
Masalah muncul saat selera mereka berbeda. Penghuni A butuh minyak kelapa, penghuni B butuh minyak zaitun, tapi raknya cuma muat satu botol. Salah satu harus mengalah.
Dalam dunia nyata Raspberry Pi, itu terjadi seperti ini: Node-RED butuh Node.js versi 18, sementara aplikasi dashboard kamu butuh Node.js versi 20. Kamu update Node.js demi dashboard, Node-RED langsung mogok. Ini yang disebut dependency hell, dan hampir semua orang yang main Raspberry Pi pernah kena.
Model ini tetap punya kelebihan: paling ringan, tanpa lapisan tambahan apa pun, dan akses ke hardware seperti GPIO, kamera, atau port serial berjalan mulus tanpa konfigurasi khusus. Untuk project yang cuma butuh satu-dua aplikasi, install langsung masih pilihan paling waras.
2. Dengan Virtual Machine — bangun rumah utuh di dalam tanah yang sama
Solusi klasik untuk dependency hell adalah memberi tiap aplikasi rumahnya sendiri. Virtual machine melakukan persis itu: membangun rumah lengkap dari nol — pondasi, dinding, atap, meteran listrik, dapur pribadi — di atas tanah yang sama.
Secara teknis, setiap VM membawa sistem operasi lengkap dengan kernel-nya sendiri. Ada perangkat lunak bernama hypervisor yang bertugas membagi hardware fisik (CPU, RAM, disk) ke rumah-rumah virtual itu.
Isolasinya luar biasa kuat. Satu VM boleh hancur berantakan tanpa mengganggu yang lain. Tapi harganya mahal: setiap rumah butuh pondasi sendiri. Satu VM Linux minimal makan 512 MB–1 GB RAM hanya untuk hidup, ditambah beberapa gigabyte ruang disk, dan butuh puluhan detik sampai satu menit untuk booting.
Di Raspberry Pi 4 dengan RAM 4 GB, menjalankan dua VM saja sudah membuatnya megap-megap. Sisa tenaga untuk aplikasi yang sebenarnya kamu butuhkan tinggal sedikit.
3. Dengan container — kamar kos, bukan rumah
Container mengambil jalan tengah yang cerdas. Alih-alih membangun rumah utuh, ia menyekat rumah yang sudah ada menjadi kamar-kamar kos.
Setiap kamar punya pintu, kunci, lemari, dan isi yang sepenuhnya milik penghuninya. Dari dalam kamar, penghuni merasa punya tempat sendiri dan tidak tahu-menahu isi kamar sebelah. Tapi pondasi, atap, dan instalasi listriknya? Dipakai bersama.
“Pondasi bersama” itu adalah kernel Linux. Container tidak membawa kernel sendiri — ia meminjam kernel milik Raspberry Pi kamu. Yang dipisahkan hanyalah hal-hal di lapisan atas: filesystem, daftar proses, konfigurasi jaringan, dan nama host.
Karena tidak perlu membangun pondasi, container hidup dalam hitungan detik dan hanya memakan RAM sebesar aplikasi di dalamnya. Container Node-RED cukup puluhan megabyte. Di Raspberry Pi 4, menjalankan lima sampai delapan container sekaligus itu hal biasa.
Perbandingan singkat
| Aspek | Install langsung | Virtual Machine | Container |
|---|---|---|---|
| Waktu start | — | 30–60 detik | 1–3 detik |
| RAM per unit | Sesuai aplikasi | 512 MB–1 GB+ | Puluhan MB |
| Ukuran di disk | Kecil | Beberapa GB | Puluhan–ratusan MB |
| Kernel | Milik host | Punya sendiri | Pinjam milik host |
| Kekuatan isolasi | Tidak ada | Sangat kuat | Cukup kuat |
| Akses GPIO/serial | Paling mudah | Ribet | Perlu opsi tambahan |
| Cocok untuk | 1–2 aplikasi | Uji coba OS berbeda | Banyak service sekaligus |
Apakah Komputer Bisa Langsung Menjalankan Container Tanpa Docker?
Ini pertanyaan yang jarang dijawab dengan jujur di tutorial lain, padahal penting untuk membangun pemahaman yang benar.
Jawabannya: bisa — asalkan sistem operasinya Linux.
Kemampuan membuat container bukan milik Docker. Itu fitur bawaan kernel Linux yang sudah ada bertahun-tahun sebelum Docker lahir. Dua fitur utamanya:
- Namespaces — memisahkan “pandangan” sebuah proses terhadap sistem. Dengan ini, sebuah proses bisa dibuat seolah-olah hanya dia sendiri yang berjalan di komputer, dengan filesystem dan jaringannya sendiri.
- Cgroups (control groups) — membatasi jatah sumber daya. Proses ini boleh pakai maksimal 20% CPU dan 200 MB RAM, misalnya.
Kembali ke analogi kos: kernel Linux adalah tukang bangunan yang punya kemampuan menyekat kamar. Docker bukan tukang bangunannya — Docker adalah pengelola kos yang mengatur segalanya jadi praktis.
Mau bukti bahwa kernel bisa menyekat sendiri tanpa Docker? Coba jalankan ini di terminal Raspberry Pi kamu:
sudo unshare --pid --fork --mount-proc bash
ps aux
exit
Di dalam shell yang muncul, perintah ps aux cuma menampilkan segelintir proses. Semua proses lain yang sedang berjalan di Raspberry Pi kamu — mendadak tidak terlihat. Padahal mereka masih hidup, kamu bisa cek lagi setelah mengetik exit.
Itu sudah isolasi ala container. Tanpa Docker sama sekali. Cuma modal perintah bawaan Linux.
Lalu Docker sebenarnya menambahkan apa?
Kalau kernel sudah bisa menyekat sendiri, kenapa semua orang tetap pakai Docker? Karena melakukannya secara manual itu menyiksa. Untuk membuat satu container “asli” dari nol, kamu harus menyiapkan root filesystem lengkap, mengatur enam jenis namespace satu per satu, menyusun aturan cgroups, mengonfigurasi virtual network interface, lalu menjalankan prosesnya. Puluhan baris perintah, untuk satu aplikasi.
Docker membungkus semua itu jadi satu perintah, sambil menambahkan hal-hal yang tidak disediakan kernel:
- Format image standar — aplikasi beserta seluruh dependency-nya dikemas jadi satu paket yang bisa dipindah ke mesin mana pun.
- Docker Hub — gudang berisi jutaan image siap pakai. Ini alasan kamu bisa menjalankan InfluxDB tanpa membaca dokumentasi instalasinya sama sekali.
- Manajemen jaringan — container bisa saling memanggil pakai nama, tanpa mengurus alamat IP.
- Volume — sistem penyimpanan data yang hidup lebih lama daripada container-nya.
- Restart policy — container otomatis hidup lagi setelah Raspberry Pi reboot.
Dan Docker bukan satu-satunya pilihan. Alternatif yang juga jalan di Raspberry Pi: Podman (tanpa daemon, bisa berjalan tanpa hak root), LXC/LXD (container-nya lebih mirip OS penuh ketimbang aplikasi tunggal), serta containerd + nerdctl untuk yang mau lebih dekat ke lapisan bawah. Perintah Podman bahkan hampir identik dengan Docker, jadi ilmu di artikel ini tetap terpakai.
Jadi, Urutannya Harus Docker Dulu Baru Container?
Secara konsep, tidak. Docker bukan pondasi tempat container berdiri. Docker adalah lapisan pengelola di atas kemampuan yang sudah dimiliki kernel.
Urutan lapisan yang sebenarnya seperti ini, dari bawah ke atas:
┌──────────────────────────────────────────┐
│ Container A │ Container B │ C │ ← aplikasi kamu
├──────────────────────────────────────────┤
│ Docker CLI + Docker Engine │ ← pengelola (bisa diganti Podman)
│ └── containerd → runc │ ← yang benar-benar membuat container
├──────────────────────────────────────────┤
│ Kernel Linux (namespaces + cgroups) │ ← sumber kemampuan isolasi
├──────────────────────────────────────────┤
│ Hardware Raspberry Pi │
└──────────────────────────────────────────┘
Menariknya, Docker versi modern pun sebenarnya tidak membuat container secara langsung. Ia menyerahkan tugas itu ke containerd, yang lalu memanggil runc untuk berbicara dengan kernel. Docker lebih berperan sebagai manajer proyek daripada tukang.
Tapi secara praktis, ya — di Raspberry Pi kamu memang perlu memasang salah satu container engine dulu sebelum bisa mengetik docker run. Bukan karena container mustahil tanpa itu, melainkan karena tidak ada orang waras yang mau menyusun namespace secara manual setiap kali ingin menjalankan aplikasi.
Bandingkan dengan ojek: motor dan tukang ojek sudah ada jauh sebelum ada aplikasi ojek online. Aplikasi itu tidak menciptakan ojek — ia cuma bikin proses memesannya jadi satu ketukan. Docker persis seperti itu terhadap container.
Catatan untuk pengguna Windows dan macOS
Ada satu keanehan yang perlu kamu tahu. Windows dan macOS tidak memakai kernel Linux, jadi mereka tidak punya namespaces dan cgroups. Solusinya, Docker Desktop diam-diam menjalankan sebuah VM Linux kecil di latar belakang, lalu container-nya hidup di dalam VM itu.
Jadi di laptop, urutannya justru: VM dulu, baru container. Ini yang bikin Docker di Windows terasa berat dan lambat.
Di Raspberry Pi, tidak ada drama itu. Sistemnya sudah Linux asli, jadi container berjalan langsung di atas kernel tanpa perantara. Inilah alasan Docker justru terasa ringan dan wajar di perangkat sekecil ini.
Tiga Istilah yang Wajib Kamu Pahami
Sebelum masuk ke praktik, kunci dulu tiga kata ini:
- Image — cetakan atau template aplikasi. Sifatnya read-only dan tidak berubah. Contohnya
nodered/node-red:latest. - Container — image yang sedang berjalan. Satu image bisa dijalankan menjadi banyak container sekaligus.
- Volume — tempat penyimpanan data yang hidup di luar container. Ini kunci supaya datamu tidak ikut hilang saat container dihapus atau di-update.
Analogi cepatnya: image itu resep, container itu masakan yang sudah jadi di piring, volume itu kulkas tempat menyimpan bahannya. Piring boleh dicuci bersih kapan saja, resep tetap ada, isi kulkas tetap aman.
Kenapa Docker Cocok Banget di Raspberry Pi
Install jadi satu baris perintah. Mau coba InfluxDB? Tidak perlu tambah repository, urus dependency, atau baca dokumentasi instalasi selama 20 menit. Satu perintah docker run, selesai.
Tidak ada konflik dependency. Aplikasi A butuh Python 3.9, aplikasi B butuh Python 3.11. Di sistem biasa ini bikin pusing. Di Docker, keduanya bawa Python-nya masing-masing.
Gampang backup dan pindah. Konfigurasi kamu tersimpan dalam file docker-compose.yml dan folder volume. Salin dua hal itu ke Raspberry Pi baru, jalankan satu perintah, dan sistemmu hidup lagi persis seperti sebelumnya.
Rollback aman. Update bikin aplikasi rusak? Ganti tag versi di file compose, jalankan ulang, beres.
Tapi jujur saja, ada juga kekurangannya. Docker menambah overhead penyimpanan (image bisa ratusan MB) dan menambah lapisan abstraksi yang perlu kamu pelajari saat debugging. Untuk project sekali pakai yang sederhana, install langsung mungkin lebih cepat. Docker mulai terasa manfaatnya begitu kamu punya lebih dari dua service yang jalan bareng.
Yang Kamu Butuhkan
- Raspberry Pi 3, 4, 5, atau Zero 2 W (RAM minimal 1 GB, idealnya 2 GB ke atas)
- Raspberry Pi OS versi 64-bit (Bookworm atau lebih baru) — ini penting, banyak image modern sudah tidak menyediakan build 32-bit
- SD card minimal 16 GB, atau lebih baik lagi SSD via USB
- Koneksi internet
- Akses terminal, bisa langsung atau lewat SSH
Cek dulu arsitektur sistem kamu:
uname -m
Kalau outputnya aarch64, kamu pakai 64-bit dan siap lanjut. Kalau armv7l, kamu masih di 32-bit — masih bisa jalan, tapi beberapa image (InfluxDB 2.x, misalnya) tidak tersedia. Saran saya, flash ulang dengan Raspberry Pi OS 64-bit.
Langkah 1: Install Docker
Docker menyediakan script instalasi resmi yang otomatis mendeteksi arsitektur Raspberry Pi kamu.
# Update sistem dulu
sudo apt update && sudo apt upgrade -y
# Download dan jalankan script instalasi resmi Docker
curl -sSL https://get.docker.com | sh
Proses ini butuh 2–5 menit tergantung kecepatan internet dan model Pi kamu. Script tersebut menambahkan repository resmi Docker, memasang Docker Engine, dan mengaktifkan service-nya otomatis saat boot.
Langkah 2: Jalankan Docker Tanpa sudo
Secara default, semua perintah Docker butuh sudo. Melelahkan kalau harus mengetiknya berulang kali.
# Tambahkan user kamu ke grup docker
sudo usermod -aG docker $USER
# Terapkan perubahan grup (atau logout lalu login lagi)
newgrp docker
Perlu dicatat: user yang masuk grup docker praktis punya akses setara root ke sistem. Untuk Raspberry Pi pribadi di jaringan lokal ini wajar saja, tapi jangan lakukan ini di server produksi yang dipakai banyak orang.
Langkah 3: Verifikasi Instalasi
# Cek versi Docker
docker --version
# Jalankan container uji coba
docker run hello-world
Kalau muncul pesan “Hello from Docker!”, instalasi kamu berhasil. Yang barusan terjadi: Docker tidak menemukan image hello-world di lokal, jadi ia mengunduhnya dari Docker Hub, membuat container dari image itu, menjalankannya, lalu container berhenti setelah tugasnya selesai.
Langkah 4: Install Docker Compose
Menjalankan container satu per satu lewat docker run cepat jadi merepotkan begitu kamu punya beberapa service. Docker Compose membiarkan kamu mendefinisikan semuanya dalam satu file YAML.
sudo apt install docker-compose-plugin -y
# Verifikasi
docker compose version
Perhatikan perintahnya: docker compose (pakai spasi), bukan docker-compose (pakai tanda hubung). Versi lama memang memakai tanda hubung, tapi Compose v2 sudah jadi plugin bawaan Docker. Banyak tutorial lama di internet masih pakai format lama — jangan bingung kalau menemukannya.
Langkah 5: Container Pertama yang Benar-Benar Berguna
Mari jalankan Portainer, sebuah dashboard web untuk mengelola container. Dengan ini kamu bisa memantau container lewat browser, bukan hanya terminal.
docker volume create portainer_data
docker run -d \
--name portainer \
--restart unless-stopped \
-p 9443:9443 \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
Mari bedah baris per baris:
-dmenjalankan container di background (detached), jadi terminal kamu tetap bebas dipakai.--name portainermemberi nama yang mudah diingat. Tanpa ini, Docker akan memberi nama acak seperti nostalgic_tesla.--restart unless-stoppedmembuat container otomatis hidup lagi setelah Raspberry Pi reboot atau setelah crash. Untuk perangkat yang jalan 24/7, opsi ini hampir selalu kamu perlukan.-p 9443:9443memetakan port. Format penulisannya port_host:port_container.-v /var/run/docker.sock:/var/run/docker.sockmemberi Portainer akses ke Docker Engine supaya bisa mengelola container lain.-v portainer_data:/datamenyimpan data Portainer di volume, bukan di dalam container.
Buka browser lalu akses https://<IP-Raspberry-Pi>:9443. Browser akan memperingatkan soal sertifikat self-signed — lanjutkan saja, ini normal untuk akses lokal. Buat akun admin, dan kamu langsung melihat dashboard semua container.
Langkah 6: Bangun Stack IoT dengan Docker Compose
Sekarang bagian serunya. Kita akan menjalankan tiga service sekaligus: MQTT broker, Node-RED untuk logika otomasi, dan InfluxDB untuk menyimpan data time-series.
Buat foldernya dulu:
mkdir -p ~/iot-stack/mosquitto/config
cd ~/iot-stack
nano docker-compose.yml
Isi dengan konfigurasi berikut:
services:
mosquitto:
image: eclipse-mosquitto:2
container_name: mosquitto
restart: unless-stopped
ports:
- "1883:1883"
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
nodered:
image: nodered/node-red:latest
container_name: nodered
restart: unless-stopped
ports:
- "1880:1880"
volumes:
- ./nodered-data:/data
environment:
- TZ=Asia/Jakarta
depends_on:
- mosquitto
influxdb:
image: influxdb:2
container_name: influxdb
restart: unless-stopped
ports:
- "8086:8086"
volumes:
- influxdb-data:/var/lib/influxdb2
environment:
- DOCKER_INFLUXDB_INIT_MODE=setup
- DOCKER_INFLUXDB_INIT_USERNAME=admin
- DOCKER_INFLUXDB_INIT_PASSWORD=gantipassword123
- DOCKER_INFLUXDB_INIT_ORG=bisaioti
- DOCKER_INFLUXDB_INIT_BUCKET=sensor
volumes:
influxdb-data:
Mosquitto versi 2 tidak menerima koneksi anonim dari luar secara default, jadi kita perlu file konfigurasi:
nano ~/iot-stack/mosquitto/config/mosquitto.conf
listener 1883
allow_anonymous true
persistence true
persistence_location /mosquitto/data/
Untuk pembelajaran di jaringan lokal, allow_anonymous true masih bisa diterima. Untuk penggunaan serius, aktifkan autentikasi username-password. Bahasan lengkapnya ada di [link ke artikel tentang keamanan MQTT].
Jalankan semuanya:
docker compose up -d
Docker akan mengunduh ketiga image lalu menjalankannya. Cek statusnya:
docker compose ps
Ketiga container seharusnya berstatus running. Akses Node-RED di http://<IP-Pi>:1880 dan InfluxDB di http://<IP-Pi>:8086.
Satu hal yang perlu kamu tahu: container dalam satu file compose bisa saling memanggil pakai nama service-nya. Jadi di dalam Node-RED, alamat broker MQTT-nya cukup ditulis mosquitto, bukan alamat IP. Docker menyediakan DNS internal untuk ini, dan kamu tidak perlu khawatir alamat IP berubah setelah reboot.
Perintah Docker yang Paling Sering Dipakai
docker ps # container yang sedang jalan
docker ps -a # semua container, termasuk yang mati
docker logs -f nodered # lihat log secara real-time
docker exec -it nodered bash # masuk ke dalam container
docker stop nodered # hentikan container
docker restart nodered # restart container
docker stats # pantau CPU dan RAM tiap container
docker compose down # matikan seluruh stack
docker compose pull # unduh versi image terbaru
docker compose up -d # jalankan ulang dengan image baru
docker system df # cek pemakaian disk oleh Docker
docker system prune -a # hapus image dan container tak terpakai
Perintah docker logs adalah teman terbaikmu saat ada yang tidak beres. Sebelum menebak-nebak penyebab masalah, baca lognya dulu.
Troubleshooting
“exec format error” saat menjalankan container
Image yang kamu tarik tidak tersedia untuk arsitektur ARM. Cek dulu dukungan platformnya:
docker manifest inspect nama-image:tag | grep architecture
Cari image yang mendukung arm64 atau arm/v7. Untuk aplikasi populer, biasanya ada versi resmi ARM atau alternatif dari komunitas seperti LinuxServer.io.
Permission denied di folder volume
Sering terjadi pada Node-RED. Container berjalan sebagai user dengan UID tertentu yang tidak punya izin menulis ke folder host:
sudo chown -R 1000:1000 ~/iot-stack/nodered-data
SD card cepat rusak
Log container terus menulis ke disk dan ini menggerus umur SD card. Batasi ukuran log dengan menambahkan konfigurasi ini di setiap service:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
Untuk sistem yang jalan permanen, pertimbangkan boot dari SSD USB. Bahasannya ada di [link ke artikel tentang boot Raspberry Pi dari SSD].
Container restart terus-menerus
Jalankan docker logs nama-container untuk melihat penyebabnya. Biang keladinya biasanya konfigurasi yang salah, port yang sudah dipakai proses lain, atau RAM yang habis. Cek pemakaian memori dengan free -h.
Penutup
Container mengubah cara kita mengelola Raspberry Pi — dari sistem yang makin berantakan setiap kali install aplikasi baru, jadi sistem yang bersih, rapi, dan gampang direplikasi. Kamu sudah belajar konsep dasar container, memasang Docker, menjalankan container tunggal, dan menyusun stack IoT lengkap dengan Docker Compose.
Langkah berikutnya yang layak kamu coba:
- Tambahkan Grafana ke stack untuk memvisualkan data dari InfluxDB
- Pasang Watchtower supaya image container ter-update otomatis
- Bikin image Docker sendiri dari aplikasi buatanmu pakai Dockerfile
- Pasang reverse proxy seperti Nginx Proxy Manager supaya semua service bisa diakses lewat satu domain
Punya pertanyaan atau kendala saat mengikuti panduan ini? Tulis di kolom komentar.
Artikel terkait: [link ke artikel tentang MQTT], [link ke artikel tentang Node-RED untuk pemula], [link ke artikel tentang Raspberry Pi 5]




