Docker 컨테이너 'Connection Refused' (Errno 111) 오류 해결 가이드

🎯 타겟 독자: Docker 입문자, 컨테이너를 띄웠으나 localhost로 접속이 안 되는 백엔드 개발자, MSA(마이크로서비스) 구축 중 통신 오류를 겪는 엔지니어.


📝 요약: Docker 접속 오류(Errno 111)의 90%는 애플리케이션이 '0.0.0.0'이 아닌 '127.0.0.1'로 바인딩 되어 있거나, 포트 포워딩(-p) 설정이 누락되어 발생합니다. 이 글에서는 네트워크 인터페이스의 차이를 이해하고, 외부 접속을 허용하는 올바른 설정법을 정리합니다.

도커 컨테이너 네트워킹 다이어그램

1. 문제 정의: "컨테이너는 떴는데 접속이 안 돼요"

Docker 입문자들이 가장 흔하게 겪는 상황입니다. docker ps로 확인하면 상태(STATUS)는 분명히 Up인데, 브라우저나 Postman으로 접속하면 즉시 연결이 거부됩니다.

  • curl: (7) Failed to connect to localhost port 8080: Connection refused
  • Python: ConnectionRefusedError: [Errno 111] Connection refused

이 문제는 방화벽 때문이 아닙니다. "누구의 요청을 들을 준비가 되었는가(Listen Address)"에 대한 설정이 잘못되었기 때문입니다.

2. 원인 분석: 127.0.0.1의 함정

핵심은 Loopback(127.0.0.1)Any Address(0.0.0.0)의 차이입니다.

로컬 PC에서 개발할 때 서버를 localhost로 띄우는 건 보안상 좋은 습관입니다. 하지만 Docker 컨테이너는 독립된 IP를 가진 별도의 컴퓨터 취급을 받습니다.

⚠️ 중요: 컨테이너 내부 앱이 127.0.0.1만 바라보고 있다면, 이는 "컨테이너 자기 자신의 내부 요청만 받겠다"는 뜻입니다. 외부(호스트 PC)의 요청은 무시됩니다.

3. 해결 솔루션 (단계별 가이드)

Step 1. 포트 바인딩(Port Mapping) 확인

가장 기초적인 실수입니다. 컨테이너의 문을 열어주어야 합니다.

# 잘못된 예 (포트 매핑 없음) docker run my-server:v1 # 올바른 예 (-p 호스트포트:컨테이너포트) docker run -p 8080:3000 my-server:v1

Step 2. 애플리케이션 바인딩 주소 변경 (핵심)

포트 매핑을 했는데도 안 된다면, 코드를 수정해야 합니다. 무조건 0.0.0.0으로 설정하세요.

Python (Flask/FastAPI)

# Flask: host='0.0.0.0' 필수 if __name__ == '__main__': app.run(host='0.0.0.0', port=5000) # FastAPI (Uvicorn) 실행 명령 uvicorn main:app --host 0.0.0.0 --port 8000

Node.js (Express)

const app = express(); // 명시적으로 0.0.0.0을 지정하세요 app.listen(3000, '0.0.0.0', () => { console.log('Server running on 0.0.0.0:3000'); });

Spring Boot

# application.properties server.address=0.0.0.0

Step 3. Dockerfile 검증

DockerfileEXPOSE 명령어가 있는지 확인합니다. 이는 문서화 목적이지만, 오케스트레이션 도구(K8s, AWS ECS)에서는 중요한 역할을 합니다.

FROM python:3.12-slim WORKDIR /app COPY . . RUN pip install -r requirements.txt # 이 포트를 쓴다고 명시 EXPOSE 8000 CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"]

4. 네트워크 모드 비교 (리눅스 유저 팁)

리눅스 환경에서는 포트 포워딩 대신 네트워크 모드를 변경하는 방법도 있습니다.

모드 설명 접속 (Host)
Bridge 기본값. NAT 통신 localhost:포트 (매핑 필요)
Host 호스트 네트워크 공유 localhost:포트 (매핑 불필요)

5. 결론

Docker 네트워크 오류 해결은 "내 컴퓨터(Host)와 컨테이너(Guest)는 다른 세상에 산다"는 것을 인지하는 것에서 시작합니다.

접속이 안 된다면 딱 3가지만 기억하세요.
1. docker run -p 옵션을 썼는가?
2. 코드가 0.0.0.0에서 리스닝 중인가?
3. 컨테이너 내부 방화벽이 있는가? (드물지만 확인 필요)

이 블로그의 인기 게시물

Python 3.13+ 환경에서 'ModuleNotFoundError' 발생하는 원인과 가상환경(venv) 재설정 해결법