Ringkasan Utama
Belajar Docker dari nol cukup lewat enam langkah: tulis Dockerfile, jalankan docker build untuk membuat image, jalankan docker run dengan flag -p untuk membuat container dan membuka port, lihat isinya dengan docker ps, docker logs, dan docker exec, lalu simpan data dengan volume agar tidak hilang saat container dihapus.
Kamu sudah install Docker, lalu mengetik docker run dan terminal mengeluarkan satu baris panjang berisi huruf acak. Kamu buka browser, localhost tidak merespons. Kamu ketik ulang perintahnya, dan sekarang muncul error bahwa nama container sudah dipakai. Hampir semua orang yang belajar Docker dari nol berhenti di titik ini, bukan karena Docker sulit, tetapi karena tidak ada yang menjelaskan apa yang sebenarnya terjadi di balik setiap perintah.
Panduan ini membangun satu aplikasi Node.js kecil dan membawanya dari Dockerfile sampai container yang datanya tahan hapus. Setiap perintah saya cocokkan dengan dokumentasi resmi Docker, dan pola Dockerfile-nya sama dengan yang dipakai situs ini sendiri. Output yang saya tulis hanya yang memang pasti keluar dari kode di bawah; untuk ID dan waktu, hasil di komputermu akan berbeda.
Mau versi animasinya? Pelajaran gratis kami menjelaskan layer dan build cache secara visual: Belajar Docker untuk pemula: image, container, dan Dockerfile. Artikel ini adalah sisi prakteknya: kamu mengetik, menjalankan, dan melihat sendiri hasilnya.
Yang kamu butuhkan
Tidak banyak. Semua langkah di bawah berjalan di Linux, macOS, maupun Windows selama Docker aktif.
- Docker terpasang dan berjalan (Docker Desktop di macOS atau Windows, Docker Engine di Linux).
- Terminal dan satu editor teks apa saja. Kamu tidak perlu install Node.js di komputermu, karena Node.js ada di dalam image.
- Sekitar 30 menit, dan folder kosong bernama belajar-docker.
docker --version
# Expect one line starting with: Docker version ...
# "command not found" or "cannot connect to the Docker daemon" means
# Docker is not installed or not running yet. Fix that first.Cek dulu bahwa Docker hidup. Kalau perintah di atas gagal, selesaikan itu dulu; langkah-langkah berikutnya tidak akan jalan tanpa Docker daemon yang aktif.
Langkah 1: Pahami image dan container lewat tiga perintah
Image adalah paket read-only berisi aplikasi beserta semua yang dibutuhkannya. Container adalah image yang sedang dijalankan. Satu image bisa menjadi banyak container, sama seperti satu file installer bisa dijalankan berkali-kali. Cara paling mudah mengingatnya: perintah yang kamu ketik menentukan kamu sedang berurusan dengan yang mana.
| Kamu ingin | Perintah | Hasilnya |
|---|---|---|
| Membuat image dari Dockerfile | docker build | Sebuah image bernama belajar-docker:v1 |
| Menjalankan image | docker run | Sebuah container yang berjalan |
| Melihat apa yang berjalan | docker ps | Daftar container, bukan image |
Kalau kamu bingung di langkah berikutnya, kembali ke tabel ini. Dockerfile dan image ada di sisi build; container dan port ada di sisi run.
Langkah 2: Tulis aplikasi kecil dan Dockerfile
Buat dua file di folder belajar-docker. Aplikasinya menghitung berapa kali ia dikunjungi dan menyimpan angkanya di /data/count.txt. Penghitung ini kita pakai di Langkah 6 untuk melihat kenapa data container bisa hilang.
// belajar-docker/server.js
const http = require("node:http");
const fs = require("node:fs");
const FILE = "/data/count.txt";
http
.createServer((req, res) => {
let n = 0;
try {
n = Number(fs.readFileSync(FILE, "utf8")) || 0;
} catch {
// first visit: the file does not exist yet
}
n += 1;
fs.writeFileSync(FILE, String(n));
console.log("visit " + n);
res.end("Kunjungan ke-" + n + "\n");
})
// 0.0.0.0, not 127.0.0.1: inside a container, 127.0.0.1 is the container
// itself, so a port you publish could never reach the server.
.listen(3000, "0.0.0.0");# belajar-docker/Dockerfile
FROM node:22-alpine
WORKDIR /app
# /data is where the counter file lives; step 6 mounts a volume here.
RUN mkdir /data
COPY server.js .
EXPOSE 3000
CMD ["node", "server.js"]Baca Dockerfile dari atas ke bawah: mulai dari image dasar node:22-alpine, pindah ke folder /app, salin server.js, catat bahwa aplikasi memakai port 3000, lalu tentukan perintah yang dijalankan saat container hidup. Dokumentasi menegaskan bahwa EXPOSE hanya mencatat port dan tidak membukanya; membuka port adalah urusan docker run di Langkah 4.
# Wrong: single quotes. The reference requires double quotes in the JSON array.
CMD ['node', 'server.js']
# Right:
CMD ["node", "server.js"]Pola yang sama dipakai Dockerfile situs ini: WORKDIR /app, port 3000 di dalam container, dan CMD dalam bentuk array JSON, yaitu CMD [node, server.js] dengan tanda kutip ganda. Bedanya, Dockerfile situs ini punya beberapa stage supaya image akhirnya kecil. Itu topik yang lebih lanjut, dibahas di artikel best practice di akhir tulisan ini.
Langkah 3: Build image pertamamu
Jalankan docker build dari dalam folder belajar-docker. Titik di akhir perintah bukan hiasan: itu build context, yaitu folder yang dikirim ke Docker. Lupa titik itu adalah salah satu error pertama yang dialami pemula.
cd belajar-docker
# -t gives the image a name:tag. The trailing "." is the build context:
# the current folder, which is sent to Docker.
docker build -t belajar-docker:v1 .
docker image ls belajar-docker
# Expect one row: REPOSITORY belajar-docker, TAG v1Saat build berjalan, kamu akan melihat satu langkah progres untuk setiap instruksi di Dockerfile. Pertama kali, Docker mengunduh image node:22-alpine, jadi butuh waktu lebih lama. Jalankan perintah yang sama sekali lagi dan Docker memakai cache untuk langkah yang tidak berubah, itulah kenapa build kedua jauh lebih cepat.
Langkah 4: Jalankan container dan buka port-nya
docker run mengubah image menjadi container. Tiga flag di bawah adalah yang paling sering kamu pakai. Flag -d menjalankan container di background dan mencetak ID-nya, --name memberimu nama yang mudah diketik, dan -p menghubungkan port di komputermu ke port di dalam container.
# -d run in the background and print the container ID
# --name a name you can type instead of the random ID
# -p HOST:CONTAINER traffic to host port 8080 goes to container port 3000
docker run -d --name belajar-app -p 8080:3000 belajar-docker:v1
curl http://localhost:8080
# Kunjungan ke-1
curl http://localhost:8080
# Kunjungan ke-2# Wrong: host and container swapped. Nothing listens on 8080 inside the container.
docker run -d --name belajar-app -p 3000:8080 belajar-docker:v1
# Right: host side first, container side second.
docker run -d --name belajar-app -p 8080:3000 belajar-docker:v1
# Same thing, but only this machine can reach it (what this site does on its VPS).
docker run -d --name belajar-app -p 127.0.0.1:8080:3000 belajar-docker:v1Urutannya selalu port host dulu, lalu port container. Kalau tidak menulis alamat IP, Docker membuka port itu di semua interface, artinya bisa dijangkau dari luar komputermu. Itu sebabnya situs ini di VPS memakai bentuk 127.0.0.1 di depan port, sehingga hanya nginx di mesin yang sama yang bisa mengaksesnya.
Kalau aplikasimu mendengarkan di 127.0.0.1 di dalam container, port yang kamu buka tidak akan pernah sampai, karena 127.0.0.1 di sana berarti container itu sendiri. Pakai 0.0.0.0 di dalam container, lalu batasi akses dari luar lewat -p 127.0.0.1:8080:3000. Dockerfile situs ini juga mengatur HOSTNAME ke 0.0.0.0 karena alasan yang sama.
Langkah 5: Intip container dengan ps, logs, dan exec
Tiga perintah ini adalah alat debugging harianmu. docker ps menunjukkan container yang berjalan, docker logs menampilkan apa yang dicetak aplikasi, dan docker exec menjalankan perintah baru di dalam container yang sedang hidup. Flag -it pada exec memberimu terminal interaktif; dokumentasi docker exec memakai sh sebagai contoh, dan sh pasti ada di image Alpine.
docker ps
# Columns: CONTAINER ID, IMAGE, COMMAND, CREATED, STATUS, PORTS, NAMES
# One row: belajar-app, STATUS Up ...
docker ps -a # -a also lists stopped containers
docker logs belajar-app
# visit 1
# visit 2
docker logs -f --tail 20 belajar-app # -f follows, Ctrl+C to stop following
docker exec -it belajar-app sh
cat /data/count.txt
# 2
exitDua kebiasaan penting. Pertama, kalau container tidak muncul di docker ps, tambahkan -a sebelum menyimpulkan bahwa ia hilang; mungkin ia sudah berhenti. Kedua, docker exec hanya bekerja pada container yang prosesnya masih berjalan, jadi untuk container yang crash, baca docker logs saja.
Langkah 6: Simpan data dengan volume
Semua yang ditulis aplikasi ke dalam container disimpan di layer tulis milik container itu. Hapus container, dan datanya ikut hilang. Coba sendiri: urutan di bawah menghapus container lalu menjalankannya lagi, dan penghitungnya kembali ke 1.
# 1. Without a volume: the counter dies with the container.
docker rm -f belajar-app
docker run -d --name belajar-app -p 8080:3000 belajar-docker:v1
curl http://localhost:8080
# Kunjungan ke-1 <- the count started over
# 2. With a named volume mounted at /data.
docker rm -f belajar-app
docker run -d --name belajar-app -p 8080:3000 -v belajar-data:/data belajar-docker:v1
curl http://localhost:8080
# Kunjungan ke-1
curl http://localhost:8080
# Kunjungan ke-2
docker rm -f belajar-app
docker run -d --name belajar-app -p 8080:3000 -v belajar-data:/data belajar-docker:v1
curl http://localhost:8080
# Kunjungan ke-3 <- the number survived the containerSolusinya volume. Dokumentasi Docker menyebutkan bahwa isi volume berada di luar siklus hidup sebuah container, jadi data tetap ada walau containernya dihapus. Bentuk -v nama-volume:/path memasang volume bernama ke folder di dalam container; Docker membuat volumenya otomatis kalau belum ada.
# Clean up when you are done
docker rm -f belajar-app
docker volume rm belajar-dataPola ini persis yang dipakai situs ini di production: file compose-nya memasang volume bernama next-image-cache supaya cache gambar yang sudah dioptimasi tidak hilang setiap kali container diganti saat deploy. Perhatikan juga bahwa docker rm tanpa flag tambahan tidak menghapus volume bernama; kamu harus menjalankan docker volume rm sendiri.
Error umum dan cara memperbaikinya
Enam gejala ini menghabiskan sebagian besar waktu pemula. Cocokkan pesan di terminalmu dengan kolom pertama.
| Gejala | Penyebab | Perbaikan |
|---|---|---|
| Pesan bind failed: port is already allocated | Port 8080 di komputermu sudah dipakai container lain, termasuk container lama yang belum dihapus. | Cek docker ps -a, hapus yang lama dengan docker rm -f nama, atau pakai port host lain seperti -p 8081:3000. |
| Pesan Conflict: the container name is already in use | Container lama, walau sudah berhenti, masih memegang nama belajar-app sampai dihapus. | docker rm -f belajar-app, lalu jalankan docker run lagi. |
| curl menolak koneksi atau koneksinya terputus | Mapping port tertukar (-p 3000:8080), atau aplikasi mendengarkan di 127.0.0.1 di dalam container. | Tulis -p port-host:port-container, dan buat aplikasi mendengarkan di 0.0.0.0. |
| Container langsung berstatus Exited di docker ps -a | Proses utama selesai atau crash. Container hidup hanya selama proses utamanya hidup. | Baca docker logs nama dan perbaiki errornya; periksa juga CMD di Dockerfile. |
| Tidak bisa terhubung ke Docker daemon | Docker Desktop atau service Docker belum berjalan. | Buka Docker Desktop, atau di Linux jalankan service Docker, lalu coba docker --version dan docker ps lagi. |
| Data atau penghitung kembali ke awal setelah container dihapus | Data ditulis ke layer tulis container, bukan ke volume. | Tambahkan -v nama-volume:/path saat docker run, seperti di Langkah 6. |
Aturan umumnya: saat container bermasalah, jalankan docker ps -a lalu docker logs nama sebelum mengubah apa pun. Hampir semua jawabannya ada di dua perintah itu.
Checklist sebelum lanjut
- Saya bisa menjelaskan bahwa docker build membuat image dan docker run membuat container.
- Saya tahu urutan -p adalah port host dulu, lalu port container.
- Saya bisa memakai docker ps -a, docker logs, dan docker exec -it untuk melihat isi container.
- Saya paham data tanpa volume hilang saat container dihapus.
- Saya sudah membersihkan dengan docker rm -f belajar-app dan docker volume rm belajar-data.
Belajar lebih dalam
Kamu sudah punya container pertama. Untuk memahami kenapa urutan instruksi Dockerfile menentukan kecepatan build, buka pelajaran gratis Belajar Docker untuk pemula: image, container, dan Dockerfile. Setelah itu, baca best practice Docker containerizationuntuk merapikan image sebelum dipakai di server, dan Docker Compose Watch untuk development lokalkalau kamu sudah bosan membangun ulang image setiap kali mengubah satu baris kode.
Satu aturan untuk dibawa pulang: image adalah apa yang kamu build, container adalah apa yang kamu run, dan apa pun yang penting harus tinggal di volume, bukan di dalam container. Dari sini, Docker Compose adalah langkah wajar berikutnya.

