IT/기초 지식

[Docker] Docker 컨테이너에 네트워크 액세스하기(docker run -p 옵션)

개발자 두더지 2021. 10. 12. 20:28
728x90

들어가기에 앞서


$ docker run -t -p 9000:8080 gihyodocker/echo:latest

 위의 docker run 커맨드에서 -p 9000:8080의 부분이 이해가 잘 안가서 정리하는 내용이다.

 

 

TCP/IP접속과 포트


 Docker에 대한 이야기를 하기 전에 TCP/IP 접속과 포트에 대해서 알보자. 이미 이 내용을 잘 알고 있다면 넘겨도 괜찮다. 

 예를 들어 웹브라우저에서 https://qiita.com 에 접속하는 것을 생각해보자. 보통 별로 신경쓰지 않지만, 블라우저에 표시하는 데이터를 qitta.com으로 부터 취득하기 때문에 https접속하지만, 그 토대가 되는 것이 TCP/IP 접속이다. 그 때 필요한 것이 "IP주소"랑 "포트 번호"이다.

 IP주소는 "호스트명"으로부터 DNS이라는 구조를 통해 알 수 있다. 커맨드 라인으로 확인하면 아래와 같다.

$ nslookup qiita.com
Server:     xxx
Address:    xxx#53

Non-authoritative answer:
Name:   qiita.com
Address: 13.112.220.124
Name:   qiita.com
Address: 52.199.237.49
Name:   qiita.com
Address: 18.179.247.240

 한편으로 포트 번호는 서비스마다 정해진 값이 할당되어 있다. 이것을 Well-Known port라고 말한다. 예를 들어 http프로토콜에서는 80번, https프로토콜에서는 443번이 사용된다. 

 그러므로 https://qiita.com 의 경우는 13.112.220.124, 52.199.237.49, 18.179.247.240 몇 개의 호스트 포트 번호 443으로 접속한다. 

 서버쪽의 qiita.com에서는 443번에 누군가 접속하기를 기다리는(listen), 접속해 오면 미리 설정해둔 어플리케이션(이 경우에는 httpd)에 넘겨준다.

 또한 보통 신경쓰지 않겠지만, 포트 번호는 접속처의 서버쪽뿐만 아니라 접속원의 클라이언트 쪽에도 할당된다. 서버쪽에서부터 봤을 때에 어떤 IP 주소의 어떤 포트로 접속해왔는지 특정하지 위함이지만, 일시적으로 할당된 포트를 ephemeral port라고 부른다.

 

 

Docker 컨테이너와 포트


 Docker 컨테이너는 Linux(macOS/Windows의 Hypervisor상에 동작하는 Linux를 포함한)의 위에서 가동하는 가상화환경이다. 커널은 컨테이너 간에 공유하고 있는 것으로, 프로세스, 파일 시스템, 네트워크는 각각 독립하고 있어 개별적으로 분리되어 있다.

 따라서 컨테이너의 안에 어떤 포트를 받길 기다리고 있는 서버 어플리케이션을 움직이고 있다해도, 그대로는 외부로부터 접근할 수 없다.

 이 상황에서 외부에서 부터 액세스할 수 있게 하는 것이 맨 위에서 얘기한 커맨드 -p(--publish) 옵션이 된다. 컨테이너의 포트를 외부에 "공개"하는 느낌이라고 생각하면 될 것 같다. 이 때, 원래 컨테이너가 지정하고 있는 포트 번호와 외부 공개하는 포트 번호를 바꾸는 것이 가능해, 이것을 포트 맵핑 혹은 포트 포워딩이라고 부른다.

 예를 들어, p 9000:8080를 지정한 경우에는 외부로부터 온 9000번으로의 액세스를 컨테이너의 8080번으로 대체하는 것을 의미한다.

$ docker run -t -p 9000:8080 -d --rm gihyodocker/echo:latest
$ curl http://localhost:9000/
Hello Docker!!

 

 

여러 개의 컨테이너를 가동할 경우


 Docker는 동일한 이미지 파일로부터 여러 개의 컨테이너를 실행할 수 있다. 그러나 포트 맵핑을 실행할 경우에는 약간의 주의가 필요하다. 위에서의 커맨드로 기존에 하나의 컨테이너를 가동하고 있는 상태에 하나를 더 가동시켜보았다.

$ docker run -t -p 9000:8080 -d --rm gihyodocker/echo:latest
....
docker: Error response from daemon: driver failed programming external connectivity on endpoint sad_blackwell (....): Bind for 0.0.0.0:9000 failed: port is already allocated.

 잘 생각해보면 당연한 이야기이지만, 호스트쪽의 포트 9000번이 이미 사용되고 있기 때문에 실행할 수 없다는 에러가 발생하고 있다. 이 경우에는 다른 포트를 지정하면 될 뿐이다. 예를 들어 -p 9001:8080으로 하나의 컨테이너를 더 실행한다면 아래와 같은 그림이 될 것이다.

 

 

마무리


 Docker의 -p/--publish 옵션에 대해서 알아보았다. 실제로 여러 개의 컨테이너를 관리할 경우는 docker-compose를 이용하는 경우가 많으며, docker-compose를 이용하는 경우에는 포트 맵핑 지정은 docker-compose.yml(docker-compose 설정 파일)에 작성하게 된다. 


참고자료

https://qiita.com/ksato9700/items/0b4c7de5d857dc731443

 

 

728x90