개발 및 AI · Clash 기술 블로그

Docker 및 WSL2에서 Clash 프록시를 사용하는 방법: 이미지 가져오기 시간 초과 및 네트워크 구성

Windows, WSL2, Docker 엔진 및 컨테이너는 각각 별도의 네트워크 환경을 사용하므로 브라우저가 작동한다고 해서 docker pull에서 프록시를 사용한다는 뜻은 아닙니다. 요청이 시작되는 위치에 따라 계층별로 설정하세요.

  • Docker
  • WSL2
  • 개발 환경
이 글의 목차

docker pull, WSL 명령, 컨테이너 요청은 서로 다른 위치에서 시작됩니다

Docker와 WSL2가 Windows의 Clash를 사용하게 하려면 터미널 하나에만 프록시를 설정해서는 안 됩니다. docker pull, WSL의 apt, 이미지 빌드 중 RUN, 시작한 컨테이너의 요청은 각각 다른 구성 요소가 보냅니다. 오류가 발생한 단계의 계층을 설정하세요.

Windows의 Clash가 127.0.0.1에서 수신한다면 Windows 로컬에서만 접근할 수 있습니다. WSL2는 기본적으로 NAT 가상 네트워크에서 실행되고 컨테이너에는 자체 네트워크 네임스페이스가 있습니다. 여기서 보이는 127.0.0.1은 보통 호스트가 아니라 자기 자신입니다.

Docker 이미지 가져오기, docker build의 다운로드, 실행 중인 컨테이너의 외부 접속도 서로 다른 구성 요소가 시작합니다. WSL shell에서 HTTP_PROXY만 export해도 Docker Desktop의 이미지 가져오기가 프록시를 사용하지 않을 수 있습니다.

오류 발생 계층

실패한 작업실제로 요청을 시작한 구성 요소
WSL의 curl / apt / git 시간 초과WSL 배포판 내부 프로세스
docker pull 시간 초과Docker Desktop 또는 Docker Engine 데몬
빌드 중 RUN apt-get 시간 초과BuildKit / 빌드 컨테이너
시작한 앱의 요청 실패실행 중인 컨테이너
Windows, WSL2, 컨테이너 사이의 프록시 경로
  1. Windows의 ClashLAN에서 접근 가능한 mixed-port 수신
  2. WSL2호스트 주소로 해당 포트 접근
  3. Docker 빌드HTTP_PROXY와 HTTPS_PROXY를 명시적으로 전달
  4. 컨테이너 내부 도구Git, npm 또는 패키지 관리자를 별도로 처리

127.0.0.1은 각 계층에서 자기 자신을 가리킵니다. 프록시 주소에는 이전 계층에서 실제로 접근 가능한 호스트 주소를 입력해야 합니다.

가상 네트워크에서 호스트 프록시 포트에 접근할 수 있어야 합니다

먼저 Clash에서 실제 HTTP 또는 mixed-port를 확인하세요. 흔한 예시는 7890이지만 클라이언트마다 다를 수 있습니다. WSL에서 호스트 IP로 접근하면 LAN 연결로 취급되므로 클라이언트가 LAN 접근을 허용하고 WSL에서 도달할 수 있는 주소에서 수신해야 합니다.

LAN 허용은 포트 접근 범위를 넓힙니다. 신뢰할 수 있는 가정 또는 조직의 사설 네트워크에서만 사용하고 Windows 방화벽에서 출발지를 제한하세요. 인증 없는 프록시를 공용 Wi-Fi나 인터넷에 노출하지 마세요. 시험 후 더 이상 필요하지 않으면 LAN 접근을 끌 수 있습니다.

WSL 기본 NAT에서는 호스트 IP를 사용하고 미러 네트워크에서는 127.0.0.1을 직접 시험할 수 있습니다

기본 NAT 모드에서는 WSL의 기본 경로에서 다음 홉을 읽을 수 있으며 보통 WSL 가상 네트워크의 Windows 호스트 주소입니다. Windows 11 22H2 이상에서 mirrored networking을 켜면 WSL이 127.0.0.1을 통해 Windows 서비스에 직접 접근할 수 있습니다.

WSL 기본 NAT 시험, 7890은 교체할 Clash 포트
HOST_IP=$(ip route show | grep -i default | awk '{ print $3 }')
CLASH_PORT=7890
echo "Windows host: $HOST_IP"
curl -I -x "http://${HOST_IP}:${CLASH_PORT}" https://example.com

이 curl이 HTTP 응답을 받은 뒤에 WSL 환경 변수를 설정할 필요가 있습니다. 프록시 포트가 바로 Connection refused를 반환하면 Clash 수신 대기, LAN 허용 또는 방화벽의 문제입니다. 포트에는 접근하지만 외부 요청이 timeout이라면 노드와 규칙을 확인하세요.

포트 접근을 확인한 뒤 WSL 명령줄에 환경 변수를 설정하세요

현재 WSL shell에 임시 적용, 7890은 포트 자리표시자
HOST_IP=$(ip route show | grep -i default | awk '{ print $3 }')
CLASH_PORT=7890
export HTTP_PROXY="http://${HOST_IP}:${CLASH_PORT}"
export HTTPS_PROXY="http://${HOST_IP}:${CLASH_PORT}"
export NO_PROXY="localhost,127.0.0.1,::1"
curl -I https://example.com

임시 변수는 터미널을 닫으면 사라져 진단에 적합합니다. apt, git 또는 curl로 같은 요청을 다시 실행하고 성공을 확인한 뒤 shell 유형에 따라 자체 시작 파일에 작성하세요.

Windows에서 지원되는 WSL 버전에서는 .wslconfig에 autoProxy=true를 사용해 Windows의 HTTP 프록시 정보를 가져올 수도 있습니다. 활성화한 뒤 WSL을 다시 시작하고 실제 변수 값을 확인하세요.

NO_PROXY에는 WSL 내부에서만 제공되는 서비스를 포함해 localhost 접근이 Windows 프록시로 우회되지 않게 하세요. 회사 내부 도메인과 사설 네트워크 범위를 넣을지는 실제 네트워크에 따라 결정합니다.

docker pull이 실패하면 Docker Desktop의 프록시 설정을 확인하세요

Docker Desktop의 이미지 가져오기와 WSL shell 명령은 서로 다른 프로세스가 시작합니다. Docker Desktop의 Settings를 열어 Resources / Proxies에 호스트에서 사용 가능한 HTTP, HTTPS 프록시를 입력하고 설정을 적용하세요. 버전에 따라 탭 이름이 조금 다를 수 있습니다.

Docker 공식 문서는 Desktop이 daemon.json의 데몬 프록시 설정을 읽지 않는다고 명시합니다. WSL 터미널에서 이미 접속할 수 있다고 Docker Desktop 자체 프록시 설정을 건너뛰지 마세요.

Docker Desktop이 아니라 독립형 Linux Docker Engine을 사용할 때만 Engine 문서에 따라 daemon.json 또는 systemd 환경에 데몬 프록시를 설정하고 Docker 서비스를 다시 시작하세요. 실행 형태부터 확인해 읽히지 않는 파일을 수정하지 않도록 합니다.

WSL curl은 성공하지만 docker pull은 계속 timeout

Docker Desktop의 Proxies 설정과 다시 시작한 뒤 상태를 확인하세요.

Docker Desktop에서 daemon.json을 수정해도 효과가 없음

Desktop 그래픽 설정으로 옮기세요. 이 제품은 daemon proxy 설정을 무시합니다.

네이티브 Linux Engine의 이미지 가져오기 실패

Windows 시스템 프록시가 아니라 daemon의 프록시 환경과 서비스 로그를 확인하세요.

이미지를 가져와도 빌드 단계와 실행 컨테이너에는 프록시가 없을 수 있습니다

Docker 클라이언트 설정은 새 컨테이너와 빌드에 프록시 환경을 자동으로 주입하거나 단일 명령에서 명시적으로 전달할 수 있습니다. 빌드에는 --build-arg, 실행에는 --env를 사용하세요. 자격 증명이 포함된 프록시 주소를 Dockerfile의 ENV로 고정하지 마세요. 이미지 기록과 설정에 남을 수 있습니다.

Docker Desktop 단일 시험, 7890은 교체할 Clash 포트
CLASH_PROXY=http://host.docker.internal:7890

docker build \
  --build-arg HTTP_PROXY="$CLASH_PROXY" \
  --build-arg HTTPS_PROXY="$CLASH_PROXY" \
  -t demo-app .

docker run --rm \
  --env HTTP_PROXY="$CLASH_PROXY" \
  --env HTTPS_PROXY="$CLASH_PROXY" \
  --env NO_PROXY="localhost,127.0.0.1" \
  demo-app

Docker Desktop은 보통 host.docker.internal로 호스트를 가리킵니다. 네이티브 Linux Engine에서의 사용 가능 여부는 환경에 따라 다르며 명확한 호스트 게이트웨이 또는 추가 host-gateway 설정이 필요합니다. 명령 실행 전에 컨테이너 내부 curl 또는 앱 로그로 이 호스트 이름과 포트에 실제로 접근할 수 있는지 검증하세요.

NO_PROXY가 빠지면 컨테이너 간 요청도 먼 경로로 우회합니다

데이터베이스 이름, Compose 서비스 이름, localhost, 내부 네트워크 범위는 보통 외부 프록시에 전달하지 않아야 합니다. 실제 내부 도메인을 NO_PROXY에 넣으면 앱이 db:5432 또는 redis:6379에 접속할 때 Windows를 한 바퀴 우회하는 일을 막을 수 있습니다. 도구별 와일드카드와 CIDR 지원이 완전히 같지 않으므로 설정 후 대상 프로세스에서 변수를 출력하고 실제 요청을 수행하세요.

프록시 주소에 사용자 이름 또는 비밀번호가 있다면 공개 compose.yaml, Dockerfile 또는 이미지에 작성하지 마세요. 로컬 환경 파일이나 프로젝트의 secret 관리 방식을 사용하고 로그에 완전한 URL이 출력되지 않게 합니다.

실제 사용 방식에 따라 네 번 검증

  • WSL의 curl이 Windows Clash를 통해 응답을 받음
  • docker pull로 작은 이미지를 가져올 수 있음
  • docker build의 네트워크 단계가 더 이상 시간 초과되지 않음
  • 실행 컨테이너에서 인터넷에 접근하고 내부 서비스에도 직접 연결할 수 있음

네 결과는 각각 WSL, Docker 엔진, 빌드 과정, 실행 컨테이너에 해당합니다. 실패한 항목이 있다면 해당 계층의 설정으로 돌아가고 이미 통과한 다른 세 계층을 다시 수정할 필요는 없습니다.

참고 자료