Docker pull 타임아웃? Windows·macOS에서 Docker Desktop을 Clash HTTP/HTTPS 프록시로 연결하는 단계
이 글은 어떤 상황에 맞을까요?
이미 Clash 계열 클라이언트로 브라우저·일부 앱의 외부 접속은 잘 되는데, Docker Desktop만 docker pull·이미지 빌드 중 레이어 다운로드에서 시간 초과가 나거나, 컨테이너 안에서 apt·curl·npm만 극도로 느릴 때 읽기 좋은 글입니다. 원인을 “구독이 나빠서” 한 줄로 줄이기보다, 트래픽이 거치는 층을 나누어 보면 해결이 훨씬 빨라집니다. 첫째는 Windows·macOS 호스트의 시스템 프록시, 둘째는 Docker 엔진(데몬)이 레지스트리에 붙을 때 쓰는 HTTP/HTTPS 프록시, 셋째는 Windows에서 Docker가 쓰는 WSL2 백엔드의 라우팅·DNS, 넷째는 컨테이너 프로세스가 상속하는 HTTP_PROXY·HTTPS_PROXY·NO_PROXY입니다.
Clash를 처음 켜는 전체 흐름은 문서·시작 가이드를, 투명 프록시 개념은 TUN 모드 가이드를 참고하면 이 글과 맥락이 이어집니다. Windows에서 Clash와 WSL2를 같이 쓸 때 호스트는 되는데 리눅스만 끊기는 패턴은 WSL2 라우팅·MTU 가이드가 다루는 축과 겹치므로, 본문에서는 도커 엔진·프록시 설정에 초점을 맞춥니다.
참고: docker pull은 브라우저가 아니라 Docker 데몬이 수행합니다. 호스트에서 Clash 시스템 프록시만 켜 두었다고 해서, 데몬이 자동으로 같은 프록시를 쓰지 않는 경우가 많습니다. 반대로 엔진 프록시만 맞춰 두고 컨테이너 내부 앱은 HTTP_PROXY를 안 받으면, 빌드 단계와 런타임 단계에서 증상이 갈라져 보입니다.
네 가지 층을 먼저 구분하기
첫째, 호스트 OS에서 Edge·Chrome이 가는 경로와 Docker CLI가 붙는 대상은 다릅니다. CLI는 로컬의 Docker API에만 말하고, 실제 레지스트리 접속은 엔진이 합니다. 둘째, HTTP/HTTPS 프록시는 레지스트리가 HTTPS여도 CONNECT를 통해 중계할 수 있어, Clash의 mixed-port(HTTP 프록시 겸 SOCKS가 있는 포트)를 주소로 넣는 방식이 흔합니다. 셋째, Windows Docker Desktop은 기본적으로 WSL2 위에서 엔진이 돌아가므로, 프록시를 넣어도 가상 네트워크·DNS 문제가 남아 있으면 여전히 타임아웃이 납니다. 이 경우 앞서 인용한 WSL2 글의 라우팅·MTU 점검이 선행되어야 합니다. 넷째, Dockerfile의 RUN apt-get이나 컨테이너 셸의 curl은 해당 컨테이너 네임스페이스의 환경 변수를 봅니다. 빌드 시에는 docker build --build-arg로, 실행 시에는 compose의 environment나 docker run -e로 넘겨야 합니다.
이 구분이 서 있으면 “같은 노드인데 왜 브라우저만 빠르지?” 같은 혼란이 줄어듭니다. 다음 절부터는 Clash 쪽에서 프록시 주소를 확정한 뒤, 플랫폼별로 Docker Desktop에 싣는 순서입니다.
1단계: Clash에서 프록시 주소·포트 확정하기
Clash Verge·FlClash 등 GUI에서는 포트 화면에서 mixed-port 또는 HTTP 포트를 확인합니다. 로컬에서만 쓸 때는 127.0.0.1과 해당 포트 조합이 일반적입니다. 예를 들어 mixed-port가 7890이면 엔진에 넣을 값은 http://127.0.0.1:7890 형태가 됩니다. Allow LAN을 켠 상태에서 다른 기기용으로 0.0.0.0에 바인딩했다면, Docker VM이 보는 루프백과 맞지 않을 수 있으니, Docker 전용으로는 127.0.0.1 기준을 유지하는 편이 안전합니다.
인증이 필요한 상용 HTTP 프록시가 아니라면 사용자 이름·비밀번호 없이 위 형태만으로 충분한 경우가 많습니다. 프록시를 켠 뒤 호스트 터미널에서 curl -x http://127.0.0.1:포트 https://example.com -I로 한 번 응답 헤더가 오는지 확인하면, Clash 층이 준비된 것입니다.
2단계: Windows Docker Desktop에 엔진 프록시 넣기
Docker Desktop을 연 뒤 Settings에서 Resources 아래 Proxies(또는 버전에 따라 Manual proxy configuration)를 찾습니다. Manual proxy를 켜고 Web Server (HTTP)와 Secure Web Server (HTTPS)에 앞서 확정한 http://127.0.0.1:포트를 동일하게 넣습니다. Bypass 또는 no_proxy에 localhost, 127.0.0.1, ::1, 그리고 사내 레지스트리·허브 미러 호스트를 필요하면 추가합니다. 이렇게 하면 Docker 엔진이 Docker Hub·GHCR 등 외부 레지스트리로 나갈 때 프록시를 타도록 요청할 수 있습니다.
적용 후에는 Docker Desktop을 재시작하거나 Apply & Restart를 눌러 엔진이 새 설정을 읽게 하세요. 그다음 PowerShell이나 CMD에서 docker pull hello-world처럼 작은 이미지로 시험합니다. 여전히 느리면 WSL2 쪽 네트워크가 원인인지 확인해야 하므로, 같은 시점에 WSL 배포판 안에서 curl로 외부 접속이 되는지, /etc/resolv.conf가 기대한 DNS를 가리키는지 살펴보는 것이 좋습니다. 여기서 막히면 프록시 문자열만 바꿔서는 해결되지 않으며, WSL2 라우팅·MTU 글의 순서와 병행하는 것이 합리적입니다.
고급 사용자는 WSL2 내부의 데몬 설정 파일에 proxies 블록을 직접 쓰는 방식도 문서화되어 있으나, Docker Desktop 버전마다 UI와 파일 위치가 달라질 수 있어, 가능하면 공식 UI의 Proxies를 먼저 맞추는 것을 권합니다.
3단계: macOS Docker Desktop에 엔진 프록시 넣기
macOS에서도 흐름은 같습니다. 메뉴 막대의 Docker 아이콘에서 Settings → Resources → Proxies로 들어가 Manual proxy를 활성화하고, HTTP·HTTPS에 동일한 http://127.0.0.1:포트를 지정합니다. Bypass proxy settings for these hosts & IPs에 로컬과 사내 도메인을 넣어 두면 불필요한 홉을 줄일 수 있습니다. Apple Silicon과 Intel 모두에서 호스트의 Clash는 보통 127.0.0.1로 접근 가능하므로, Linux VM 안의 또 다른 IP를 적을 필요는 대개 없습니다.
적용 후 docker pull로 확인합니다. macOS 방화벽이나 보안 소프트웨어가 로컬 프록시 포트의 연결을 막는 경우는 드물지만, 그럴 때는 해당 제품의 예외 목록을 점검합니다. VPN과 Clash를 동시에 켜 두었다면 한쪽만 켠 상태에서 재현 여부를 먼저 비교해 보세요.
4단계: 빌드와 컨테이너 실행 환경 변수
엔진 프록시를 맞춰도 Dockerfile의 RUN 단계에서만 실패하는 경우가 있습니다. 빌드는 빌더가 수행하며, 호스트의 프록시 환경 변수가 자동으로 항상 전달되지는 않기 때문입니다. 예를 들어 docker build --build-arg HTTP_PROXY=http://127.0.0.1:7890 --build-arg HTTPS_PROXY=http://127.0.0.1:7890 ...처럼 build-arg로 넘기고, Dockerfile에서 ARG HTTP_PROXY를 선언한 뒤 ENV로 내려주는 패턴이 흔합니다. Compose를 쓰면 build.args와 서비스 environment에 같은 값을 반복해 줄 수 있습니다.
실행 중인 컨테이너에 대해서는 docker run -e HTTP_PROXY=... 또는 Compose의 environment에 HTTP_PROXY, HTTPS_PROXY, NO_PROXY를 명시합니다. NO_PROXY에는 레지스트리 미러·사내 Git·Artifact 저장소 호스트를 빠뜻리지 않는 것이 좋습니다. 그렇지 않으면 사내 주소까지 불필요하게 프록시를 한 바퀴 돌다 실패하는 일이 생깁니다.
팁: 언어 런타임·패키지 매니저는 http_proxy 소문자 환경 변수를 읽는 경우도 있습니다. 팀 표준으로 대문자·소문자 둘 다 넣어 두면 스크립트별 차이를 줄일 수 있습니다.
5단계: 레지스트리 미러·DNS·방화벽
프록시가 정상인데도 특정 지역에서 Docker Hub가 느리다면, 조직에서 허용하는 경우 레지스트리 미러를 엔진 설정에 추가하는 방법이 병행됩니다. 이는 Clash와 무관한 축이지만, “프록시를 태웠는데도 느리다”는 체감을 줄이는 데 도움이 됩니다. 반대로 DNS가 불안정하면 CONNECT 단계에서 이미 지연되므로, Clash의 DNS 모드·fake-ip 설정은 TUN 가이드의 DNS 절과 함께 보는 것이 좋습니다.
회사 네트워크에서는 보안 장비가 프록시 없는 직접 TLS를 차단하는 경우도 있어, 그때는 IT 정책에 맞는 공식 프록시 주소를 써야 합니다. Clash는 개인 환경에서 로컬 프록시를 제공하는 도구로 이해하고, 직장 장비에서는 내부 가이드를 우선하세요.
한 페이지 체크리스트
- 호스트에서
curl -x로 Clash HTTP 프록시가 실제로 응답하는지 확인한다. - Docker Desktop Proxies에 HTTP·HTTPS 동일 주소를 넣고 재시작 후
docker pull로 검증한다. - Windows에서는 WSL2만 이상하면 라우팅·MTU·DNS를 별도 글 순서로 점검한다.
- 빌드 실패 시
--build-arg와 DockerfileARG/ENV전달을 확인한다. - 컨테이너 내부만 실패하면
HTTP_PROXY·NO_PROXY런타임 환경을 확인한다. - 사내 호스트는
NO_PROXY에 넣어 불필요한 프록시 우회를 막는다.
주의: 알 수 없는 출처의 프록시 설정 스크립트나 이미지는 보안 위험이 있습니다. 조직망에서는 정책을 위반하지 않도록 하고, 신뢰할 수 있는 클라이언트와 구독만 사용하세요.
마무리
정리하면, Docker Desktop에서 docker pull과 빌드·컨테이너 네트워크 문제는 Clash 한 줄 설정으로 동시에 풀리지 않는 경우가 많습니다. HTTP/HTTPS 프록시를 엔진에 싣고, WSL2·컨테이너 환경 변수·NO_PROXY를 각각 확인해야 레지스트리 타임아웃과 내부 도구 실패를 동시에 줄일 수 있습니다. 같은 Clash·Mihomo 계열이라도 규칙과 DNS 표현이 유연해, 개발 트래픽만 골라 프록시에 태우는 설계가 가능합니다.
지금 환경에 맞는 클라이언트를 설치·검증하려면 Clash를 무료로 다운로드한 뒤, 위 체크리스트 순서대로 Docker 층을 맞춰 보시길 권합니다. 호스트와 컨테이너가 같은 인터넷을 쓴다고 가정하면 오히려 시간만 늘어납니다. 층을 나누어 보면 원인이 빨리 좁혀집니다.