Docker를 처음 배우면 가장 헷갈리는 부분 중 하나가 바로 포트 매핑입니다.
분명히 컨테이너 안에서 서버를 실행했는데, 브라우저에서 접속이 되지 않는 경험을 해본 적 있을 겁니다.
그 이유는 간단합니다. 컨테이너 안의 포트와 내 컴퓨터의 포트는 다르기 때문입니다.
이번 글에서는 Docker 네트워크 구조와 포트 매핑이 왜 필요한지,
그리고 -p 8080:80 같은 명령어가 실제로 어떤 흐름을 만드는지 정리해보겠습니다.
1. 컨테이너는 독립된 네트워크 공간
컨테이너는 가상 머신과 달리 무겁지 않지만, 기본적으로 호스트와 격리된 네트워크 공간을 가집니다.
- 내 컴퓨터(호스트)에는 여러 개의 포트(80, 443, 8080 등)가 열려 있고, 이를 통해 외부와 통신합니다.
- 컨테이너도 자체적으로 포트를 열 수 있지만, 호스트와 자동으로 연결되지는 않습니다.
즉, 컨테이너 내부에서 웹 서버를 실행한다고 해서, 내 브라우저에서 바로 접근할 수 있는 것은 아닙니다.
2. 컨테이너 내부 포트 vs 호스트 포트
예를 들어, nginx 컨테이너를 실행한다고 가정해 보겠습니다.
docker run nginx
nginx는 컨테이너 내부에서 기본적으로 80번 포트를 열지만,
이 상태에서는 내 브라우저에서 http://localhost로 접속해도 아무 일도 일어나지 않습니다.
왜냐하면 컨테이너 내부의 80번 포트와 내 컴퓨터의 포트가 연결되어 있지 않기 때문입니다.
3. 포트 매핑: -p 호스트포트:컨테이너포트
이때 필요한 것이 바로 -p 옵션입니다.
docker run -d -p 8080:80 nginx
8080:80의미 → 호스트의 8080번 포트를 컨테이너의 80번 포트와 연결- 이제 브라우저에서 http://localhost:8080에 접속하면, 요청이 내 PC(호스트) 8080번 포트로 들어오고, Docker가 이 요청을 컨테이너 80번 포트로 전달합니다. 이렇게 해서 비로소 컨테이너 안의 웹 서버에 접근할 수 있습니다.
4. 실제 접속 흐름 이해하기
포트 매핑이 동작하는 과정을 단계별로 살펴보겠습니다.
- 사용자가 브라우저에
http://localhost:8080입력 - 요청이 내 컴퓨터의 8080번 포트로 들어옴
- Docker 엔진이 “8080 → 컨테이너의 80” 규칙을 확인
- 요청을 실행 중인 nginx 컨테이너의 80번 포트로 전달
- nginx가 응답을 만들어 다시 Docker를 통해 8080번 포트로 반환
- 최종적으로 브라우저에서 nginx 페이지 확인
즉, Docker는 포트 프록시 역할을 하면서 외부와 컨테이너 내부를 이어주는 다리 역할을 합니다.
5. 다른 예시와 활용
[Node.js 서버]
docker run -d -p 3000:3000 my-node-app
→ 내 PC의 3000번 포트를 컨테이너의 3000번 포트와 연결
[여러 개의 컨테이너 실행]
docker run -d -p 8081:80 nginx
docker run -d -p 8082:80 nginx
→ 동일한 nginx 이미지를 실행하지만, 각각 다른 포트로 접근 가능
→ http://localhost:8081, http://localhost:8082
6. 자주 하는 실수와 팁
- 컨테이너 포트만 EXPOSE 했다고 접속 가능한 줄 착각
→EXPOSE는 단순한 문서화일 뿐, 실제 포트 매핑을 하려면-p옵션이 필요합니다. - 잘못된 포트 매핑
→-p 80:8080과-p 8080:80은 전혀 다릅니다. 앞쪽은 호스트 포트, 뒤쪽은 컨테이너 포트입니다. - 이미 사용 중인 포트 충돌
→ 호스트의 같은 포트를 두 컨테이너에 동시에 매핑할 수 없습니다. 다른 포트를 선택해야 합니다.
Docker 컨테이너는 독립된 네트워크 공간을 가지기 때문에,
호스트 포트와 컨테이너 포트를 매핑하지 않으면 외부에서 접근할 수 없습니다.
-p 호스트:컨테이너옵션으로 연결해야 하며- 그 과정에서 Docker가 요청을 중계하는 프록시 역할을 합니다.
포트 매핑은 “내 컴퓨터로 들어온 요청을 컨테이너로 안전하게 전달하는 다리”입니다.
이를 이해하면 nginx, Node.js, Python Flask 등 어떤 서버 애플리케이션이든 Docker에서 올바르게 실행하고 접속할 수 있습니다.
'개발정리 (docker)' 카테고리의 다른 글
| [docker] Docker 컨테이너의 실체: 리눅스 네임스페이스와 cgroups (0) | 2025.09.26 |
|---|---|
| [docker] 컨테이너 다루기 필수 명령어 모음 (0) | 2025.09.24 |
| [docker] 내 애플리케이션을 Docker 이미지로 만들기 (0) | 2025.09.22 |
| [docker] Dockerfile 제대로 이해하기: 실무에서 자주 쓰는 명령어 정리 (0) | 2025.09.19 |
| [docker] Docker의 장점과 단점 (0) | 2025.09.18 |