SSH 연결 위에 다른 프로토콜의 트래픽을 안전하게 실어 나르는 기법입니다. SSH가 이미 암호화, 인증, 무결성 검증을 모두 처리해주기 때문에 별도의 TLS 설정 없이도 안전한 통신이 가능합니다.
💻 방법 1: SSH 로컬 포워딩으로 소켓 터널링 (가장 기본적인 방법)
원격 서버의 Docker 소켓을 로컬 포트로 포워딩하는 방식입니다.
# 로컬 포트 2375를 원격 서버의 Docker 소켓으로 포워딩
ssh -L localhost:2375:/var/run/docker.sock user@REMOTE_HOST -fN
각 옵션 설명:
-L localhost:2375:/var/run/docker.sock : 로컬 2375 포트를 원격 소켓으로 연결
-f : 백그라운드에서 실행
-N : 원격 명령 실행 없이 터널만 유지
터널이 열린 후에는 환경변수를 설정해 Docker CLI가 이 터널을 사용하게 합니다:
export DOCKER_HOST=tcp://localhost:2375
docker ps # 원격 서버의 컨테이너 목록 출력
docker images # 원격 서버의 이미지 목록 출력
이 방식의 장점은 인터넷에 포트를 노출하지 않으면서, SSH의 검증된 인증 방식(키, MFA 등)을 그대로 활용한다는 것입니다.
터널 종료 시:
# 터널 프로세스 찾기
ps aux | grep ssh
# PID로 종료
kill $PID
# DOCKER_HOST 해제
unset DOCKER_HOST
💻 방법 2: DOCKER_HOST에 ssh:// 스킴 사용 (Docker 18.09+)
Docker 18.09 버전부터는 SSH를 네이티브로 지원합니다. 터널을 별도로 만들 필요 없이 DOCKER_HOST 환경변수에 바로 SSH 주소를 지정할 수 있습니다.
# 환경변수 방식 (임시)
export DOCKER_HOST=ssh://docker-user@host1.example.com
docker ps
docker run -d nginx
# 사용 후 원래대로 복원
unset DOCKER_HOST
이 방식은 context를 별도로 생성하지 않아도 되므로 다른 엔진과 임시로 연결할 때 유용합니다.
⚠️ 중요: ssh:// 방식은 반드시 SSH 키 인증이 필요합니다. 패스워드 인증은 Docker에서 지원되지 않으며, DOCKER_HOST 기반 설정에서는 불가능합니다.
SSH 키 등록:
# 키 생성
ssh-keygen -t ed25519 -C "docker-remote-key"
# 원격 서버에 공개 키 등록
ssh-copy-id docker-user@host1.example.com
# ssh-agent에 키 추가
ssh-add ~/.ssh/id_ed25519
SSH 연결 최적화 (~/.ssh/config):
Host docker-remote
HostName host1.example.com
User docker-user
IdentityFile ~/.ssh/id_ed25519
ControlMaster auto
ControlPath ~/.ssh/control-%C
ControlPersist yes
ControlMaster와 ControlPersist 설정을 통해 하나의 SSH 연결을 여러 docker CLI 호출에서 재사용할 수 있어, 매번 핸드셰이크를 반복하지 않아도 됩니다.
이후 훨씬 간결하게 사용 가능합니다:
export DOCKER_HOST=ssh://docker-remote
docker ps
💻 방법 3: docker context로 원격 엔진 관리 (운영 추천)
여러 원격 서버를 자주 오가며 관리한다면 docker context가 가장 깔끔한 방법입니다.
# 원격 컨텍스트 생성
docker context create my-remote-engine \
--docker "host=ssh://docker-user@host1.example.com" \
--description "Production Server"
# 컨텍스트 목록 확인
docker context ls
# 컨텍스트 전환
docker context use my-remote-engine
# 이제 모든 docker 명령이 원격 서버에서 실행됨
docker ps
docker run -d --name web nginx
# 로컬로 복귀
docker context use default
원격 엔진 컨텍스트를 생성한 뒤 docker context use로 활성화하면 VS Code 및 Docker CLI 모두 해당 원격 머신 컨텍스트를 사용하게 됩니다.
💻 방법 4: CI/CD 파이프라인에서 활용
GitHub Actions, GitLab CI, Jenkins 등에서 원격 Docker 호스트에 배포할 때 유용한 패턴입니다.
#!/bin/bash
# deploy.sh — CI/CD 원격 배포 스크립트
SSH_USER="deploy"
SSH_HOST="prod.example.com"
# 환경변수만 설정하면 끝 (SSH 키는 CI 시크릿에 등록)
export DOCKER_HOST="ssh://${SSH_USER}@${SSH_HOST}"
# 이미지 pull 및 컨테이너 재배포
docker pull myapp:latest
docker stop myapp || true
docker rm myapp || true
docker run -d \
--name myapp \
--restart unless-stopped \
-p 80:8080 \
myapp:latest
echo "✅ 배포 완료"
unset DOCKER_HOST
# 반드시 먼저 known_hosts에 등록
ssh-keyscan -H host1.example.com >> ~/.ssh/known_hosts
# 또는 한 번 직접 SSH 접속하여 확인
ssh docker-user@host1.example.com
② SSH 키 패스프레이즈 문제
키에 패스프레이즈가 설정되어 있으면 docker 명령마다 비밀번호를 요청합니다. ssh-agent에 미리 키를 등록해야 합니다.
eval $(ssh-agent -s)
ssh-add ~/.ssh/id_ed25519
# 등록 확인
ssh-add -l
③ 원격 사용자의 docker 그룹 미등록
원격 호스트에서 SSH_USER는 Docker 소켓에 접근 권한이 있는 사용자여야 합니다 (예: docker 그룹 멤버).
# 원격 서버에서 실행
sudo usermod -aG docker docker-user
# 그룹 변경 적용 (로그아웃 후 재접속 필요)
④ TCP 포트를 인터넷에 직접 노출하지 말 것
# ❌ 절대 금지 — 포트를 모든 IP에 오픈
"hosts": ["unix:///var/run/docker.sock", "tcp://0.0.0.0:2375"]
# ✅ 루프백만 허용 (로컬 SSH 터널 용도)
"hosts": ["unix:///var/run/docker.sock", "tcp://127.0.0.1:2375"]
✅ 정리 / 마무리
방법
장점
적합한 상황
ssh -L 포트 포워딩
가장 유연, 세밀한 제어
일시적 연결, 레거시 환경
DOCKER_HOST=ssh://
설정 간단, 추가 소프트웨어 불필요
빠른 임시 연결, CI/CD
docker context
멀티 서버 관리에 최적화
운영 환경, 일상적 원격 관리
핵심을 다시 한번 정리하면:
Docker 소켓은 절대 인터넷에 직접 노출하지 않는다
SSH 터널은 추가 인프라 없이 바로 사용 가능한 가장 안전한 원격 접근 방법
Docker 18.09 이상에서는 ssh:// 스킴이 네이티브로 지원되어 구성이 매우 단순해졌다
운영 환경에서는 docker context로 원격 호스트를 체계적으로 관리하자
다음 단계로는 TLS 상호 인증 방식 또는 Tailscale/ZeroTier 같은 Zero-Trust 네트워크를 활용한 Docker 원격 접근 방식도 검토해 볼 만 합니다.