Skip to content

필사 모드: 셀프호스팅 배포 플랫폼 고르기 2026 — Coolify·Dokploy·CapRover·Kamal·Openship을 가르는 다섯 축

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.

들어가며 — Openship이 올라온 날, 되돌아온 같은 질문

GeekNews에 Openship이 올라왔습니다. 설명은 익숙하면서도 야심찹니다 — 저장소를 가리키면 스택을 감지해 컨테이너를 빌드하고, 도메인과 TLS를 설정하고, 배포까지 한다. 설정 파일도, 파이프라인도, YAML도 필요 없다는 것입니다. Apache 2.0 라이선스에 데스크톱 앱·웹 대시보드·CLI·REST API를 모두 제공합니다.

그리고 댓글은 늘 그렇듯 같은 질문으로 수렴합니다. "Coolify랑 뭐가 다른가." "그냥 compose 쓰면 안 되나." "이거 유지보수 누가 하나."

이 글은 그 질문에 답하기 위한 결정 프레임입니다. 기능 목록을 나열하는 비교는 도움이 되지 않습니다. 후보들은 대부분 같은 기능을 광고하고 — 깃 푸시 배포, 자동 TLS, 데이터베이스, 백업, 로그 — 실제로 3개월 뒤에 후회 여부를 가르는 것은 그 목록에 잘 안 적히는 다섯 가지입니다. 미리 밝혀 두면, 이 글의 결론은 "셀프호스팅이 좋다"도 "매니지드가 좋다"도 아닙니다. 셀프호스팅은 돈을 아끼는 대신 주의력을 지불하는 거래이고, 그 환율이 팀마다 다르다는 것입니다.

결정을 가르는 다섯 개의 축

기능표 대신 다음 다섯 질문으로 후보를 거르면 대개 둘 이하로 좁혀집니다.

첫째, 컨트롤 플레인이 어디에 사는가. 항상 떠 있는 대시보드 서버인가, 아니면 명령을 실행할 때만 존재하는 로컬 CLI인가. 이것이 "배포 시스템이 죽으면 무슨 일이 일어나는가"를 결정합니다.

둘째, 롤백이 몇 초에 몇 개의 명령인가. 새벽 3시에 되돌리는 경로가 UI 버튼 하나인지, 이전 이미지 태그를 찾아 손으로 다시 배포하는 것인지, 아니면 문서에도 없는지.

셋째, 시크릿이 어디에 어떤 형태로 저장되는가. 플랫폼의 데이터베이스에 들어간다면 그 데이터베이스의 백업과 접근 권한이 곧 시크릿의 보안 경계가 됩니다.

넷째, 노드가 하나에서 여럿으로 늘어날 때 무엇이 바뀌는가. 대부분의 도구가 "멀티 서버 지원"이라고 적지만, 실제로는 여러 대에 각각 배포하는 것과 클러스터로 다루는 것 사이에 큰 차이가 있습니다.

다섯째, 이 도구를 쓰는 데 매달 몇 시간이 드는가. 이게 매니지드 PaaS 요금과 실제로 비교되는 항목입니다.

컨트롤 플레인은 어디에 사는가

후보들은 이 축에서 뚜렷하게 두 진영으로 갈립니다.

상주 컨트롤 플레인 진영 — Coolify, Dokploy, CapRover, Openship(서버 모드). 서버에 대시보드가 항상 떠 있습니다. Coolify의 경우 컨트롤 플레인이 대시보드·내부 PostgreSQL·깃 웹훅 수신·배포 오케스트레이션을 담당하고, 워커 노드에는 SSH로 접속해 컨테이너를 띄웁니다. 컨트롤 플레인 자체는 2 vCPU / 4GB 정도로 충분하다는 것이 통상적인 권고입니다.

# Coolify 설치 — 스크립트를 먼저 읽고 실행하는 습관을 권합니다
curl -fsSL https://cdn.coollabs.io/coolify/install.sh -o /tmp/coolify-install.sh
less /tmp/coolify-install.sh
bash /tmp/coolify-install.sh

이 진영의 장점은 명확합니다. 배포하는 사람이 백엔드 엔지니어가 아니어도 됩니다. 로그를 보고, 환경 변수를 고치고, 재배포하는 일이 브라우저에서 끝납니다. 원클릭 앱 템플릿으로 Postgres·Redis·모니터링 스택을 몇 분 만에 올릴 수 있습니다.

단점도 그만큼 명확합니다. 컨트롤 플레인이 독립적으로 고장 날 수 있는 부품이 하나 늘어납니다. 대시보드가 죽어도 이미 떠 있는 앱은 계속 돌지만, 그 상태에서는 배포도 롤백도 못 합니다. 그리고 대시보드는 공격 표면이기도 합니다 — 2026년에 Coolify 관련 CVE가 보고되면서 "대시보드를 공개 인터넷에서 빼고 VPN이나 IP 허용 목록 뒤에 두라"는 권고가 반복해서 나왔습니다. 셀프호스팅 배포 도구의 대시보드를 0.0.0.0에 열어 두는 것은 사실상 루트 셸을 열어 두는 것과 같습니다.

무상주 진영 — Kamal 2, 그리고 순수 compose + SSH. 컨트롤 플레인이 없습니다. 개발자 노트북이나 CI 러너에서 명령을 실행하는 동안에만 존재하고, 끝나면 서버에는 컨테이너와 프록시만 남습니다.

# config/deploy.yml — Kamal 2
service: app
image: acme/app

servers:
  web:
    - 10.0.0.11
    - 10.0.0.12

proxy:
  ssl: true
  host: app.example.com
  healthcheck:
    path: /up
    interval: 3

registry:
  server: ghcr.io
  username: acme-ci
  password:
    - KAMAL_REGISTRY_PASSWORD

env:
  clear:
    RAILS_ENV: production
  secret:
    - DATABASE_URL
    - SECRET_KEY_BASE

accessories:
  db:
    image: postgres:17
    host: 10.0.0.20
    env:
      secret:
        - POSTGRES_PASSWORD
    directories:
      - data:/var/lib/postgresql/data
kamal setup          # 최초 1회: 도커 설치, 프록시 기동, 액세서리 생성
kamal deploy         # 빌드 → 푸시 → 서버별 롤링 교체
kamal app logs -f    # 전체 서버의 로그 스트림
kamal rollback       # 직전 정상 버전으로 되돌리기
kamal proxy reboot   # 프록시만 재시작

Kamal 2는 Traefik을 걷어내고 자체 kamal-proxy를 씁니다. 무중단 배포를 위해 만들어진 프록시라, 새 컨테이너가 헬스체크를 통과할 때까지 기다렸다가 트래픽을 넘기는 동작이 기본입니다. Rails 8의 기본 배포 도구이기도 해서 Rails 생태계에서는 사실상 표준이 됐지만, 도커 이미지를 만들 수 있으면 언어는 무관합니다.

이 진영의 장점은 고장 날 컨트롤 플레인이 없다는 것입니다. 단점은 새벽 3시에 볼 UI가 없다는 것 — 로그를 보려면 SSH나 CLI를 써야 하고, 팀에 터미널이 편하지 않은 사람이 있으면 그 사람은 배포 흐름에서 배제됩니다.

Openship은 흥미롭게도 두 모드를 다 제공합니다. 데스크톱 앱이 로컬 컨트롤 플레인이 되어 SSH로 배포하는 모드와, 서버에 상주시켜 깃 푸시 배포를 받는 모드가 따로 있습니다. 다만 이 글 시점의 공개 버전은 0.1.x 대이고 저장소 스스로 "코어는 프로덕션 준비, 활발히 개발 중"이라고 표현합니다. 멀티 노드 클러스터, 사설 네트워킹, 시각적 CI/CD 파이프라인은 아직 예정 항목으로 적혀 있습니다. 신규 프로젝트에서 시험해 볼 만하지만, 이미 돌고 있는 서비스를 옮길 대상으로 삼기에는 이릅니다.

롤백과 무중단 배포의 실제 모양

배포 도구를 고를 때 사람들이 가장 적게 확인하고 가장 자주 후회하는 항목입니다.

무중단 배포는 사실상 모든 후보가 합니다. 방식도 비슷합니다 — 새 컨테이너를 띄우고, 헬스체크를 통과하면, 프록시가 트래픽을 넘기고, 옛 컨테이너를 내립니다. Kamal은 kamal-proxy가, Coolify와 Dokploy는 Traefik 계열이, CapRover는 Docker Swarm의 롤링 업데이트가, Openship은 OpenResty 기반 엣지가 그 역할을 합니다.

차이는 롤백에서 납니다. 확인해야 할 것은 세 가지입니다.

  • 이전 이미지가 서버에 남아 있는가. 남아 있지 않으면 롤백은 "레지스트리에서 다시 받기"가 되고, 레지스트리가 접근 불가면 롤백 자체가 불가능해집니다. Kamal은 이전 컨테이너를 남겨 두어 kamal rollback이 즉시 동작합니다.
  • 롤백에 필요한 정보가 UI나 CLI에서 바로 보이는가. 이전 배포의 이미지 태그를 찾기 위해 레지스트리 콘솔을 뒤져야 한다면 그건 롤백 경로가 없는 것입니다.
  • 마이그레이션은 어떻게 되는가. 이건 어떤 도구도 해결해 주지 않습니다. 앞뒤 호환되는 마이그레이션을 쓰고 배포와 스키마 변경을 분리하는 것은 여전히 애플리케이션 쪽 설계 문제입니다.

세 번째가 핵심입니다. 컨테이너 롤백이 30초에 끝나도 스키마를 되돌릴 수 없으면 실제 복구 시간은 30초가 아닙니다. 도구 선택보다 앞서는 결정입니다.

한 가지 더. 롤백을 실제로 연습해 보지 않은 롤백 기능은 없는 것과 같습니다. 스테이징에서 일부러 나쁜 배포를 하고 되돌리는 훈련을 분기에 한 번은 해야 합니다. 백업 복구도 마찬가지입니다 — 백업이 돌고 있다는 사실과 복구가 된다는 사실은 별개입니다.

시크릿 — 가장 자주 미끄러지는 곳

여기서 후보들의 성격 차이가 가장 크게 드러납니다.

대시보드형 도구는 대개 시크릿을 자체 데이터베이스에 저장합니다. UI에서 입력하고, 배포 시 환경 변수로 주입합니다. 편하지만 결과적으로 그 데이터베이스가 시크릿 저장소가 됩니다. 확인할 것은 셋입니다 — 저장 시 암호화가 되는가, 그 암호화 키는 어디에 있는가(같은 서버에 있다면 실질적 보호는 제한적입니다), 대시보드 백업에 시크릿이 그대로 들어가는가.

Kamal은 반대 방향입니다. 시크릿을 자기가 보관하지 않고, 배포 시점에 로컬에서 읽어 컨테이너에 주입합니다. .kamal/secrets 파일이 그 통로인데, 이 파일 자체를 커밋하지 않고 외부 볼트에서 채우는 것이 권장 방식입니다.

# .kamal/secrets — 값이 아니라 "가져오는 방법"을 적는다
KAMAL_REGISTRY_PASSWORD=$(op read "op://infra/ghcr/token")
DATABASE_URL=$(op read "op://infra/app/database-url")
SECRET_KEY_BASE=$(op read "op://infra/app/secret-key-base")
# CI에서는 같은 자리를 CI 시크릿으로 채운다
# .kamal/secrets.production
KAMAL_REGISTRY_PASSWORD=$KAMAL_REGISTRY_PASSWORD
DATABASE_URL=$DATABASE_URL

이 방식의 장점은 시크릿의 단일 출처가 배포 도구 바깥에 남는다는 것입니다. 배포 플랫폼을 갈아치워도 시크릿 관리 체계는 그대로입니다. 단점은 한 겹 더 설정해야 한다는 것과, 볼트가 죽으면 배포가 막힌다는 것입니다.

어느 쪽을 고르든 지켜야 할 최소선은 같습니다. 시크릿을 이미지에 굽지 말고, 빌드 로그에 찍히지 않게 하고, 로테이션 절차를 문서로 남기고, 배포 도구의 백업에 시크릿이 평문으로 들어가는지 한 번은 직접 확인하는 것입니다.

후보 비교

도구컨트롤 플레인롤백시크릿 저장 위치멀티 노드상태 / 라이선스
Coolify상주 대시보드 + SSH 워커UI에서 이전 배포 선택플랫폼 DB컨트롤 플레인 1대 + SSH 워커 N대성숙, 커뮤니티 큼 / Apache 2.0
Dokploy상주 대시보드(경량)UI에서 이전 배포 선택플랫폼 DBDocker Swarm 기반활발, Coolify보다 가벼움 / Apache 2.0
CapRover상주 대시보드이전 이미지 태그로 재배포플랫폼 설정Docker Swarm 네이티브오래됨, 안정적 / Apache 2.0
Kamal 2없음(CLI 실행 시에만)kamal rollback 즉시외부 볼트에서 배포 시 주입서버 목록에 나열, 롤링 배포성숙, Rails 8 기본 / MIT
Openship데스크톱·서버·클라우드 선택문서상 지원플랫폼 관리예정 항목0.1.x, 초기 / Apache 2.0
compose + 러너없음(CI가 실행)직접 작성해야 함CI 시크릿 또는 볼트서버마다 별도 구성도구 없음, 전부 자작

표를 한 줄로 요약하면 이렇습니다. 팀에 터미널이 편하지 않은 사람이 있으면 대시보드형, 전원이 백엔드 엔지니어면 Kamal이나 compose. 이 기준 하나가 실제 만족도의 대부분을 설명합니다.

순수 compose 조합도 진지한 선택지입니다. 서버에 docker compose와 systemd 유닛을 두고, GitHub Actions 셀프호스티드 러너나 웹훅 수신기가 git pull && docker compose up -d를 실행하는 구성입니다. 서비스가 한두 개고 배포가 주 1회라면 이 구성이 가장 적은 개념으로 가장 오래 갑니다. 다만 무중단 배포와 롤백은 직접 만들어야 하고, 그 부분을 안 만들면 배포할 때마다 몇 초씩 끊깁니다. 그 몇 초를 감당할 수 있는지가 판단 기준입니다.

돈이 아니라 주의력을 지불한다

셀프호스팅 논의에서 가장 흔한 왜곡은 비용 비교를 요금만으로 하는 것입니다. 매니지드 PaaS 월 200달러와 VPS 월 40달러를 비교하면 결론은 뻔합니다. 그런데 그 200달러에는 우리가 하지 않던 일이 포함돼 있습니다.

셀프호스팅으로 넘어오면 다음이 우리 일이 됩니다.

  • OS 보안 패치와 재부팅 일정
  • 도커 엔진과 배포 플랫폼 자체의 업그레이드(그리고 업그레이드가 깨졌을 때의 복구)
  • 디스크 사용량 관리 — 오래된 이미지와 빌드 캐시가 디스크를 채워 배포가 멈추는 일은 정말 흔합니다
  • 백업 스케줄과 복구 훈련
  • 대시보드 접근 통제, VPN 또는 허용 목록 유지
  • 인증서 갱신 실패 시 대응(자동화돼 있어도 실패는 납니다)
  • 그리고 이 모든 것에 대한 온콜

시간으로 환산하면 팀마다 다르지만, 서비스 몇 개 규모에서 정상 상태일 때 월 2~4시간, 무언가 깨진 달에는 하루가 통째로 들어가는 것이 흔한 범위입니다. 엔지니어 시간을 시간당 얼마로 잡느냐에 따라 이 계산은 쉽게 뒤집힙니다.

그래서 정직한 결론은 이렇습니다.

  • 셀프호스팅이 유리한 경우: 인프라를 다룰 줄 아는 사람이 이미 팀에 있고, 서버가 어차피 필요하고(백그라운드 워커, 상시 실행 프로세스, GPU), 데이터 위치에 대한 요구가 있고, 트래픽 대비 매니지드 요금이 비대해진 경우.
  • 매니지드가 유리한 경우: 팀이 작고 제품에 집중해야 하고, 트래픽이 예측 불가능하고, 온콜을 세울 사람이 없고, 배포가 잦고, 규정 요구가 없는 경우.
  • 최악의 경우: 셀프호스팅으로 옮겼는데 아무도 유지보수를 맡지 않는 경우. 이건 매니지드보다도 비쌉니다 — 6개월 뒤 아무도 업그레이드하지 못하는 플랫폼 위에서 프로덕션이 돌게 됩니다.

컨테이너 런타임을 옮기는 일 자체의 실무 이슈는 도커에서 팟맨으로 편을 참고하세요.

마치며 — 유지보수를 맡을 사람의 이름을 먼저 적으세요

Openship 같은 새 도구가 계속 나오는 이유는 이 문제가 아직 잘 풀리지 않았기 때문입니다. 매니지드 PaaS의 편의와 자기 서버의 통제권을 동시에 갖고 싶다는 요구는 정당하고, Coolify·Dokploy·Kamal은 각자 다른 지점에서 그 요구에 답합니다.

  • 후보를 다섯 축으로 거르세요 — 컨트롤 플레인 위치, 롤백 경로, 시크릿 위치, 멀티 노드, 월간 운영 시간. 기능표는 그다음입니다.
  • 대시보드형을 고른다면 대시보드를 공개 인터넷에서 빼세요. VPN이나 IP 허용 목록 뒤가 기본입니다.
  • Kamal이나 compose를 고른다면 롤백과 로그 조회를 문서로 남기세요. UI가 없는 만큼 절차가 지식이 됩니다.
  • Openship은 0.1.x 대입니다. 신규 사이드 프로젝트에서 먼저 만나 보고, 멀티 노드가 필요한 워크로드는 로드맵이 실제로 도착한 뒤에 고려하는 편이 맞습니다.
  • 도입 문서 첫 줄에 이 플랫폼의 업그레이드를 책임질 사람의 이름을 적으세요. 그 이름이 비어 있으면 도구 비교는 의미가 없습니다.

셀프호스팅은 비용을 없애지 않습니다. 청구서에서 캘린더로 옮길 뿐입니다.

참고 자료

현재 단락 (1/115)

[GeekNews에 Openship](https://github.com/oblien/openship)이 올라왔습니다. 설명은 익숙하면서도 야심찹니다 — 저장소를 가리키면 스택을 감...

작성 글자: 0원문 글자: 6,940작성 단락: 0/115