외부와 통신하기: 포트 매핑의 원리
컨테이너 내부의 격리된 네트워크 포트를 내 컴퓨터(호스트)의 포트와 연결하여 외부에서 접근할 수 있게 하는 포트 매핑을 배웁니다.
도커 컨테이너를 무사히 실행했는데, 브라우저에서 `localhost:3000`으로 접속하니 "사이트에 연결할 수 없음"이라는 에러가 나온 적 있으신가요? 이는 컨테이너가 기본적으로 외부와 단절된 격리된 네트워크 공간에 살고 있기 때문입니다.
컨테이너 안에서 서버가 열심히 돌아가고 있더라도, 밖에서 그 서버에 접속할 수 있는 길을 뚫어주지 않으면 아무 소용이 없습니다. 이번 에피소드에서는 내 컴퓨터(호스트)와 도커 컨테이너 내부를 연결해주는 포트 매핑(Port Mapping)의 개념과 설정 방법을 알아봅니다.
왜 포트 매핑이 필요한가요?
도커 컨테이너는 일종의 작은 가상 머신처럼 동작합니다. 내 컴퓨터(호스트) 안에 있지만, 네트워크는 완전히 독립된 공간으로 나뉘어져 있습니다.
철저히 격리된 컨테이너의 세계
예를 들어, 컨테이너 안에서 Node.js 서버가 3000번 포트로 실행되었다고 가정해 보겠습니다. 이 3000번 포트는 컨테이너 내부의 포트일 뿐, 내 컴퓨터의 3000번 포트와는 아무런 관련이 없습니다. 따라서 브라우저를 열고 내 컴퓨터의 `localhost:3000`에 접속하더라도 아무것도 응답하지 않게 됩니다.
이 두 세계를 연결하기 위해서는 내 컴퓨터의 특정 포트로 들어오는 요청을 컨테이너 내부의 특정 포트로 전달(Forwarding)해 주어야 합니다. 이 과정을 포트 매핑(Port Mapping)이라고 부릅니다.
포트 매핑의 흐름
내 컴퓨터 브라우저
요청 전송
내 컴퓨터 포트 (Host Port)
내 컴퓨터 포트
포트 매핑으로 전달
컨테이너 포트 (Container Port)
컨테이너 포트
요청 처리
컨테이너 내부 애플리케이션
포트 매핑 설정 방법
도커 컨테이너를 실행할 때, 명령어에 `-p` (publish) 옵션을 추가하여 포트 매핑을 설정할 수 있습니다.
`-p 호스트_포트:컨테이너_포트` 공식
포트 매핑의 규칙은 아주 단순하지만, 순서를 헷갈리기 쉽습니다. 항상 콜론(:)을 기준으로 왼쪽이 내 컴퓨터(호스트)의 포트, 오른쪽이 컨테이너 내부의 포트입니다.
포트 매핑 명령어 실행
bashdocker run -p 8080:3000 my-node-app- 1docker run -p 8080:3000 my-node-app
- 2이 명령어는 컨테이너를 실행하면서 네트워크 포트를 연결합니다.
- 3내 컴퓨터의 8080 포트로 들어오는 모든 요청을,
- 4컨테이너 내부의 3000 포트로 전달합니다.
위와 같이 실행한 후에는 브라우저에서 `localhost:8080`으로 접속해야 합니다. 사용자가 8080으로 접속하면 도커가 이를 가로채서 컨테이너 안의 3000번에서 기다리고 있는 앱에게 전달해 줍니다.
포트 매핑 시 자주 하는 실수
오해 또는 실수
순서를 반대로 적기 (예: -p 3000:8080)
바로잡기
항상 내 컴퓨터(호스트) 포트가 먼저, 컨테이너 포트가 나중입니다. (-p 호스트:컨테이너)
오해 또는 실수
호스트 포트 충돌
바로잡기
내 컴퓨터에서 이미 8080 포트를 다른 프로그램이 사용 중이라면 에러가 발생합니다. 이럴 때는 호스트 포트를 8081 등으로 변경해야 합니다. (-p 8081:3000)
실전 예제로 이해하는 포트 매핑
바이브코딩을 하다 보면 여러 개의 컨테이너를 동시에 띄워야 할 때가 있습니다. 이때 포트 매핑의 진가가 발휘됩니다.
하나의 이미지로 여러 개의 포트 열기
동일한 애플리케이션 이미지를 두 개 실행하되, 각각 다른 포트로 접근하고 싶다면 어떻게 해야 할까요? 컨테이너 내부 포트는 고정해두고, 호스트 포트만 다르게 매핑하면 됩니다.
두 개의 웹 서버를 동시에 띄우기
Nginx 웹 서버의 기본 컨테이너 포트는 80입니다. 이를 내 컴퓨터의 8081번과 8082번 포트에 각각 연결해 보겠습니다.
# 첫 번째 서버 실행
docker run -d -p 8081:80 nginx
# 두 번째 서버 실행
docker run -d -p 8082:80 nginx이렇게 하면 내 컴퓨터의 8081, 8082 포트는 다르지만, 목적지인 각 컨테이너 내부에서는 모두 80번 포트로 안전하게 트래픽이 전달됩니다. 포트 충돌 없이 완벽하게 격리된 두 개의 서버가 완성되었습니다.
포트를 열어두지 않았을 때의 보안 효과
역으로 생각해보면, 포트 매핑을 명시적으로 해주지 않으면 외부에서 해당 컨테이너로 절대 접근할 수 없다는 뜻이기도 합니다. 이는 보안상 큰 장점이 됩니다. 예를 들어 데이터베이스 컨테이너를 띄울 때 호스트와 포트 매핑을 하지 않으면, 오직 도커 네트워크 내부에 있는 다른 컨테이너(예: API 서버)만이 데이터베이스에 접근할 수 있게 됩니다. 외부의 악의적인 접근을 원천 차단하는 것이죠.
개념 퀴즈
퀴즈 답을 맞춰야 학습 완료가 됩니다.다음 중 도커 컨테이너 내부의 80 포트를 내 컴퓨터의 8080 포트로 연결하기 위한 올바른 옵션은 무엇인가요?
3줄 요약
- 1컨테이너는 기본적으로 호스트 컴퓨터와 격리된 독립적인 네트워크를 사용합니다.
- 2외부에서 컨테이너에 접속하려면 -p 호스트포트:컨테이너포트 형식으로 포트 매핑을 해야 합니다.
- 3호스트 포트는 내 마음대로 바꿀 수 있지만, 컨테이너 포트는 애플리케이션 설정에 맞게 지정해야 합니다.