•
5 min read

Cara Cepat Mengatasi Port Conflict pada Docker di macOS

Identifikasi penyebab port conflict di Docker macOS dan perbaiki dengan cepat menggunakan lsof, netstat, dan Docker CLI.

Pendahuluan

Docker di macOS sering gagal bind ke port karena layanan lain menggunakan port yang sama (misalnya, sisa container, sistem, atau app lain). Pesan error seperti “EADDRINUSE” atau “Cannot start service: address already in use” menunjukkan konflik. Artikel ini menjelaskan langkah-langkah untuk menemukan dan melepaskan port yang digunakan, lalu mengonfigurasi Docker untuk menghindari konflik berulang.

Deteksi port yang sibuk

Gunakan lsof atau netstat untuk menemukan PID yang memegang port:

Terminal window
# Contoh: port 8080
lsof -i :8080
# Output (contoh):
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# docker 1234 user 9u IPv4 0x... 0t0 TCP *:8080 (LISTEN)

Jika lsof tidak tersedia, gunakan netstat:

Terminal window
netstat -tulpn | grep :8080

Hasil tipikal:

TCP 0.0.0.0:8080 0.0.0.0:0 LISTEN 1234

Kedua perintah menampilkan PID dan nama program. Di macOS, lsof adalah pilihan utama.

Hentikan proses yang menggunakan port

Setelah mendapatkan PID, hentikan proses tersebut. Contoh untuk container Docker yang tersisa:

Terminal window
# Hentikan container yang sedang berjalan dengan nama "conflicting_container"
docker stop conflicting_container
# Hapus container yang tidak diperlukan
docker rm conflicting_container

Jika itu adalah daemon sistem (misalnya, nginx), edit konfigurasi atau gunakan Homebrew untuk uninstall:

Terminal window
# Contoh untuk nginx yang diinstal via Homebrew
brew services stop nginx
brew uninstall nginx

Setelah layanan berhenti, verifikasi port bebas:

Terminal window
lsof -i :8080
# Tidak ada output → port bebas

Atur Docker untuk menggunakan port unik

Docker Desktop untuk macOS menggunakan VM internal. Secara default, Docker mengizinkan penggunaan kembali port setelah container berhenti, tetapi sisa container atau proses binding ke port host akan menyebabkan konflik berulang.

Gunakan label publish yang eksplisit atau ports di docker-compose.yml:

version: "3.9"
services:
web:
image: nginx:alpine
ports:
- "8080:80" # bind host 8080 → container 80
labels:
- "com.docker.compose.staging=false"

Jika Anda memerlukan port acak untuk menghindari konflik di masa depan, gunakan placeholder ${{ random }} di CI atau buat rentang port dinamis melalui skrip:

Terminal window
# Pilih port bebas secara acak antara 49152–65535
FREE_PORT=$(shuf -i 49152-65535 -n 1)
docker run -p ${FREE_PORT}:80 nginx
echo "Container menggunakan port ${FREE_PORT}"

Trade-off dan batasan

PendekatanKelebihanKekurangan
Hentikan layanan yang menggunakan portSegera menyelesaikan konflikMungkin mengganggu aplikasi lain
Gunakan docker-compose dengan pemetaan port eksplisitMenjamin binding yang dapat diulangMemerlukan file compose tambahan
Port acakMenghilangkan kebutuhan untuk mengelola konflikSulit untuk dokumentasi dan debugging

Docker di macOS juga mendukung macOS IP 127.0.0.1:. Jika Anda memerlukan binding ke antarmuka host, gunakan 0.0.0.0 di container, tetapi ingat bahwa Docker VM tidak mengekspos antarmuka host secara langsung.

Pemecahan Masalah

Error: EADDRINUSE

Terminal window
docker run -p 8080:80 nginx
# Output (diringkas):
# Error response from daemon: "Driver networking endpoint "bridge" does not have a free port to allocate"

Penyebab: Port 8080 sudah digunakan oleh proses di host (misalnya, sisa container, mongod, atau vscode).

Solusi: Jalankan lsof -i :8080, hentikan proses yang teridentifikasi, lalu jalankan container lagi.

Error: Cannot start service: address already in use

Terminal window
docker compose up -d
# Output (diringkas):
# Service "db" failed to start: address already in use

Penyebab: Container lain (mungkin dari docker compose sebelumnya) masih memegang port 3306.

Solusi: Jalankan docker ps -a, temukan container yang berhenti, lalu docker rm <container>.

Error: socket: address already in use

Terminal window
lsof -i :3000
# Output (contoh):
# COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
# python 4567 user 9u IPv4 0x... 0t0 TCP *:3000 (LISTEN)

Penyebab: Skrip Python yang berjalan di host menggunakan port 3000.

Solusi: Hentikan skrip (kill -9 4567) atau ubah skrip untuk menggunakan port bebas.

Port tetap konflik setelah restart

Jika port masih sibuk setelah container dihapus, periksa LaunchDaemons atau system.ini yang mungkin memulai layanan secara otomatis. Gunakan brew services list untuk menemukan daemon yang dikelola Homebrew.

Jika tidak ada, jalankan sudo kill -9 $(lsof -t -i :<PORT>) untuk menghapus paksa, lalu verifikasi:

Terminal window
lsof -i :<PORT>
# Tidak ada output → port bebas

Ringkasan

  • Gunakan lsof -i :<PORT> untuk menemukan proses yang menggunakan port.
  • Hentikan atau hapus proses tersebut (docker stop/rm, brew services stop).
  • Verifikasi port bebas sebelum menjalankan container lagi.
  • Gunakan pemetaan port eksplisit di docker-compose.yml atau pilih port acak untuk menghindari konflik berulang.

Port conflict di Docker macOS dapat diperbaiki dengan cepat menggunakan langkah-langkah di atas, dan konfigurasi yang tepat mencegah masalah ini muncul kembali.

Found this article helpful? Share it