Docker Desktop이 VPN, DNS, HTTP 프록시, 포트 포워딩을 통해 다양한 네트워크 환경에서 컨테이너 네트워킹을 안정적으로 동작시키는 내부 방식을 설명합니다.
800명 이상의 빌더와 리더로부터 얻은 AI 에이전트 현황 인사이트. 사본을 다운로드하세요
✕
AI 및 에이전트 * Docker Sandboxes New 코딩 에이전트를 위한 새로운 격리 환경 * AI Governance New 모든 팀 전반에서 에이전트와 Claws를 관리 * Gordon New Docker 전반의 당신의 AI Agent * Docker Model Runner 손쉬운 로컬 우선 LLM 추론 * Docker MCP Catalog and Toolkit MCP 도구 연결 및 관리
애플리케이션 보안
* [Docker Hardened Images 안전하고 엔터프라이즈 준비가 된 이미지를 제공](https://www.docker.com/products/hardened-images/)
* [Docker Scout 소프트웨어 공급망 단순화](https://www.docker.com/products/docker-scout/)
애플리케이션 개발
* [Docker Desktop 애플리케이션을 컨테이너화](https://www.docker.com/products/docker-desktop/)
* [Docker Hub 컨테이너 이미지 검색 및 공유](https://www.docker.com/products/docker-hub/)
* [Docker Offload 로컬 제약에서 벗어나기](https://www.docker.com/products/docker-offload/)
개발자 * Documentation Docker 제품 가이드 찾기 * Getting Started Docker 기초 배우기 * Resources 유용한 자료 라이브러리 검색 * Training Docker 지식 향상 * Extensions SDK 나만의 확장 기능 만들고 공유하기 * Community 다른 Docker 개발자와 연결 * Open Source 오픈 소스 프로젝트 살펴보기 * Preview Program Docker의 미래를 함께 만들기 * Customer Stories 고객 사례에서 영감 얻기
## Docker Hardened Images (DHI)모든 팀을 위한 안전하고 최소한의 컨테이너 이미지, 필요 시 엔터프라이즈 기능과 함께 무료 제공. 무료 체험 시작
검색
메뉴 전환
게시일 2022년 1월 25일

현대 애플리케이션은 네트워크를 광범위하게 사용합니다. 빌드 시점에는 Linux 배포판의 패키지 저장소에서 패키지를 가져오기 위해 apt-get/dnf/yum/apk install을 수행하는 일이 흔합니다. 런타임에는 애플리케이션이 어떤 상태를 저장하기 위해 내부 postgres 또는 mysql 데이터베이스에 connect() 하기를 원할 수 있으며, 동시에 TCP 및 UDP 포트를 통해 API와 UI를 노출하기 위해 listen() 과 accept() 를 호출할 수도 있습니다. 한편 개발자는 사무실이든 집이든 모바일 환경이든 VPN 환경이든 어디에서나 작업할 수 있어야 합니다. Docker Desktop은 이러한 모든 시나리오의 모든 사용 사례에서 네트워킹이 “그냥 작동”하도록 설계되었습니다. 이 글에서는 이를 가능하게 하기 위해 우리가 사용하는 도구와 기법을 설명하며, 모두가 좋아하는 프로토콜 스위트인 TCP/IP부터 시작합니다.
컨테이너가 외부 세계에 연결하려고 할 때는 TCP/IP를 사용합니다. Linux 컨테이너는 Linux 커널이 필요하므로 Docker Desktop에는 보조 Linux VM이 포함됩니다. 따라서 컨테이너의 트래픽은 호스트가 아니라 Linux VM에서 시작되며, 이것이 심각한 문제를 일으킵니다.
많은 IT 부서는 “호스트 에서 시작된 트래픽만 VPN을 통해 전달하라”는 식의 VPN 정책을 만듭니다. 그 의도는 호스트가 실수로 라우터처럼 동작하여 인터넷의 안전하지 않은 트래픽을 안전한 기업 네트워크로 전달하는 일을 막는 것입니다. 따라서 VPN 소프트웨어가 Linux VM에서 온 트래픽을 보면, 그 트래픽은 VPN을 통해 라우팅되지 않으며, 그 결과 컨테이너는 내부 레지스트리 같은 리소스에 접근할 수 없게 됩니다.
Docker Desktop은 vpnkit을 통해 모든 트래픽을 사용자 수준에서 전달함으로써 이 문제를 피합니다. vpnkit은 MirageOS Unikernel project의 네트워크 프로토콜 라이브러리 위에 OCaml로 작성된 TCP/IP 스택입니다. 다음 다이어그램은 보조 VM에서 vpnkit을 거쳐 인터넷으로 나가는 패킷 흐름을 보여줍니다.
VM이 부팅되면 DHCP를 사용해 주소를 요청합니다. 요청을 담은 이더넷 프레임은 공유 메모리를 통해 VM에서 호스트로 전송되며, Mac에서는 virtio device를 사용하고 Windows에서는 “hypervisor socket”(AF_VSOCK)을 사용합니다. Vpnkit에는 DHCP (mirage/charrua) 서버로 요청을 전달하는 가상 이더넷 스위치(mirage-vnetif)가 포함되어 있습니다.
VM이 VM의 IP 주소와 게이트웨이의 IP를 포함한 DHCP 응답을 받으면, 게이트웨이의 이더넷 주소를 찾기 위해 ARP 요청을 보냅니다(mirage/arp). ARP 응답을 받은 뒤에는 인터넷으로 패킷을 보낼 준비가 됩니다.
vpnkit이 새로운 목적지 IP 주소를 가진 나가는 패킷을 보면, 원격 머신을 나타내는 가상 TCP/IP 스택을 생성합니다(mirage/mirage-tcpip). 이 스택은 Linux 안의 스택의 피어처럼 동작하며 연결을 수락하고 패킷을 교환합니다. 컨테이너가 TCP 연결을 설정하기 위해 connect() 를 호출하면 Linux는 SYNchronize 플래그가 설정된 TCP 패킷을 보냅니다. Vpnkit은 이 SYNchronize 플래그를 관찰하고 호스트에서 자체적으로 connect() 를 호출합니다. connect() 가 성공하면 vpnkit은 TCP 핸드셰이크를 완료하는 TCP SYNchronize 패킷으로 Linux에 응답합니다. Linux 안에서는 connect() 가 성공하고 데이터는 양방향으로 프록시됩니다(mirage/mirage-flow). connect() 가 거부되면 vpnkit은 TCP RST (reset) 패킷으로 응답하고, 그러면 Linux 내부의 connect() 는 오류를 반환합니다. UDP와 ICMP도 비슷한 방식으로 처리됩니다.
저수준 TCP/IP 외에도 vpnkit에는 DNS 서버(mirage/ocaml-dns)와 HTTP 프록시(mirage/cohttp) 같은 여러 고수준 네트워크 서비스가 내장되어 있습니다. 이러한 서비스는 설정에 따라 가상 IP 주소 또는 DNS 이름을 통해 직접 지정할 수도 있고, 나가는 트래픽을 매칭해 동적으로 리디렉션하는 방식으로 간접적으로 사용할 수도 있습니다.
TCP/IP 주소는 직접 다루기 어렵습니다. 다음 섹션에서는 Docker Desktop이 Domain Name System (DNS)을 사용하여 네트워크 서비스에 사람이 읽을 수 있는 이름을 부여하는 방법을 설명합니다.
Docker Desktop 내부에는 여러 DNS 서버가 있습니다.
컨테이너에서 오는 DNS 요청은 먼저 dockerd 내부의 서버에서 처리되며, 이 서버는 같은 내부 네트워크에 있는 다른 컨테이너의 이름을 인식합니다. 덕분에 컨테이너는 내부 IP 주소를 몰라도 서로 쉽게 통신할 수 있습니다. 예를 들어 다이어그램에는 docker/awesome-compose example에서 가져온 “nginx”, “golang”, “postgres” 라는 3개의 컨테이너가 있습니다. 애플리케이션이 시작될 때마다 내부 IP 주소는 달라질 수 있지만, dockerd 내부의 DNS 서버 덕분에 컨테이너는 사람이 읽기 쉬운 이름으로 여전히 쉽게 서로 연결할 수 있습니다.
그 외 모든 이름 조회는 CoreDNS로 전송됩니다(CNCF 제공). 그런 다음 요청은 도메인 이름에 따라 호스트의 두 가지 DNS 서버 중 하나로 전달됩니다. docker.internal 도메인은 특별하며 현재 호스트에 대해 유효한 IP 주소로 해석되는 DNS 이름 host.docker.internal 을 포함합니다. 우리는 모든 것이 완전히 컨테이너화되는 것을 선호하지만, 때로는 애플리케이션의 일부를 전통적인 호스트 서비스로 실행하는 것이 타당할 수 있습니다. 특별한 이름 host.docker.internal 은 컨테이너가 IP 주소를 하드코딩할 걱정 없이 이들 호스트 서비스에 이식성 있게 접근할 수 있도록 해줍니다.
호스트의 두 번째 DNS 서버는 표준 OS 시스템 라이브러리를 통해 다른 모든 요청을 해석합니다. 이렇게 하면 개발자의 웹 브라우저에서 어떤 이름이 올바르게 해석된다면, 개발자의 컨테이너 안에서도 그 이름이 올바르게 해석되도록 보장할 수 있습니다. 이는 특히 다이어그램에 묘사된 것처럼 일부 요청은 기업 VPN을 통해 전송되고(예: internal.registry.mycompany) 다른 요청은 일반 인터넷으로 전송되는(예: docker.com) 정교한 설정에서 매우 중요합니다.
이제 DNS를 설명했으니 HTTP에 대해 이야기해 보겠습니다.
일부 조직은 인터넷 직접 접근을 차단하고 모든 트래픽을 필터링과 로깅을 위해 HTTP 프록시를 통해 보내도록 요구합니다. 이는 빌드 중 이미지 풀링뿐 아니라 컨테이너가 생성하는 아웃바운드 네트워크 트래픽에도 영향을 줍니다.
HTTP 프록시를 사용하는 가장 단순한 방법은 환경 변수를 통해 Docker 엔진이 프록시를 명시적으로 가리키게 하는 것입니다. 이 방법의 단점은 프록시를 변경해야 할 때 변수를 갱신하기 위해 Docker 엔진 프로세스를 재시작해야 하며, 이로 인해 눈에 띄는 중단이 발생한다는 점입니다. Docker Desktop은 vpnkit 내부에서 사용자 정의 HTTP 프록시를 실행하고 이를 업스트림 프록시로 전달함으로써 이 문제를 피합니다. 업스트림 프록시가 바뀌면 내부 프록시가 동적으로 재구성되므로 Docker 엔진을 재시작할 필요가 없습니다.
Mac에서 Docker Desktop은 시스템 환경설정에 저장된 프록시 설정을 모니터링합니다. 컴퓨터가 네트워크를 전환할 때(예: WiFi 네트워크 간 이동 또는 셀룰러 전환) Docker Desktop은 내부 HTTP 프록시를 자동으로 업데이트하여 개발자가 아무 조치도 취하지 않아도 모든 것이 계속 작동하도록 합니다.
이제 컨테이너끼리, 그리고 인터넷과 통신하는 부분은 대체로 설명했습니다. 그렇다면 개발자는 어떻게 컨테이너와 통신할까요?
애플리케이션을 개발할 때는 웹 브라우저 같은 디버그 도구로 접근 가능한 호스트 포트에 UI와 API를 노출할 수 있으면 유용합니다. Docker Desktop은 Linux 컨테이너를 Linux VM 안에서 실행하므로 단절이 생깁니다. 포트는 VM 안에서 열려 있지만 도구는 호스트에서 실행됩니다. 따라서 호스트에서 VM 안으로 연결을 전달할 무언가가 필요합니다.
웹 애플리케이션을 디버깅하는 상황을 생각해 봅시다. 개발자는 http://localhost 로 접근할 수 있도록 컨테이너의 80번 포트를 호스트의 80번 포트에 노출해 달라고 docker run -p 80:80 을 입력합니다. Docker API 호출은 평소처럼 호스트의 /var/run/docker.sock 에 기록됩니다. Docker Desktop이 Linux 컨테이너를 실행할 때 Docker 엔진(위 다이어그램의 dockerd)은 호스트에서 네이티브로 실행되는 것이 아니라 보조 Linux VM 안에서 실행되는 Linux 프로그램입니다. 따라서 Docker Desktop에는 호스트의 요청을 VM으로 전달하는 Docker API 프록시가 포함됩니다. 보안과 신뢰성을 위해 요청은 네트워크를 통한 TCP 위에서 직접 전달되지 않습니다. 대신 Docker Desktop은 위 다이어그램에서 vpnkit-bridge 로 표시된 프로세스를 통해 공유 메모리 hypervisor sockets 같은 안전한 저수준 전송 위로 Unix domain socket 연결을 전달합니다.
Docker API 프록시는 단순히 요청과 응답을 앞뒤로 전달하는 것 이상을 할 수 있습니다. 개발자 경험을 개선하기 위해 요청과 응답을 디코드하고 변환할 수도 있습니다. 개발자가 docker run -p 80:80 으로 포트를 노출하면 Docker API 프록시는 요청을 디코드하고 내부 API를 사용해 com.docker.backend 프로세스를 통해 포트 포워드를 요청합니다. 호스트에서 이미 누군가 그 포트를 리슨하고 있다면 사람이 읽을 수 있는 오류 메시지가 개발자에게 반환됩니다. 포트가 비어 있다면 com.docker.backend 프로세스가 연결 수락을 시작하고, vpnkit-bridge 위에서 실행되는 vpnkit-forwarder 프로세스를 통해 이를 컨테이너로 전달합니다.
Docker Desktop은 호스트에서 “root” 또는 “Administrator” 권한으로 실행되지 않습니다. 개발자는 docker run –privileged 를 사용해 보조 VM 안에서 root가 될 수 있지만, hypervisor는 호스트가 항상 완전히 보호되도록 보장합니다. 이는 보안 측면에서 훌륭하지만 macOS에서는 사용성 문제를 일으킵니다. Unix에서 “privileged port” 로 간주되는, 즉 포트 번호가 1024보다 작은 80번 포트에 개발자가 어떻게 노출할 수 있을까요(docker run -p 80:80)? 해결책은 Docker Desktop에 launchd 에 의해 root로 실행되는 아주 작은 보조 특권 서비스가 포함되어 있으며, 이 서비스가 “이 포트를 바인드해 주세요” API를 노출한다는 점입니다. 여기서 이런 질문이 생깁니다. “비root 사용자가 privileged ports를 바인드하도록 허용하는 것은 안전할까요?”
원래 privileged port 개념은 포트를 서비스 인증에 사용하던 시절에서 왔습니다. 예를 들어 80번 포트에 바인드된 서비스와 통신하고 있으므로 그것이 호스트의 HTTP 데몬이라고 안전하게 가정할 수 있었는데, 80번 포트 바인드는 root 권한이 필요했기 때문에 관리자가 그렇게 구성했을 것이라고 생각할 수 있었기 때문입니다. 현대에는 서비스를 인증하는 방식으로 TLS 인증서와 ssh 지문을 사용하므로, 시스템 서비스가 Docker Desktop이 시작되기 전에 자신의 포트를 바인드하기만 하면 — macOS는 부팅 시 launchd 를 통해 포트를 바인드함으로써 이를 보장합니다 — 혼동이나 서비스 거부는 발생할 수 없습니다. 이에 따라 현대 macOS는 모든 IP(0.0.0.0 또는 INADDR_ANY)에서 privileged port를 바인드하는 작업을 비특권 작업으로 만들었습니다. Docker Desktop이 여전히 특권 보조 서비스를 사용해 포트를 바인드해야 하는 경우는 단 하나, 특정 IP가 요청될 때입니다(예: docker run -p 127.0.0.1:80:80). 이 경우는 macOS에서 여전히 root 권한이 필요합니다.
애플리케이션은 Docker 이미지 풀링, Linux 패키지 설치, 데이터베이스 백엔드와의 통신, API와 UI 노출 등 매우 많은 일상적 활동을 위해 신뢰할 수 있는 네트워크 연결이 필요합니다. Docker Desktop은 매우 다양한 네트워크 환경에서 실행됩니다. 사무실, 집, 그리고 불안정한 와이파이 환경의 이동 중에도 실행됩니다. 어떤 머신에는 제한적인 방화벽 정책이 설치되어 있습니다. 또 어떤 머신에는 정교한 VPN 구성이 있습니다. 이 모든 환경의 모든 사용 사례에서 Docker Desktop은 “그냥 작동”하는 것을 목표로 하며, 그래서 개발자는 우리의 문제를 디버깅하는 대신 자신의 애플리케이션을 빌드하고 테스트하는 데 집중할 수 있습니다!
이런 종류의 도구를 만드는 일이 흥미롭게 느껴진다면, Docker Desktop 네트워킹을 더 좋게 만드는 일에 함께해 주세요. 우리는 채용 중입니다. https://www.docker.com/career-openings 를 확인하세요.
DockerCon2022에 5월 10일 화요일 함께하세요. DockerCon은 차세대 현대적 애플리케이션을 구축하는 개발자와 개발 팀을 위한 특별한 경험을 제공하는 무료 1일 가상 이벤트입니다. 코드에서 클라우드까지 빠르게 나아가는 방법과 개발 과제를 해결하는 방법을 배우고 싶다면, DockerCon 2022는 애플리케이션을 빌드하고 공유하고 실행하는 데 도움이 되는 매력적인 라이브 콘텐츠를 제공합니다. 지금 등록하세요.https://www.docker.com/dockercon/
목차
Srini Sekaran 지금 읽기
Aditya Tripathi 지금 읽기
Srini Sekaran 지금 읽기
Aditya Tripathi 지금 읽기© 2026 Docker Inc. All rights reserved
내 개인정보 판매 금지
이 웹사이트는 사용자 경험을 향상하고 웹사이트의 성능과 트래픽을 분석하기 위해 쿠키를 사용합니다. 또한 당사는 귀하의 사이트 사용 정보 일부를 소셜 미디어, 광고 및 분석 파트너와 공유합니다.
내 개인정보 판매 금지 쿠키 수락

당사 웹사이트를 방문하면 정보를 수집하기 위해 브라우저에 쿠키를 저장합니다. 수집된 정보는 귀하, 귀하의 선호도 또는 귀하의 기기와 관련될 수 있으며, 주로 사이트가 귀하가 기대하는 대로 작동하도록 하고 보다 개인화된 웹 경험을 제공하는 데 사용됩니다. 그러나 특정 유형의 쿠키를 허용하지 않도록 선택할 수 있으며, 이는 사이트 경험과 당사가 제공할 수 있는 서비스에 영향을 줄 수 있습니다. 더 자세히 알아보고 기본 설정을 선호에 따라 변경하려면 각 카테고리 제목을 클릭하세요. 당사 웹사이트의 적절한 기능 보장을 위해 배포되는 First Party Strictly Necessary Cookies(예: 쿠키 배너 표시 및 설정 기억, 계정 로그인, 로그아웃 시 리디렉션 등)는 거부할 수 없습니다. 사용되는 First and Third Party Cookies에 대한 자세한 내용은 이 링크를 따르세요.
모두 허용
항상 활성화
이 쿠키는 웹사이트 기능에 필요하며 시스템에서 끌 수 없습니다. 보통 이 쿠키는 개인정보 기본 설정, 로그인, 양식 작성 등 귀하가 요청한 서비스에 해당하는 작업에 대한 응답으로만 설정됩니다. 브라우저에서 이 쿠키를 차단하거나 알리도록 설정할 수 있지만, 그러면 사이트의 일부가 작동하지 않을 수 있습니다. 이 쿠키는 개인 식별이 가능한 정보를 저장하지 않습니다.
California Consumer Privacy Act에 따라 귀하는 제삼자에게 귀하의 개인정보를 판매하는 것을 거부할 권리가 있습니다. 이 쿠키는 분석과 맞춤형 광고를 통한 경험 개인화를 위해 정보를 수집합니다. 이 토글 스위치를 사용하여 개인정보 판매 거부 권리를 행사할 수 있습니다. 거부할 경우 맞춤형 광고를 제공할 수 없으며 귀하의 개인정보를 어떠한 제삼자에게도 넘기지 않습니다. 또한 California 소비자로서의 권리에 대해 추가 설명이 필요하면 이 Exercise My Rights 링크를 사용해 당사의 법무 부서에 문의할 수 있습니다.
브라우저에서 개인정보 보호 제어(예: 플러그인)를 활성화한 경우, 당사는 이를 유효한 판매 거부 요청으로 간주해야 합니다. 따라서 웹 전반에서 귀하의 활동을 추적할 수 없게 됩니다. 이는 귀하의 선호에 따라 광고를 개인화하는 당사의 능력에 영향을 줄 수 있습니다.
지우기
적용 취소
Consent Leg.Interest
checkbox label label
checkbox label label
checkbox label label
내 선택 확인