Docker 컨테이너 실행 시, 포트 bind 불가 문제

bind를 거부하는 도커

Error invoking remote method 'docker-start-container': Error: (HTTP code 500) server error - Ports are not available: listen tcp 0.0.0.0:<port>: bind: An attempt was made to access a socket in a way forbidden by its access permissions.

나는 평소에 Postgresql 이용해 개발할 때, 도커 컨테이너를 생성해 개발을 하는 경우가 많다. 그런데 어느 날 컨테이너를 실행시킬 때, 위와 같은 에러가 발생하는 것을 확인했다. 혹시나 해당 포트를 사용하고 있는 중인가 확인도 했지만, 해당 포트를 점유 중인 프로세스를 찾을 수 없었다. 그러다 보니 당시에는 원인도 모르고 그냥 컴퓨터를 껐다 켜고 봤는데, 껐다 켜고 나니 문제 없이 실행되는 것을 보고 그 뒤로는 신경 쓰지 않고 지냈었다.

그런데 사용하는 컨테이너가 하나둘 늘어나기 시작하고, 사용해야 하는 포트의 개수가 늘어나다 보니 이런 문제가 너무 빈번하게 일어나기 시작했다. 결국엔 근본적인 문제 해결법이 필요할 수 밖에 없었다.


문제는 동적 포트야!

일반적으로 포트를 점유한 프로세스도 찾을 수 없는데도 해당 포트를 사용 중인 상황을 겪고 있다면, 보통은 운영체제나 프로세스에 의해 미리 동적 포트가 할당되어서 그럴 가능성이 높다. 운영체제나 프로세스는 처음 시작 시, 시스템에서 사용할 포트를 동적으로 할당 시킨다. 당연한 소리지만, 이 때 할당된 포트는 사용자가 사용할 수 없다. 컴퓨터를 재부팅 시, 다시 포트를 사용 할 수 있게 되는 것은 매번 이 동적으로 할당된 포트가 바뀌게 되기 때문이다. 윈도우를 사용중이라면, PowerShell을 열고 다음의 명령어를 입력해보자.

netsh interface ipv4 show excludedportrange protocol=tcp
결과 화면

위의 사진처럼 시작 포트와 끝 포트 정보가 뜨게 될 것인데 시작 포트와 끝 포트의 의미는, 저 사이의 포트들은 시스템 혹은 프로세스에 의해 예약되어 있다는 의미다. 예를 들어, 시작 포트: 2116 끝 포트: 2215 라면 2116~2215 포트는 모두 예약되어 있다는 의미다.


그래서 해결법은?

근본적으로는 내가 사용하고자 하는 포트들을 예약해서, 시스템이나 다른 프로세스가 자동으로 포트를 할당하지 않도록 해야 한다. 우선은 관리자 권한으로 PowerShell을 열도록 하자. PowerShell을 열었다면 다음 명령어를 입력해 포트를 예약하도록 하자.

netsh int ipv4 add excludedportrange protocol=tcp startport=5432 numberofports=1 store=persistent

위의 명령어는 tcp 프로토콜의 5432번 포트부터 한 개의 포트를 예약하겠다는 의미다. 만약 5432부터 5442 포트까지 예약하고 싶다면 numberofports 인수를 10으로 바꿔주면 된다.

이제 다시 아래의 명령어를 입력해 보자.

netsh interface ipv4 show excludedportrange protocol=tcp

내가 지정한 포트와 그 옆에 (*) 표시가 있는 것을 볼 수 있는데, 이는 관리 포트로 시스템이나 프로세스가 이 포트에는 자동으로 할당하지 않게 된다.


정리하며

그동안 정체불명의 포트 사용자로부터 여러모로 고통을 받았는데(...) 이 기회에 해당 현상과 관련해 조사하며 이 의문을 해결할 수 있었다. 다른 사람들도 이 글을 보고 고통에서 해방될 수 있는 사람이 있기를 바라며 이 글을 마치겠다.


참고한 문헌 및 글

  1. Cannot start service backend: Ports are not available: listen tcp 0.0.0.0:3001: bind: An attempt was made to access a socket in a way forbidden by its access permissions. 에러 해결하기 (velog.io)