VPS로 Docker 셀프 호스팅 시작하기 2026: docker-compose + Caddy로 SaaS 대체 앱 운영까지

이 글에는 제휴 링크(affiliate link)가 포함되어 있습니다. Vultr·DigitalOcean 가입 링크를 사용하시면 추가 크레딧 혜택이 제공되며, 블로그 운영에 도움이 됩니다. Docker 자체는 모든 VPS 공급자에서 동일하게 동작합니다.

2026년, VPS 한 대만 있으면 유료 SaaS를 대체하는 셀프 호스팅(self-hosted) 앱을 직접 운영할 수 있습니다(서버 사양이 허용하는 범위에서). 북마크 관리(Linkding), 비밀번호 관리자(Vaultwarden), 메모(Trilium), 미디어 갤러리(Immich), 마크다운 노트(Joplin)까지 — 매월 내던 구독료를 VPS 한 대 비용으로 통합하는 셈입니다. 그 핵심에 Docker가 있습니다. 이 가이드에서는 VPS에 Docker를 설치하고, docker-compose로 앱을 올리며, 도메인+SSL까지 연결하는 한국 실전 셀프 호스팅 입문 과정을 정리합니다.

이 글은 VPS 실전 가이드 시리즈 #7입니다. 서버가 아직 없다면 VPS 3대 비교 2026에서, 배포 기초는 Vultr 워드프레스 배포 튜토리얼에서 확인하세요. 서버 보안은 VPS 보안 완벽 가이드가 선행되어야 합니다.

왜 Docker로 셀프 호스팅인가?

VPS로 Docker 셀프 호스팅 시작하기 2026: docker-compose + Caddy로 SaaS 대체 앱 운영까지

과거엔 서버에 앱 하나를 올릴 때마다 의존성 충돌, 버전 관리, 설정 파일 분산에 시달렸습니다. Docker는 이 문제를 “앱과 모든 설정을 하나의 격리된 컨테이너로 포장”해 해결합니다. 셀프 호스팅 입문자가 Docker를 선택하는 이유는 다음과 같습니다.

  • 재현성: 동일한 컨테이너는 어떤 VPS에서도 똑같이 동작한다
  • 격리: 여러 앱이 서로 충돌하지 않고 한 서버에 공존한다
  • 복구: 설정을 코드(compose 파일)로 관리해 서버 이전이 훨씬 쉬워진다
  • 생태계: Docker Hub 등에 공개된 수많은 이미지를 그대로 가져다 쓴다

특히 docker-compose를 쓰면 “명령어 한 줄로 전체 서비스 구성을 올리고 내리는” 것이 가능합니다. 이것이 셀프 호스팅을 대중화한 핵심 도구입니다.

1단계: VPS에 Docker + Compose 설치

Ubuntu/Debian 기준으로 Docker 공식 설치 스크립트로 Docker와 docker compose 플러그인을 설치합니다. 서버는 보안 가이드를 따라 기본 세팅(방화벽, sudo 사용자)이 끝난 상태라고 가정합니다.

# 패키지 최신화
sudo apt update && sudo apt upgrade -y

# Docker 공식 설치 스크립트: 내려받아 내용을 확인한 뒤 실행
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh ./get-docker.sh --dry-run
sudo sh get-docker.sh

# 현재 사용자를 docker 그룹에 추가 (sudo 없이 실행)
sudo usermod -aG docker $USER
newgrp docker

# 설치 확인
docker --version
docker compose version

Docker 공식 문서는 이 편의 스크립트가 설치 옵션을 거의 바꿀 수 없고 최신 안정 버전을 그대로 설치해 의도치 않은 메이저 업그레이드가 생길 수 있다고 안내합니다. 운영 서버라면 Docker 공식 apt 저장소 설치 방법을 권장하며, 어느 쪽이든 업그레이드는 테스트 환경에서 먼저 확인하세요.

docker 그룹에 사용자를 추가하면 매번 sudo를 치지 않아도 됩니다. (보안상 root 권한과 동일하므로 신뢰할 수 있는 사용자에게만 부여하세요.)

실전 팁: 설치 직후 docker run hello-world로 정상 작동을 확인하세요. “Hello from Docker!” 메시지가 나오면 설치가 완료된 것입니다.

2단계: docker-compose로 첫 앱 올리기 (Linkding)

코딩 인터페이스가 떠 있는 노트북 위에 두 손을 올리고 타이핑하는 모습

실습용으로 가벼운 북마크 관리자 Linkding을 올려봅니다. 디렉토리를 만들고 docker-compose.yml을 작성합니다.

mkdir -p ~/docker/linkding && cd ~/docker/linkding
nano docker-compose.yml

아래 내용을 붙여넣습니다.

services:
  linkding:
    container_name: linkding
    image: sissbruecker/linkding:latest
    ports:
      - "127.0.0.1:9090:9090"
    volumes:
      - ./data:/etc/linkding/data
    restart: unless-stopped

이제 서비스를 백그라운드로 시작합니다.

docker compose up -d
docker compose ps          # 실행 상태 확인
docker compose logs -f     # 로그 실시간 확인 (Ctrl+C로 종료)

처음 접속하려면 관리자 계정이 필요합니다. Linkding 공식 문서(User Setup)의 방법대로 아래 명령을 실행하면 비밀번호를 물어봅니다.

docker compose exec linkding python manage.py createsuperuser --username=내아이디 --email=내메일@example.com

이 설정은 포트를 서버 안(127.0.0.1)에만 열기 때문에 서버 밖에서는 서버IP:9090으로 접속되지 않습니다. 서버에서 curl -I http://127.0.0.1:9090으로 응답을 확인하고, 외부 접속은 다음 단계의 리버스 프록시로 엽니다. 9090 포트를 그대로 외부에 노출하면 위험하기 때문입니다.

3단계: 리버스 프록시 + SSL로 도메인 연결 (Caddy)

녹슨 금속 게이트를 잠근 자물쇠 클로즈업

여러 컨테이너를 각각 다른 포트로 열어두면 관리가 어렵고 보안도 취약합니다. 리버스 프록시로 80/443 포트 하나에서 모든 앱을 도메인별로 라우팅하는 것이 정석입니다. 여기서는 자동 SSL이 내장된 Caddy를 사용합니다 (Nginx + Certbot 조합보다 설정이 훨씬 단순합니다).

mkdir -p ~/docker/caddy && cd ~/docker/caddy
nano docker-compose.yml
services:
  caddy:
    container_name: caddy
    image: caddy:2
    restart: unless-stopped
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    network_mode: host

volumes:
  caddy_data:
  caddy_config:

같은 디렉토리에 Caddyfile을 만듭니다 (bookmarks.도메인.com는 실제 도메인으로 교체).

bookmarks.example.com {
    reverse_proxy localhost:9090
}

이제 Caddy를 띄웁니다. network_mode: host이면 Caddy가 서버의 80·443 포트를 직접 사용하므로 ports: 항목은 필요하지 않습니다.

docker compose up -d
docker compose logs -f caddy    # SSL 발급 로그 확인

Caddy는 시작하면서 인증서를 자동으로 발급하고 만료 전에 알아서 갱신합니다(기본 발급처는 Let’s Encrypt와 ZeroSSL, Caddy 공식 문서). 도메인이 서버 IP를 가리키고 80·443 포트가 열려 있다면 발급이 끝난 뒤 https://bookmarks.example.com으로 Linkding에 접속할 수 있습니다. 방화벽(UFW)에서는 80·443만 열어두세요. 9090은 127.0.0.1에만 바인딩했으므로 외부에 노출되지 않습니다(Docker가 공개한 포트는 UFW 규칙을 우회하므로 UFW만으로는 막을 수 없습니다 — Docker 공식 문서).

추천 셀프 호스팅 앱 — SaaS 대체 매트릭스

손에 들고 있는 스마트폰 화면에 앱 아이콘이 보이고 배경에 노트북이 있는 사진

한 대의 VPS에 올려두면 유용한 인기 셀프 호스팅 앱을 정리합니다. 모두 Docker로 배포 가능합니다.

앱 대체하는 SaaS 용도 난이도
Vaultwarden 1Password / Bitwarden 유료 비밀번호 관리자 ★★☆
Immich Google Photos / iCloud 사진 자동 백업·갤러리 ★★☆
Joplin Server Evernote / Notion 마크다운 노트 동기화 ★☆☆
Linkding Raindrop.io 등 북마크 서비스 북마크 관리 ★☆☆
Nextcloud Google Drive / Dropbox 클라우드 스토리지 ★★★
Paperless-ngx 문서 관리 SaaS 영수증·문서 OCR 보관 ★★☆
AdGuard Home 광고 차단 유료 DNS 네트워크 광고 차단 ★☆☆

이 앱들로 구독 서비스 일부를 대체하면 구독료를 줄일 수 있습니다. 단, 셀프 호스팅은 ‘백업 책임’이 사용자에게 있으므로 반드시 정기 백업을 구성하세요. 백업 전략은 VPS 백업 완벽 가이드에서 다룹니다.

4단계: 업데이트·백업·운영 수칙

Docker 셀프 호스팅을 장기 운영하려면 몇 가지 습관이 필요합니다.

이미지 업데이트 — 정기적으로 최신 이미지로 갱신합니다.

cd ~/docker/linkding
docker compose pull            # 최신 이미지 받기
docker compose up -d           # 컨테이너 재생성
docker image prune -f          # 오래된 이미지 정리

데이터 백업 — 앱 데이터는 ./data 같은 볼륨 디렉토리에 있으므로, 이 디렉토리만 백업하면 전체 상태가 보존됩니다. compose 파일과 데이터 디렉토리를 함께 보관하면 서버 이전 시 그대로 복원됩니다.

리소스 관리 — docker stats로 각 컨테이너의 CPU/메모리 사용량을 모니터링하세요. 1GB RAM 서버에 무거운 앱(Nextcloud 등)을 여러 개 올리면 메모리 부족이 발생합니다. Immich는 공식 요구사항이 CPU 최소 2코어·권장 4코어라서 1 vCPU 최저가 플랜에는 맞지 않습니다(Immich 문서). 이럴 때는 2GB 이상 플랜으로 업그레이드하거나 Swap을 추가합니다.

비용 비교: 셀프 호스팅 vs SaaS 구독

손에 들린 투명 유리병에 SAVINGS 라벨이 붙어 동전이 가득 담긴 모습

구성 월 비용
VPS $5 플랜 + 가벼운 앱(Linkding 등) 월 $5~6
지금 구독 중인 서비스의 합계(각 서비스 공식 요금 기준) 사용자마다 다름
절감 효과 구독료 합계 − VPS 월 요금

공급자를 아직 고르지 않았다면, 한국 접속 속도가 빠른 Vultr(서울 리전, $100 크레딧) 또는 DigitalOcean을 추천합니다. 가성비가 최우선이라면 Hetzner로 시작하세요.

마무리: VPS 한 대로 끝없는 자유

Docker와 docker-compose, 리버스 프록시(Caddy) 세 가지만 익히면 VPS 한 대가 곧 나만의 개인 클라우드가 됩니다. 유료 SaaS 구독을 하나둘 대체하면 초기 학습 시간을 금방 회수할 수 있고, 데이터 주권까지 확보할 수 있습니다. 핵심은 compose 파일로 설정을 코드화해두는 것 — 서버가 바뀌어도 같은 compose 파일과 데이터 폴더로 환경을 다시 만들 수 있습니다.

시작은 가벼운 앱 하나(Linkding 등)로 해보세요. 익숙해지면 Vaultwarden, Immich 순으로 영역을 넓히면 됩니다. 그리고 잊지 말 것 — 백업은 셀프 호스팅의 생명줄입니다. VPS 백업 완벽 가이드로 자동 백업까지 세팅하면 비로소 안심하고 운영할 수 있습니다.

관련 글