/인프라/Docker 'port is already allocated' 30초 진단·복구 런북
인프라docker 포트 충돌port is already allocated

Docker 'port is already allocated' 30초 진단·복구 런북

Docker의 'Bind for 0.0.0.0:XXXX failed: port is already allocated' 에러를 30초 만에 진단하고 복붙 명령으로 복구하는 실전 런북. 좀비 docker-proxy와 잔존 컨테이너 포트 점유를 정확히 해결합니다.

Docker 'port is already allocated' 30초 진단·복구 런북

docker compose up 했더니 또 이 에러

로컬에서 스택을 여러 개 돌리다 보면 하루에도 몇 번씩 이걸 마주칩니다.

TEXT
Error response from daemon: driver failed programming external connectivity
on endpoint web (a1b2c3...): Bind for 0.0.0.0:8080 failed: port is already allocated

여기서 많은 분들이 lsof -i :8080으로 호스트 애플리케이션 프로세스를 찾다가 헛발질을 합니다. 호스트에서 돌리는 nginx·node 프로세스가 범인인 EADDRINUSE 상황과 이 에러는 원인 지점이 다릅니다. 이 글은 호스트 OS의 일반 애플리케이션이 아니라 도커 레이어 — 다른 컨테이너, 잔존 컨테이너, 좀비 docker-proxy, 도커 네트워크 엔드포인트 가 포트를 쥐고 있는 경우에 초점을 맞춥니다.

  • 적용 범위: Docker Engine 20.10 이상, Docker Compose v2(docker compose, 하이픈 없음), Linux 호스트(Ubuntu/RHEL 계열) 기준. macOS/Windows Docker Desktop 차이는 FAQ에서 별도로 다룹니다.
  • 목표: 에러 원문 → 원인 매칭 → 진단 명령 복붙 → 복구 명령 복붙, 이 흐름으로 30초 내 재기동.

바쁘면 아래 매칭표에서 내 증상을 찾고 곧바로 진단·복구 블록으로 내려가세요.

원인 매칭표: 에러 원문 → 4가지 원인 30초 판별

8080은 예시 포트입니다. 실제 충돌 포트로 바꿔서 읽으세요.

증상 / 관찰되는 상태유력 원인30초 판별 힌트
docker ps에 8080을 publish 중인 다른 컨테이너가 보임① 다른 컨테이너가 이미 점유docker ps --filter publish=8080 에 이름이 잡힘
방금 뜬 스택인데 예전 컨테이너가 Exited/Up으로 남아 있음down 없이 재실행해 이전 컨테이너 잔존docker ps -a --filter publish=8080 에 옛 컨테이너 존재
docker ps -a엔 아무것도 없는데 여전히 에러. ssdocker-proxy가 물고 있음docker-proxy 좀비가 포트 홀드sudo ss -ltnp | grep :8080docker-proxy PID
도커와 무관하게 부팅 직후부터 8080 점유. docker-proxy 아님④ systemd·다른 서비스가 부팅 시 선점ss 결과 프로세스가 도커가 아닌 서비스명

①②는 흔하고 쉬운 케이스, ③이 이 글의 핵심(컨테이너를 다 지웠는데도 에러가 나는 경우), ④는 사실상 도커 문제가 아니므로 해당 서비스를 멈춰야 합니다.

즉시 진단 명령 복붙: 누가 포트를 쥐고 있나

위에서 아래로 순서대로 실행하면 원인이 자동으로 좁혀집니다.

Bash
# ① 이 포트를 publish 중인 "살아있는" 컨테이너 특정
docker ps --filter publish=8080

결과에 컨테이너 이름이 나오면 → 원인 ①. NAMES 열의 이름을 복구 단계에서 씁니다.

Bash
# ② 죽은 컨테이너까지 포함해서 확인 (Exited 상태 잔존 탐지)
docker ps -a --filter publish=8080

Exited (...)인데 이름이 걸려 있으면 → 원인 ②. 아직 rm되지 않아 포트 예약이 남은 상태입니다.

Bash
# ③ 커널 소켓 레벨에서 누가 LISTEN 중인지 + PID 확인
sudo ss -ltnp | grep :8080

users:(("docker-proxy",pid=12345,...)) 처럼 docker-proxy가 보이는데 위 ①②엔 컨테이너가 없다면 → 원인 ③(좀비). 도커가 아닌 다른 프로세스명이면 → 원인 ④.

Bash
# ④ 좀비 docker-proxy 목록만 따로 확인 (해당 포트 인자로 검색)
ps aux | grep '[d]ocker-proxy' | grep 8080

컨테이너가 없는데 이 프로세스가 살아 있으면 좀비 확정입니다. -host-port 8080 인자가 보입니다.

Bash
# ⑤ 네트워크 엔드포인트 잔존 확인 (컨테이너는 없는데 endpoint가 남은 경우)
docker network inspect bridge | grep -A4 Containers

Containers에 죽은 컨테이너 ID가 남아 있으면 네트워크 정리도 필요합니다.

복붙 복구 명령: 상황별 정확한 해제

원인이 특정됐으면 해당 블록만 실행하세요. 위험 명령은 아래에 경고로 따로 뺐습니다.

원인 ① 다른 컨테이너가 점유 중

정말 내려도 되는 컨테이너인지 이름으로 확인한 뒤:

Bash
docker stop <name> && docker rm <name>

내가 원하는 스택을 유지해야 한다면, 상대 컨테이너를 죽이지 말고 내 포트를 바꾸는 게 안전합니다(맨 아래 포트 변경 대안 참고).

원인 ② 이전 컨테이너 잔존 — 이게 제일 흔합니다

docker compose down 없이 재실행해서 고아(orphan) 컨테이너가 남은 경우, 핵심은 --remove-orphans입니다.

Bash
docker compose down --remove-orphans
docker compose up -d

--remove-orphans는 현재 compose 파일에 더 이상 정의돼 있지 않은 잔존 컨테이너까지 정리합니다. compose 파일을 수정한 뒤 서비스명이 바뀐 경우 특히 필요합니다.

원인 ③ 좀비 docker-proxy — 컨테이너를 지웠는데도 에러

정석 순서를 먼저 시도합니다. 대부분 여기서 풀립니다.

Bash
# 1) 남은 컨테이너/네트워크를 정상 경로로 정리
docker compose down --remove-orphans
docker container prune -f
docker network prune -f

정리 후 sudo ss -ltnp | grep :8080 을 다시 실행해 docker-proxy가 사라졌는지 확인합니다. 사라졌으면 바로 up 하면 됩니다.

그래도 docker-proxy가 포트를 붙들고 있다면 진짜 좀비입니다. 이때만 PID를 직접 종료합니다.

Bash
# 2) 진단에서 확인한 docker-proxy PID를 정확히 지정해서 종료
sudo ss -ltnp | grep :8080        # PID 재확인 (예: pid=12345)
sudo kill 12345                   # SIGTERM 먼저
# 안 죽으면
sudo kill -9 12345                # 최후에만 SIGKILL

⚠️ 주의: pkill docker-proxy처럼 이름 전체를 싹 죽이면 정상 동작 중인 다른 컨테이너의 포트 매핑까지 끊깁니다. 반드시 ss로 확인한 해당 포트의 단일 PID만 종료하세요. kill -9는 정상 종료(SIGTERM)가 안 통할 때만 씁니다.

원인 ④ systemd·다른 서비스 선점

도커 문제가 아니므로 해당 서비스를 멈추거나, 도커 포트를 바꿉니다.

Bash
sudo ss -ltnp | grep :8080         # 프로세스명 확인 (예: nginx.service)
sudo systemctl stop nginx          # 필요 시 중지 + disable

🚨 최후의 수단 — Docker 데몬 재시작 (부작용 큼)

Bash
sudo systemctl restart docker

🚨 경고 박스: 이 명령은 호스트의 모든 컨테이너를 재시작합니다. restart 정책이 없는 컨테이너는 다시 뜨지 않을 수 있고, 실행 중인 DB·큐 등 다른 스택도 일제히 끊깁니다. 좀비 docker-proxy가 위의 kill 방법으로도 정리되지 않을 때만, 다른 스택 영향 범위를 확인한 뒤 최후에 사용하세요.

즉시 우회 — 포트만 바꿔서 지금 당장 띄우기

원인 분석할 시간도 없이 당장 실행이 급하면, compose의 호스트 포트를 바꾸는 게 가장 빠릅니다.

YAML
services:
  web:
    image: nginx
    ports:
      - "8081:8080"   # 왼쪽(호스트)만 8081로 변경, 컨테이너 내부는 그대로
Bash
docker compose up -d

재발 방지: 다시는 이 에러로 멈추지 않기

1) 고정 호스트 포트를 피하고 범위/랜덤을 쓰기

YAML
services:
  web:
    ports:
      - "8080-8090:8080"   # 8080이 막히면 다음 빈 포트 자동 할당
  api:
    ports:
      - "8080"             # 호스트 포트 생략 → 랜덤 포트 (docker port <c>로 확인)

랜덤 포트로 뜬 실제 매핑은 다음으로 확인합니다.

Bash
docker compose port web 8080

2) healthcheck로 좀비/비정상 상태 조기 감지

YAML
services:
  web:
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/health"]
      interval: 10s
      timeout: 3s
      retries: 3

3) 종료 습관과 정책 표준화

  • 스택을 내릴 때는 항상 docker compose down --remove-orphans — 컨테이너 stop만 하지 말 것.
  • 계속 떠 있어야 하는 서비스는 restart: unless-stopped로 명시.
  • CI 파이프라인의 teardown 스텝에 docker compose down -v --remove-orphans를 강제로 넣어 잔존을 원천 차단.
YAML
services:
  web:
    restart: unless-stopped

이 세 가지만 습관화해도 원인 ②③은 사실상 사라집니다.

참고: 공식 문서

이 글에서 다루는 동작·설정·에러의 1차 출처는 다음 공식 문서입니다. 버전별 옵션과 정확한 동작은 여기서 확인하세요.

자주 묻는 질문 (FAQ)

Q1. 컨테이너를 docker rm으로 다 지웠는데도 계속 port is already allocated가 떠요. A. docker-proxy 프로세스나 도커 네트워크 엔드포인트가 잔존한 경우입니다. sudo ss -ltnp | grep :포트docker-proxy PID를 확인하고, docker network prune -f로 엔드포인트를 정리하세요. 그래도 남으면 해당 포트의 docker-proxy PID 하나만 sudo kill로 종료합니다(이름 전체 pkill 금지).

Q2. systemctl restart docker 없이 해결하는 방법은? A. 대부분 가능합니다. docker compose down --remove-orphansdocker container prune -fdocker network prune -f 순서로 정리하면 좀비 docker-proxy도 함께 사라지는 경우가 많습니다. 데몬 재시작은 다른 컨테이너까지 전부 재시작시키므로 최후의 수단입니다.

Q3. Bind for 0.0.0.0127.0.0.1 차이가 원인에 영향을 주나요? A. 바인드 주소는 "어느 인터페이스에 포트를 여느냐"의 차이일 뿐, 점유 원인 자체는 동일합니다. 다만 127.0.0.1:8080으로 매핑하면 로컬 전용이라 외부/다른 인터페이스의 8080과는 충돌하지 않을 수 있으므로, compose에서 "127.0.0.1:8080:8080"처럼 명시하면 충돌 표면을 줄일 수 있습니다.

Q4. macOS·Windows의 Docker Desktop에서도 같은 방법이 통하나요? A. 컨테이너 정리(docker compose down --remove-orphans, prune)와 포트 변경 대안은 동일하게 통합니다. 다만 Docker Desktop은 리눅스 VM 위에서 도커가 돌기 때문에 docker-proxy PID를 호스트 ss/ps로 직접 보고 kill하기는 어렵습니다. 이 경우 좀비가 의심되면 컨테이너·네트워크 정리 후 Docker Desktop 자체를 재시작(Restart)하는 방식으로 대응하세요.

✦ ✦ ✦
편집 검토 · Editorial Review

이 글은 AI 에이전트가 자료 조사와 1차 초안 작성을 담당하고, 사람 편집자가 사실관계·출처·톤과 맥락을 검토한 뒤 발행했습니다. 환경(OS·버전)에 따라 결과가 다를 수 있으니 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요 — 확인 후 신속히 정정합니다.

초안 · AI (Content Reviewer)·검토 · Nodelog 편집자·발행 ·
관련 공식 문서Docker 공식 문서

댓글

첫 번째 댓글을 남겨보세요.