게시일: · 수정일:

원격 서버의 Docker에 대한 접근과 관리

원격 서버의 Docker에 대한 접근과 관리 들어가며 저는 로컬 개발 환경인 macOS에서 Docker를 native하게 실행시키지 못한다는 이유로 홈 서버(Ubuntu)에 Docker를 올려 원격으로 사용하고 있습니다. macOS 환경 유저분들은 저와 비슷한 경우가 많을 거라고...

작성자: gymynnym

원격 서버의 Docker에 대한 접근과 관리

들어가며

저는 로컬 개발 환경인 macOS에서 Docker를 native하게 실행시키지 못한다는 이유로 홈 서버(Ubuntu)에 Docker를 올려 원격으로 사용하고 있습니다. macOS 환경 유저분들은 저와 비슷한 경우가 많을 거라고 생각합니다. 따라서, 이번 아티클은 제가 원격으로 Docker를 사용하기 위해 어떤 도구와 방법을 사용했는 지와 간단한 사용법을 소개하겠습니다.

lazydocker: 관리 도구

저는 Docker 관리 시, lazydocker를 애용합니다. 이는 Docker 및 Docker Compose 관리 TUI 툴이며, Dockge 또는 Portainer와 같은 WebUI 기반 무거운 관리 툴을 사용하지 못하는 환경에서 사용하기 좋습니다.

Lazydocker Demo
Lazydocker Demo

단, 다음과 같은 이유로 제 환경에서 lazydocker를 사용하려면, Docker를 로컬 시스템에서 접근할 수 있어야 했습니다.

SSH 주소 기반 접근을 시도해봤지만, 비밀번호 없이 SSH 키를 사용하는 접근 방식은 지원하지 않았습니다. 관련 이슈에 대한 기능 추가 PR이 존재하고 문제가 해결된 포크 레포지토리도 있는 듯 보이지만, 어째서인지 PR Merge가 이루어지지 않고 있습니다 :(

따라서, 조금 귀찮지만 재밌는 접근 방법을 사용해 보겠습니다.

Unix Domain Socket

먼저 Docker가 사용하는 통신 방법인 Unix Domain Socket에 대해 알아보겠습니다.

일반적인 TCP/IP 소켓 통신 같은 경우에는 네트워크 통신을 사용하기에, ip:port 기반의 주소 시스템을 사용합니다. 하지만 로컬 시스템에서만 통신하다면, 굳이 네트워크 스택을 탈 필요가 없으며, 이런 경우를 위해 Unix 시스템에서는 Unix Domain Socket을 사용할 수 있습니다.

Unix Domain Socket은 네트워크 스택을 타지 않기에 목적지 주소로 ip:port 대신 .sock 파일의 경로를 사용합니다.

$ ls -l docker.sock
srw-rw---- 1 root docker 0 Jan  1 00:00 docker.sock

파일 타입은 s(socket)이며, 파일 시스템 접근 권한으로 소켓에 대한 접근 권한 제어가 가능합니다. 다음은 이 docker.sock 파일을 외부에서 접근하는 방법에 대해서 알아보겠습니다.

SSH 로컬 포워딩

SSH는 로컬 포워딩이라는 기능을 제공하며, 이 기능은 SSH 터널을 통한 스트림 포워딩 기능입니다. 단순히 설명하자면, SSH 터널을 사용하는 TCP 포트나 Unix Domain Socket 포워딩 기능입니다. 이를 활용해 원격 서버의 TCP 포트를 활용하는 서비스나 Unix Domain Socket을 로컬에서 실행 중인 것처럼 보이게 만들 수 있습니다.

$ ssh -N -L /tmp/docker.sock:/var/run/docker.sock myuser@myhost

SSH의 -L 옵션을 통해 로컬 포워딩이 가능하며, -N 옵션은 원격 명령을 실행하지 않고(쉘 없이) 터널 연결만 유지한다는 의미입니다. 이를 통해 로컬의 /tmp/docker.sock에 원격 서버의 /var/run/docker.sock을 포워딩할 수 있습니다.

하지만, 매번 로컬에서 원격 Docker에 접근할 때 마다, 명령어 입력은 번거롭기에, ~/.ssh/config 파일을 편집해 이를 선언화 해보겠습니다.

Host *
	ControlMaster auto
	ControlPath ~/.ssh/cm-%r@%h:%p
	ControlPersist 10m
...

위 설정은 SSH 멀티플렉싱을 활성화합니다.

SSH 멀티플렉싱이란 하나의 TCP 연결에서 여러 개의 SSH 세션을 공유하는 기술입니다.

  • ControlMaster auto : 첫 접속 시 마스터 연결을 생성하고, 이후 접속은 이를 공유
  • ControlPath : 공유 연결을 관리하기 위한 소켓 파일 경로
  • ControlPersist 10m : 마지막 터널 사용이 끝난 후, 10분 간 백그라운드에서 유지 (재접속 속도 향상)
...
Host myhost
	HostName x.x.x.x
	Port 22
	User myuser
	IdentityFile ~/.ssh/id_ed25519
	LocalForward /tmp/docker.sock /var/run/docker.sock
	StreamLocalBindUnlink yes
	ExitOnForwardFailure yes
  • LocalForward [local] [remote] : 로컬의 [local]에 들어오는 요청은 원격의 [remote]로 전달
    • 예제에서는 Unix Domain Socket을 사용했지만, TCP 포트도 사용 가능
  • StreamLocalBindUnlink yes : 로컬에 소켓 파일이 이미 존재하는 경우, 덮어쓰기
  • ExitOnForwardFailure yes : 포워딩에 실패할 경우, SSH 접속 종료 (오류 출력)

접근에 사용될 사용자는 docker 그룹에 속해 있거나, root 계정이어야 합니다.

$ ssh -fN myhost

설정이 완료되었다면, 위 명령어를 통해 SSH 터널을 생성합니다. (-f 옵션을 통해 백그라운드에서 실행)

$  ssh -O check myhost # ControlMaster가 살아 있는 지
$  ssh -O exit myhost # ControlMaster 즉시 종료

이후 SSH -O 옵션을 통해, SSH 멀티플렉싱 마스터(ControlMaster)에게 명령할 수 있습니다.

lazydocker 접속하기

lazydocker는 1차적으로 DOCKER_HOST 환경변수를 통해 docker.sock을 찾습니다. 따라서 방금 로컬에 포워딩한 docker.sock의 경로를 설정해줘야 합니다.

export DOCKER_HOST=unix:///tmp/docker.sock

이때 Unix Domain Socket을 알리기 위해 unix:// 스키마 접두사를 사용합니다.

이제 모든 설정은 완료되었으며, 외부 시스템에 설치된 Docker를 lazydocker로 접근할 수 있습니다!

Tori: 모니터링 도구

최근 웹 서핑 중, Tori 라는 프로젝트를 발견했습니다.

Tori Demo
Tori Demo

Tori는 Go 언어로 작성된 경량 Docker 서버 모니터링 TUI 툴이며 다음과 같은 기능을 제공합니다:

  • 호스트 메트릭 : CPU, 메모리, 디스크 등 사용량 추적
  • Docker 컨테이너 모니터링 : stauts, health, 로그 등 추적
  • 알림 : SMTP, Webhook 기반 알림
  • 기타

현재(2026년 2월) 기준, 개발 및 테스트 단계이며 기존 모니터링 도구들을 완전히 대체하지 못합니다!

Tori는 다음과 같은 구성 요소를 가집니다:

  • tori agent : 서버에서 상시 메트릭 수집과 모니터링하는 역할
    • Unix Domain Socket으로 통신
    • SQLite를 사용해 메트릭, 로그 저장
  • tori client : tori.sock에 접근하기 위한 클라이언트
    • Bubbletea 기반 TUI
    • SSH 터널로 접근하며, SSH-like 설정 지원

tori agent

tori agent의 설치를 위해 Docker Compose를 사용해 보겠습니다.

docker-compose.yml

services:
  tori-agent:
    container_name: tori-agent
    image: ghcr.io/thobiasn/tori-cli:latest
    restart: unless-stopped
    pid: host
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - /proc:/host/proc:ro
      - /sys:/host/sys:ro
      - /run/tori:/run/tori
      - ./config.toml:/etc/tori/config.toml
      - ./data:/var/lib/tori

볼륨 설정을 통해, 다음을 설정합니다:

  • 호스트의 메트릭을 수집하기 위해 /proc, /sys 접근 허용
  • 모니터링을 위한 docker.sock에 대한 접근 허용
  • tori.sock 관리를 위한 /run/tori 경로 마운트
  • 설정 파일(config.toml) 및 SQLite 데이터 마운트

config.toml

[storage]
path = "/var/lib/tori/tori.db"
retention_days = 7

[socket]
path = "/run/tori/tori.sock"

[host]
proc = "/host/proc"
sys = "/host/sys"

[docker]
socket = "/var/run/docker.sock"

[collect]
interval = "10s"
  • [storage] : 메트릭, 로그 수집용 SQLite 설정
  • [socket] : Unix Domain Socket 위치 설정
  • [host] : 호스트 메트릭 수집 설정
  • [docker] : Docker Unix Domain Socket 위치 설정
  • [collect] : 수집 설정
[alerts.container_unhealthy]
condition = "container.health == 'unhealthy'"
for = "30s"
severity = "critical"
actions = ["notify"]

[alerts.container_down]
condition = "container.state == 'exited'"
for = "0s"
severity = "critical"
actions = ["notify"]

[alerts.container_restart_loop]
condition = "container.restart_count > 5"
severity = "critical"
actions = ["notify"]

[alerts.host_high_cpu]
condition = "host.cpu_percent > 90"
for = "1m"
severity = "warning"
actions = ["notify"]

[alerts.host_high_memory]
condition = "host.memory_percent > 90"
for = "1m"
severity = "warning"
actions = ["notify"]

[alerts.host_high_swap]
condition = "host.swap_percent > 85"
for = "30s"
severity = "warning"
actions = ["notify"]

[alerts.host_disk_full]
condition = "host.disk_percent > 90"
for = "0s"
severity = "critical"
actions = ["notify"]

[alert] 설정은 특정 상황에서 경고를 남기는 룰을 지정하며, 위 예제는 개인적으로 사용 중인 룰입니다. 이는 사용하시는 환경에 맞게 따로 설정해주시면 됩니다.

[[notify.webhooks]]
enabled = true
url = "https://discord.com/api/webhooks/..."
template = '{"content": "**{{.Subject}}**\n{{.Body}}"}'

[notify] 설정을 통해 알림 시스템을 설정할 수 있으며, 개인적으로 Discord 알림화를 자주 사용하기에, Discord 웹훅을 등록했습니다. SMTP를 통한 이메일 알림화도 가능합니다.

모든 설정이 끝나면 docker compose up을 통해 tori agent를 실행해주세요.

tori client

tori client란 방금 설치한 tori agent에 접속할 TUI 클라이언트이며, 다음과 같은 방법으로 설치가 가능합니다:

$ curl -fsSL https://raw.githubusercontent.com/thobiasn/tori-cli/main/deploy/install.sh | sh -s -- --client

설치가 끝났다면, tori myuser@myhost 또는 ~/.config/tori/config.toml 파일에 서버를 설정해줄 수 있습니다.

마치며

이외에도 Docker 이미지 탐색 툴인 dive, 원격 서버에 Docker 이미지를 전달하는 unregistry 등 다양한 도구들이 있지만, 이번 아티클에선 접근과 관리 그리고 모니터링을 중점으로 다뤄봤습니다.

단, 이 아티클에서는 docker.sock을 로컬로 포워딩하고 있으며, 이는 원격 서버의 Docker를 제어할 수 있는 권한을 부여하는 것이며, Docker 특성상 권한 상승에 매우 취약합니다. 예를 들어, 모든 파일 시스템을 마운트하여 접근할 수 있으며, 이는 사실상 root 권한을 부여하는 것과 같습니다.

만약 비슷한 환경을 구축하고자 하는 경우, 꼭 신뢰할 수 있는 환경에서만 세팅하는 것을 권장합니다.