네트워크 기술

Docker Hub 이미지 pull이 멈추거나 실패할 때: VPN·DNS 경로별 CLI 진단 (2026)

docker pull 한 줄이 몇 분째 «Pulling fs layer»에서 진행 바만 깜빡이거나, 아예 타임아웃으로 끊길 때가 있습니다. 원인 후보는 한 번에 너무 많아 보이지만, 실무에서는 ① 이름을 IP로 바꿀 수 있는지(DNS)② 레지스트리·CDN까지 패킷이 통하는지(경로·방화벽·VPN)만 먼저 갈라 내면 범위가 빠르게 줄어듭니다. 이 글은 명령줄 개발자가 자주 맞닥뜨리는 Docker Hub 시나리오를 전제로, VPN을 켠 상태와 끈 상태를 교차 확인하면서 문제를 좁히는 순서를 정리했습니다.


목차

  1. 증상으로 보는 첫 분류: DNS인지 전송인지
  2. Docker가 실제로 쓰는 DNS 확인하기
  3. 레지스트리·CDN까지 HTTPS 레벨에서 통과 테스트
  4. VPN ON/OFF A·B 테스트 해석법
  5. 분할 라우팅으로 «레지스트리만 직통» 같은 선택지
  6. MTU·HTTP 프록시·회사 방화벽 같은 2차 후보
  7. 실무 체크리스트: 순서대로 밟을 단계
  8. 일반 VPN과 비교해 보고 DVDVPN으로 마무리하는 방법

증상으로 보는 첫 분류: DNS인지 전송인지

Docker Hub 기준 이미지를 받아 오려면 대개 다음 이름들을 순차적으로 만납니다. 매니페스트와 토큰 교환을 위한 registry-1.docker.io 계열, 인증과 레이어 서명 교환에 쓰이는 auth.docker.io, 그리고 실제 바이너리 레이어가 놓인 CDN 호스트 이름들입니다. 사용자에게 보이는 로그는 «Downloading … »처럼 한 줄로 단순해 보여도, 뒤에서는 여러 TLS 세션과 리다이렉트가 이어집니다.

그래서 «오래 pending»이라는 말만으로는 원인을 특정하기 어렵습니다. 우선 로그 문구를 대략 세 갈래로 나누어 보는 편이 낫습니다. 첫째, 해석 단계에서 더 진행이 없고 호스트 이름 오류·임시 실패 메시지가 섞인다면 DNS 또는 로컬 방화벽의 UDP 53 차단 가능성을 의심합니다. 둘째, 매니페스트는 받았는데 특정 레이어 바이트 수치만 움직이지 않으면 CDN 방향 대역폭·패킷 손실·중간 프록시 쪽으로 방향을 돌립니다. 셋째, VPN을 켠 직후에만 증상이 나타나면 풀터널 때문에 회선 특유의 최적 경로가 깨졌거나, 반대로 회사 정책상 허브 노드를 거치며 속도 제한이 걸린 경우를 함께 생각합니다.

이후 섹션에서 소개할 명령은 모두 로컬 쉘에서 실행 가능한 것을 예로 들지만, 원격 빌드 서버나 CI 러너라면 같은 검사를 그 머신 안에서 반복해야 합니다. 개발 노트북에서는 되는데 파이프라인만 실패한다면, 거의 항상 러너 쪽 DNS 또는 egress 규칙이 다르기 때문입니다.

Docker가 실제로 쓰는 DNS 확인하기

운영체제에서 브라우저가 잘 열린다고 해서 Docker 데몬이 같은 리졸버를 쓴다고 가정하면 안 됩니다. 특히 Linux에서는 systemd-resolved의 스텁 리스너(127.0.0.53)와 컨테이너 브리지 네트워크가 얽히면서, 호스트에서는 되는데 데몬만 다른 네임서버를 바라보는 상황이 종종 나옵니다. macOS나 Windows의 Docker Desktop 역시 가상화 레이어 뒤에 자체 DNS 전달 규칙을 두므로, «내 터미널에서 되네»만으로 덜어내기 어렵습니다.

실무용 빠른 점검은 다음 순서입니다. 우선 호스트 OS 기준으로 registry-1.docker.ioauth.docker.io에 대해 dig 또는 nslookup으로 응답 시간과 응답 코드를 확인합니다. 응답 자체가 느리거나 서버 실패(SERVFAIL)가 반복되면 ISP나 내부 DNS 포워더 문제일 가능성이 큽니다. 다음으로 Docker 설정 파일(daemon.json)의 dns 항목이 있는지 확인합니다. 회사 표준 이미지처럼 강제로 내부 리졸버만 허용해 두었다면, 그 리졸버가 외부 프록시를 타야 하는 구조인데 라우팅이 빠져 있으면 바로 지금 증상으로 이어집니다.

컨테이너가 빌드 중이라 호스트만 보고 결론 내리기 어렵다면, 아주 작은 베이스 이미지 대신 docker run --rm busybox nslookup registry-1.docker.io 같은 방식으로 실제 컨테이너 네트워크 네임스페이스 안에서 같은 질의를 한 번 더 해 보는 것도 방법입니다. 여기서만 실패한다면 브리지 DNS 포워딩이나 사용자 정의 네트워크 설정을 의심해야 합니다.

DNS와 관련해 자주 빠지는 착각 하나를 짚자면, VPN 제품이 앱 스토어 설명에 적어 둔 «DNS 보호» 문구가 곧바로 Docker 문제를 해결한다는 기대입니다. 실제로는 어떤 트래픽에 어떤 리졸버가 적용되는지가 제품마다 다르고, CLI 도구는 브라우저보다 낮은 레벨에서 바인딩되기도 합니다. 프로토콜 전환으로 회선 특성이 바뀌는 경우도 있으므로, 같은 노드에서 UDP와 TCP 트래픽 처리 차이를 함께 보는 편이 안전합니다. 배경을 더 깊게 보려면 VPN 프로토콜 비교: WireGuard, OpenVPN, 독자 프로토콜은 어떤 상황에 맞을까에서 핸드셰이크·차단 회피 관점을 먼저 정리해 두면 이후 진단이 수월합니다.

레지스트리·CDN까지 HTTPS 레벨에서 통과 테스트

DNS가 정상이라도 TLS 핸드셰이크나 중간 프록시에서 멈출 수 있습니다. 브라우저 탭으로 Docker 웹사이트가 열린다고 레지스트리 API 엔드포인트까지 같은 경로로 통한다고 단정하면 안 됩니다. 호스트에서 curl -Iv https://registry-1.docker.io/v2/처럼 최소한의 엔드포인트에 요청을 걸어 보고, 서버 인증서 교환까지 몇 초 안에 끝나는지 확인합니다. 여기서 시간이 길게 늘어지면 회사 SSL 검사 장비나 투명 프록시가 개입했을 가능성을 의심합니다.

Docker 자체 로그(docker system events 또는 데스크톱 UI의 진단 패널)를 함께 켜 두면, 레이어 하나가 특정 URL에서만 반복 재시도하는 패턴이 보일 때가 있습니다. 이때는 CDN 호스트 이름별로 curl 테스트를 나누어 실행해 보고, 하나의 호스트 이름만 지연된다면 지역 POP 선택 문제나 특정 대역에 대한 shaping을 의심합니다. 반대로 모든 호스트에서 비슷하게 느리다면 물리 회선 혹은 VPN 터널 전체의 병목일 확률이 높습니다.

인증 단계에서만 오래 걸린다면 사용자 이름으로 로그인한 경우 토큰 엔드포인트가 추가로 호출됩니다. 개인 계정 대신 조직 레지스트리 미러를 쓰는 구조라면 미러 주소 자체의 DNS와 TLS를 별도 트랙으로 검증해야 합니다. 이 글은 Docker Hub 공개 레이어를 주 대상으로 설명하지만, 같은 진단 골격은 사설 Harbor나 클라우드 제공 레지스트리에도 그대로 이식할 수 있습니다.

VPN ON/OFF A·B 테스트 해석법

VPN을 사용 중이라면 가장 설득력 있는 실험은 단순합니다. 같은 명령을 VPN 연결 전후로 각각 실행하고, DNS 응답 시간·curl 첫 바이트 도달 시간·docker pull의 초당 메가바이트 추세를 비교합니다. 여기서 중요한 것은 한 번 성공했다고 원인이 확정되지 않는다는 점입니다. 레이트 리밋이나 CDN 라운드 로빈 때문에 간헐적으로만 재현되는 경우도 많습니다. 가능하면 각 상태에서 세 번씩 반복하고, 중간에 docker system prune로 캐시 간섭을 줄일지 여부를 통제해야 합니다.

VPN을 끄면 빨라지고 켜면 느려진다면 원인 후보는 크게 두 가지로 접습니다. 첫째, 선택한 출구 지역이 레지스트리 CDN 입장에서 비효율적인 지역이라 RTT와 재전송이 늘어난 경우입니다. 이때는 다른 도시나 국가 노드를 순차 적용해 보는 것만으로도 개선 여부를 빠르게 확인할 수 있습니다. 둘째, 풀터널 구조 때문에 원래 직접 붙어야 할 피어링 지점을 우회하여 불필요하게 긴 AS 경로를 도는 경우입니다. 이 경우에는 분할 라우팅으로 레지스트리 관련 호스트 이름 또는 대역만 회선 바깥으로 빼는 전략이 현실적인 타협이 됩니다.

반대로 VPN을 켜야만 pull이 된다면, 거주 지역이나 회선 종류에서 Docker 관련 SNI나 특정 포트가 간헐적으로 막히는 상황을 의심합니다. 이 패턴은 «항상 막힘»이 아니라 피크 시간대에만 나타나 디버깅을 어렵게 만듭니다. 이럴 때는 같은 시간대에 VPN 없이 traceroute(또는 ICMP가 막혔다면 TCP 기반 경로 추적 도구)를 남겨 두고, VPN 연결 시 홉 구조가 어떻게 바뀌는지 비교하면 다음 장비 담당자에게 넘길 근거 자료가 됩니다.

분할 라우팅으로 «레지스트리만 직통» 같은 선택지

모든 트래픽을 VPN으로 몰아넣으면 보안상 단순해 보이지만, 대용량 레이어 다운로드처럼 지연과 처리량이 동시에 중요한 작업에서는 오히려 생산성이 떨어질 수 있습니다. 특히 원격 출구가 해외인데 레지스트리 CDN 엣지가 근처 데이터센터에 있다면, 풀터널이 역으로 우회 경로를 길게 만드는 사례가 있습니다.

DVDVPN 데스크톱 클라이언트는 도메인·IP 단위로 어떤 트래픽을 터널에 넣을지 고르는 분할 터널링 편집기를 제공합니다. 개발자에게 자주 쓰이는 패턴은 두 가지입니다. 하나는 기본은 VPN으로 두고 *.docker.io 또는 회사에서 허용한 레지스트리 호스트 묶음만 예외로 직통에 두는 방식이고, 다른 하나는 반대로 평소에는 직통을 유지하다가 특정 클라우드 API 호스트만 VPN으로 보내는 방식입니다. 어떤 쪽이든 규칙 한 줄을 빠뜨렸을 때 트래픽이 암호화되지 않은 채 나간다는 리스크를 항상 염두에 두어야 하므로, 변경 후에는 반드시 출구 IP와 DNS 응답을 다시 확인합니다.

Windows 환경에서 분할 규칙을 어디에 두어야 할지 감이 오지 않는다면 Windows VPN 분할 터널링: 앱별 직연결·VPN 라우팅 설정 (2026)의 단계 설명을 먼저 따라 가며 패턴을 익힌 뒤, 동일한 호스트 이름 세트를 Docker 장애 재현 환경에 적용해 보는 흐름을 추천합니다. 모바일 위주 독자라면 앱 단위 분할과의 차이를 이해하기 위해 Android VPN 설정 전체 가이드: 설치, 노드 선택 및 권한 안내와 비교해 보는 것도 도움이 됩니다.

MTU·HTTP 프록시·회사 방화벽 같은 2차 후보

1차로 DNS와 TLS를 통과했는데도 중간에 세션이 끊긴다면 다음 후보를 순서 없이 점검합니다. VPN 인터페이스의 MTU 불일치는 대용량 응답 본문을 받을 때 조각화 문제로 표면화되며, 증상은 간헐적 타임아웃과 패킷 손실로 나타납니다. 클라이언트 설정에서 조각 허용 옵션이나 낮은 MTU 프로파일을 제공한다면 시험 삼아 적용해 볼 가치가 있습니다.

HTTP_PROXY 환경 변수가 쉘에만 걸려 있고 Docker 데몬에는 전달되지 않으면, 빌드 단계와 pull 단계의 동작이 서로 달라져 보입니다. 반대로 프록시가 모든 트래픽을 가로채도록 되어 있는데 인증서 스토어가 컨테이너 내부와 불일치하면 TLS 검증 실패로 멈춥니다. 회사 환경에서는 보안 장비가 특정 User-Agent나 SNI를 기준으로 스로틀링하는 경우도 있어, 동일 조건을 브라우저와 CLI에서 재현할 수 있는지를 나란히 적어 두면 원인 분류가 빨라집니다.

마지막으로 로컬 방화벽 규칙과 클라우드 보안 그룹을 의심합니다. 원격 서버에서만 실패한다면 해당 서버의 egress 규칙에서 443은 열려 있지만 UDP 기반 DNS만 막혀 있는 패턴, 또는 특정 지역 IP 대역만 허용하는 패턴을 특히 자주 봅니다.

실무 체크리스트: 순서대로 밟을 단계

여기까지 읽었다면 이미 감이 오겠지만, 헬프데스크 티켓을 남길 때나 나중에 나 자신을 위해 메모를 남길 때는 짧은 번호 목록이 가장 실용적입니다. 아래 순서는 대부분의 Docker Hub CLI 장애에서 재현성을 높이도록 배열했습니다. 특정 단계에서 시간이 확 줄거나 에러 메시지가 바뀌었다면, 그 지점을 원인 트리의 분기로 기록해 두세요.

  1. 증상 캡처: 정확한 이미지 이름·태그, 마지막으로 출력된 로그 세 줄, 로컬 시각, VPN 연결 여부를 한 블록으로 저장합니다. 간헐 장애라면 더 중요합니다.
  2. 호스트 DNS 스냅샷: registry-1.docker.ioauth.docker.io에 대해 응답 코드와 응답 시간을 적습니다. 내부 DNS를 경유한다면 그 포워더 주소도 함께 적습니다.
  3. TLS 스냅샷: 레지스트리 루트 경로에 대한 curl -Iv 결과에서 연결 수립까지 걸린 초 단위와 인증서 체인 요약을 남깁니다.
  4. VPN A·B: 같은 세션을 VPN 연결 전후로 각각 한 번씩 실행하고, 가능하면 노드를 두 곳 이상 바꿔 반복합니다. 출구 국가만 다른 동일 제품 내 비교가 가장 해석이 쉽습니다.
  5. 데몬 설정 확인: daemon.json의 DNS·프록시· insecure-registry 목록을 확인합니다. 표준화된 조직 이미지라면 파일 내용을 변경하지 말고 발견 사항만 보고합니다.
  6. 네트워크 스코프 분리: 문제가 로컬 데스크톱에서만인지, CI 러너에서만인지, 특정 클라우드 리전에서만인지 범위를 적습니다. 범위가 좁혀질수록 방화벽 팀에 넘길 패킷 캡처 범위도 줄어듭니다.
  7. 분할 규칙 시험: 정책이 허용한다면 레지스트리 호스트 일부만 직통으로 빼 보거나 반대로 전부 터널로 모아 보고, 각각에서 ②~④를 다시 실행합니다.

이 체크리스트를 한 번 통과하면 «Docker가 느리다»는 막연한 불만이 DNS 지연인지 TLS 중간 장비인지 VPN 우회 경로인지로 바뀝니다. 팀 내 위키에 그대로 붙여 넣어 두고, 레지스트리 미러나 자격 증명 도입 같은 구조 변경이 있을 때마다 하단 몇 줄만 업데이트하면 장기적으로 시간을 아낍니다.

추가로 CI 파이프라인 안에서는 로컬과 다른 네임서버가 기본으로 잡히는 경우가 많습니다. 러너 공급자 문서에 «기본 DNS가 무엇인지, 사용자 지정이 가능한지»를 먼저 확인하고 위 순서를 적용하면 불필요한 재시도 루프를 줄일 수 있습니다.

일반 VPN과 비교해 보고 DVDVPN으로 마무리하는 방법

문제 해결용 글이지만 현실을 외면하면 안 되는 점은, 모든 상용 VPN이 개발자 도구의 세밀한 라우팅 요구를 동일하게 만족시키지는 않는다는 것입니다. 일부 제품은 앱 목록만 간단히 고를 수 있게 해 줄 뿐 레지스트리 호스트 단위 예외를 표현하기 어렵고, 다른 제품은 재연결 때마다 DNS 캐시가 초기화되어 진단 세션 자체가 불안정해집니다. 과장된 마케팅 문구보다 규칙 표현이 명료하고 재현 가능하게 적용되는지가 장시간 pull 작업에는 더 중요합니다.

DVDVPN은 Windows·macOS·Linux·모바일까지 한 계정으로 관리 부담을 줄이고, 노드를 바꿔 가며 CDN까지의 경로를 빠르게 비교할 수 있습니다. 신규 가입 시 제공되는 무료 트래픽으로 이미지 한두 번 받아 보는 수준의 테스트를 무리 없이 할 수 있어, 장애 재현이 간헐적인 경우에도 여러 출구를 순회하며 패턴을 모으기 좋습니다. 카드를 요구하지 않고 시작할 수 있다는 점은 일회성 진단 세션을 열기에도 부담이 적습니다.

지금 환경에서 Docker Hub 접근이 특정 노드에서만 불안정하다면, 우선 클라이언트에서 노드를 바꿔 보고, 필요하면 분할 규칙으로 레지스트리 호스트만 회선에 남기는 조합까지 시험해 보세요. 최신 빌드는 다운로드 페이지에서 받을 수 있으며, 계정이 없다면 무료 가입 후 같은 절차를 반복하면 변경 전후를 더 깔끔하게 비교할 수 있습니다.

레지스트리 경로를 바꿔 가며 테스트하고 싶다면

무료 트래픽으로 VPN 노드를 바꿔 재현해 보세요

신규 사용자에게 무료 트래픽이 제공되며, 분할 규칙과 함께 개발용 회선을 정리하기 좋습니다.

무료 계정 만들기 클라이언트 다운로드