본문 바로가기
DEV & DevOps/Backend

홈서버 필수 서비스 한방에 띄우기 — Docker Compose 실전편 [Mac Mini 홈서버 완전 정복 4/10]

by Hoft 2026. 3. 29.

🖥️ Mac Mini 홈서버 완전 정복 시리즈

4/10 — 홈서버 필수 서비스 한방에 띄우기

Docker Compose 실전편

3편에서 OrbStack으로 Docker 환경을 구축하고 첫 컨테이너(Nginx)를 띄워봤습니다. 이제 진짜 홈서버다운 서비스들을 올릴 차례입니다. 이 글에서는 하나의 Docker Compose 파일로 4개 필수 서비스를 한번에 배포합니다 — 대시보드, Docker 관리, 자동 업데이트, 상태 모니터링. 서비스 간 네트워크 설계, .env 파일로 설정 관리, 로그 전략까지 실전 수준으로 다룹니다.

📌 사전 준비

  • 2편까지의 macOS 초기 세팅 완료 (SSH, 슬립 차단, 고정 IP)
  • 3편의 OrbStack(또는 Docker Desktop/Colima) 설치 완료
  • docker compose version 명령이 정상 동작하는 상태

1. 배포할 4개 서비스 소개

홈서버를 운영하려면 서비스 자체 외에도 "서비스를 관리하는 서비스"가 필요합니다. 아래 4개는 홈랩의 기본 인프라 역할을 합니다.

🏠 Homepage — 홈랩 대시보드

모든 서비스의 상태와 링크를 한 화면에 보여주는 대시보드입니다. 100개 이상의 서비스 위젯을 지원하고, YAML 파일로 설정합니다. Docker 컨테이너 상태를 실시간으로 표시할 수 있어서, 홈서버의 "컨트롤타워" 역할을 합니다.

포트: 3000 | 이미지: ghcr.io/gethomepage/homepage

🐳 Portainer CE — Docker 웹 관리

Docker 컨테이너, 이미지, 볼륨, 네트워크를 웹 브라우저에서 관리하는 도구입니다. 터미널 없이도 컨테이너를 시작/중지하고, 로그를 확인하고, 새 컨테이너를 배포할 수 있습니다. CLI에 익숙하더라도, 전체 상태를 한눈에 파악하는 데 유용합니다.

포트: 9443 (HTTPS) | 이미지: portainer/portainer-ce

🔄 Watchtower — 컨테이너 자동 업데이트

실행 중인 컨테이너의 이미지를 주기적으로 확인하고, 새 버전이 있으면 자동으로 업데이트합니다. 이미지 다운로드 → 컨테이너 중지 → 새 이미지로 재시작까지 자동으로 처리합니다.

포트: 없음 (백그라운드) | 이미지: containrrr/watchtower

⚠️ Watchtower 참고사항 — 원본 containrrr/watchtower 프로젝트가 2025년 12월에 아카이브(읽기 전용)되었습니다. 마지막 안정 버전인 v1.7.1은 여전히 Docker Hub에서 사용 가능하고, 홈랩 환경에서 문제없이 동작합니다. 활발히 유지보수되는 포크 버전(nickfedor/watchtower)도 있으니 필요 시 이미지만 교체하면 됩니다. 이 글에서는 원본 이미지를 기준으로 설명합니다.

📊 Uptime Kuma — 서비스 상태 모니터링

서비스가 살아있는지 주기적으로 체크하고, 다운되면 알림을 보냅니다. HTTP, TCP, Ping, DNS 등 다양한 프로토콜을 지원합니다. 깔끔한 UI로 가동률(Uptime)을 시각화해주며, Discord, Telegram, Slack 등 70개 이상의 알림 채널을 지원합니다.

포트: 3001 | 이미지: louislam/uptime-kuma

2. 디렉토리 구조 설계

홈랩이 커질수록 디렉토리 구조가 중요해집니다. 처음부터 체계적으로 잡으면 나중에 백업, 마이그레이션, 문제 추적이 훨씬 쉬워집니다.

~/homelab/
├── core/                      # 이번 편에서 만들 핵심 인프라
│   ├── docker-compose.yml     # 4개 서비스 정의
│   ├── .env                   # 환경변수 (포트, 타임존 등)
│   └── homepage/              # Homepage 설정 파일
│       ├── bookmarks.yaml
│       ├── services.yaml
│       ├── settings.yaml
│       └── widgets.yaml
├── nginx-proxy-manager/       # 5편에서 추가
└── ...                        # 이후 서비스별 디렉토리

디렉토리를 생성합니다.

mkdir -p ~/homelab/core/homepage
cd ~/homelab/core

💡 왜 하나의 Compose 파일로? — 4개 서비스를 개별 Compose 파일로 분리할 수도 있지만, 이 서비스들은 모두 "홈랩 핵심 인프라"라는 같은 역할을 합니다. 함께 시작/중지되어야 하고, 같은 네트워크를 공유해야 하므로 하나의 파일로 관리하는 것이 효율적입니다.

3. Docker 네트워크 설계

서비스들이 서로 통신하려면 같은 Docker 네트워크에 속해야 합니다. 이 시리즈에서는 homelab이라는 외부 네트워크를 만들어서, 이번 Compose뿐 아니라 5편의 Nginx Proxy Manager 등 이후 서비스들도 연결합니다.

# 홈랩 공유 네트워크 생성 (한 번만 실행)
docker network create homelab

네트워크 구조

homelab 네트워크 (외부, 모든 서비스 공유)
├── homepage (포트 3000)
├── portainer (포트 9443)
├── watchtower (포트 없음)
├── uptime-kuma (포트 3001)
└── (이후 추가될 서비스들)

외부 네트워크를 사용하면 Compose 파일이 다른 서비스도 컨테이너 이름으로 서로 접근할 수 있습니다. 예를 들어 Uptime Kuma에서 Portainer의 상태를 체크할 때 http://portainer:9000으로 접근 가능합니다.

4. .env 파일로 설정 관리

포트 번호, 타임존, 사용자 ID 같은 설정값을 Compose 파일에 직접 쓰지 않고 .env 파일로 분리합니다. 나중에 포트를 바꾸거나 설정을 조정할 때 .env만 수정하면 됩니다.

# ~/homelab/core/.env

# 공통
TZ=Asia/Seoul
PUID=501
PGID=20

# Homepage
HOMEPAGE_PORT=3000

# Portainer
PORTAINER_PORT=9443

# Uptime Kuma
UPTIME_KUMA_PORT=3001

# Watchtower
WATCHTOWER_POLL_INTERVAL=86400
WATCHTOWER_CLEANUP=true

💡 PUID/PGID는 macOS에서 id 명령으로 확인할 수 있습니다. macOS의 기본 사용자는 보통 UID 501, GID 20(staff)입니다. 이 값을 컨테이너에 전달하면 파일 권한 충돌을 방지할 수 있습니다.

5. Docker Compose 파일 작성 — 전체 코드

아래가 이번 편의 핵심입니다. ~/homelab/core/docker-compose.yml 파일을 만듭니다.

# ~/homelab/core/docker-compose.yml
# Mac Mini 홈서버 핵심 인프라 스택

services:

  # ─── 1. Homepage (대시보드) ───
  homepage:
    image: ghcr.io/gethomepage/homepage:latest
    container_name: homepage
    ports:
      - "${HOMEPAGE_PORT:-3000}:3000"
    volumes:
      - ./homepage:/app/config
      - /var/run/docker.sock:/var/run/docker.sock:ro
    environment:
      TZ: ${TZ}
      PUID: ${PUID}
      PGID: ${PGID}
      HOMEPAGE_ALLOWED_HOSTS: "*"
    restart: unless-stopped
    networks:
      - homelab

  # ─── 2. Portainer CE (Docker 웹 관리) ───
  portainer:
    image: portainer/portainer-ce:lts
    container_name: portainer
    ports:
      - "${PORTAINER_PORT:-9443}:9443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - portainer_data:/data
    environment:
      TZ: ${TZ}
    restart: unless-stopped
    networks:
      - homelab

  # ─── 3. Watchtower (자동 업데이트) ───
  watchtower:
    image: containrrr/watchtower:latest
    container_name: watchtower
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      TZ: ${TZ}
      WATCHTOWER_POLL_INTERVAL: ${WATCHTOWER_POLL_INTERVAL:-86400}
      WATCHTOWER_CLEANUP: ${WATCHTOWER_CLEANUP:-true}
      WATCHTOWER_INCLUDE_STOPPED: "false"
      WATCHTOWER_SCHEDULE: "0 0 4 * * *"
    restart: unless-stopped
    networks:
      - homelab

  # ─── 4. Uptime Kuma (상태 모니터링) ───
  uptime-kuma:
    image: louislam/uptime-kuma:latest
    container_name: uptime-kuma
    ports:
      - "${UPTIME_KUMA_PORT:-3001}:3001"
    volumes:
      - uptime_kuma_data:/app/data
    environment:
      TZ: ${TZ}
    restart: unless-stopped
    networks:
      - homelab

# ─── 볼륨 ───
volumes:
  portainer_data:
    name: portainer_data
  uptime_kuma_data:
    name: uptime_kuma_data

# ─── 네트워크 ───
networks:
  homelab:
    external: true

각 서비스별 설정 포인트

서비스 이미지 태그 볼륨 전략 핵심 설정
Homepage latest 바인드 마운트
(설정 직접 편집)
HOMEPAGE_ALLOWED_HOSTS 필수
Portainer lts Named 볼륨
(DB 안정성)
9443 포트 (자체 SSL)
Watchtower latest Docker 소켓만 매일 새벽 4시 체크
Uptime Kuma latest Named 볼륨
(모니터링 데이터)
포트 3001

💡 Portainer 이미지 태그: lts vs latest — Portainer는 두 가지 릴리스 트랙을 운영합니다. lts(Long Term Support)는 안정성 중심, latest는 최신 기능 우선입니다. 서버에서는 lts를 권장합니다.

💡 Watchtower 스케줄WATCHTOWER_SCHEDULE에 cron 표현식을 사용합니다. 0 0 4 * * *는 매일 새벽 4시(UTC 기준은 TZ 환경변수로 조정됨)에 업데이트를 체크합니다. 6자리 cron(초 포함)을 사용하는 것에 주의하세요.

6. 배포 및 초기 설정

6-1. 한번에 배포

cd ~/homelab/core

# 4개 서비스 한번에 시작
docker compose up -d

# 상태 확인
docker compose ps

모든 컨테이너가 Up 상태이면 성공입니다. Homepage는 초기 시작에 약 30~60초 걸릴 수 있습니다.

 

6-2. 서비스별 접속 및 초기 설정

🏠 Homepage — http://Mac의IP:3000

접속하면 기본 대시보드가 표시됩니다. ~/homelab/core/homepage/ 디렉토리에 자동 생성된 YAML 파일들을 편집해서 커스터마이즈합니다. 변경 후 페이지를 새로고침하면 바로 반영됩니다.

🐳 Portainer — https://Mac의IP:9443

첫 접속 시 반드시 관리자 계정을 생성해야 합니다. 브라우저에서 HTTPS 보안 경고가 나오면 "고급" → "계속"을 클릭합니다(자체 서명 SSL). 계정 생성 후 "Get Started" → "Local" 환경이 자동 감지됩니다.

⚠️ 중요: 첫 접속을 너무 늦게 하면(약 5분) 보안상 Portainer가 초기화 화면을 잠급니다. 그 경우 docker compose restart portainer로 재시작하세요.

📊 Uptime Kuma — http://Mac의IP:3001

첫 접속 시 관리자 계정을 생성합니다. 이후 "Add New Monitor"로 모니터링 대상을 추가합니다. 당장은 방금 띄운 서비스들부터 추가해보세요 — Homepage(http://homepage:3000), Portainer(https://portainer:9443)를 모니터링하면 Uptime Kuma가 제대로 동작하는지 확인할 수 있습니다.

🔄 Watchtower — 접속 UI 없음 (로그로 확인)

docker compose logs watchtower

정상 작동 시 시작 시간과 다음 체크 스케줄이 표시됩니다.

6-3. Homepage 기본 설정 예시

Homepage의 services.yaml을 편집해서 방금 띄운 서비스들을 대시보드에 추가합니다.

# ~/homelab/core/homepage/services.yaml
- 인프라:
    - Portainer:
        href: https://192.168.0.100:9443
        description: Docker 웹 관리
        icon: portainer.png
        widget:
            type: portainer
            url: https://portainer:9443
            env: 2
            key: {{HOMEPAGE_VAR_PORTAINER_KEY}}

    - Uptime Kuma:
        href: http://192.168.0.100:3001
        description: 서비스 상태 모니터링
        icon: uptime-kuma.png
        widget:
            type: uptimekuma
            url: http://uptime-kuma:3001
            slug: default

💡 IP 주소 192.168.0.100은 2편에서 설정한 Mac Mini의 고정 IP로 교체하세요. href는 브라우저에서 접속할 주소(호스트 IP), url은 Homepage 컨테이너가 내부적으로 통신할 주소(컨테이너 이름)입니다.

7. 로그 관리 전략

컨테이너가 늘어나면 로그도 쌓입니다. 디스크가 가득 차는 것을 방지하려면 로그 크기를 제한해야 합니다.

7-1. Docker 전역 로그 제한

Docker 데몬 설정으로 모든 컨테이너에 일괄 적용할 수 있습니다. OrbStack 환경에서는 ~/.orbstack/config/docker.json 파일을 만들거나, Docker Desktop이라면 Settings → Docker Engine에서 설정합니다.

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  }
}

이 설정은 각 컨테이너의 로그 파일을 최대 10MB × 3개 = 30MB로 제한합니다.

7-2. 유용한 로그 명령어

# 특정 서비스 로그 실시간 추적
docker compose logs -f homepage

# 최근 50줄만 보기
docker compose logs --tail=50 portainer

# 모든 서비스 로그 한번에 (타임스탬프 포함)
docker compose logs -t

# Docker 전체 디스크 사용량 확인
docker system df

7-3. 정기 정리

# 사용하지 않는 이미지, 컨테이너, 네트워크 정리
docker system prune -f

# 더 공격적인 정리 (사용하지 않는 볼륨까지)
docker system prune -a --volumes -f

⚠️ --volumes 옵션은 사용하지 않는 볼륨도 삭제합니다. 중지된 서비스의 데이터 볼륨이 삭제될 수 있으니 주의하세요. Watchtower가 WATCHTOWER_CLEANUP=true로 오래된 이미지를 자동 정리하므로, 평소에는 docker system prune -f만으로 충분합니다.

🎉 현재 홈서버 상태

4편까지 완료했다면, Mac Mini에는 지금 이런 것들이 돌아가고 있습니다.

🏠 Homepage — http://Mac의IP:3000 (대시보드)

🐳 Portainer — https://Mac의IP:9443 (Docker 관리)

🔄 Watchtower — 매일 새벽 4시 자동 업데이트 체크 중

📊 Uptime Kuma — http://Mac의IP:3001 (상태 모니터링)

🖥️ Mac Mini 홈서버 완전 정복 시리즈

✅ 1편. 왜 Mac Mini인가? — 홈서버 하드웨어 선택 가이드

✅ 2편. macOS 서버 초기 세팅 — 헤드리스 최적화 완벽 가이드

✅ 3편. Docker 환경 구축 — OrbStack vs Docker Desktop vs Colima 비교

✅ 4편. 홈서버 필수 서비스 한방에 띄우기 — Docker Compose 실전편 (현재 글)

📌 5편. 리버스 프록시 구축 — Nginx Proxy Manager로 도메인 + HTTPS

📌 6편. 외부 접속 — Cloudflare Tunnel로 포트포워딩 없이 공개

📌 7편. 보안 강화 — SSH 키 인증 + Fail2Ban + 방화벽

📌 8편. 스토리지 & 백업 전략

📌 9편. 실전 서비스 배포 — 미디어 + 사진 + 스마트홈

📌 10편. 종합 모니터링 & 운영 자동화

이 글에서는 Docker Compose로 홈서버의 핵심 인프라 4개 서비스를 한번에 배포했습니다. 대시보드(Homepage)로 전체 상태를 보고, Portainer로 Docker를 관리하고, Watchtower가 이미지를 자동 업데이트하고, Uptime Kuma가 서비스 상태를 감시합니다. 이제 홈서버의 뼈대가 갖춰졌습니다.

하지만 아직 한 가지 큰 문제가 남아있습니다 — 각 서비스에 접속할 때마다 IP:포트번호를 외워야 합니다. 3000, 9443, 3001... 서비스가 10개만 넘어도 지옥이 됩니다. 다음 5편에서는 Nginx Proxy Manager로 리버스 프록시를 구축해서, portainer.mydomain.com 같은 깔끔한 도메인 + HTTPS를 한번에 해결합니다.

도움이 됐다면 공감 ❤️ 부탁드려요! 시리즈 알림 받으시려면 구독도 부탁합니다.

반응형

▲ TOP