본문으로 건너뛰기
Docker 컨테이너 홈서버 입문 가이드
Table of Contents

“Docker 없이 홈서버 하는 건 가능은 해요. 그런데… 왜 굳이?”

홈서버 커뮤니티에서 흔히 듣는 말입니다. 사실 저도 처음엔 “뭘 그렇게까지?”라고 생각했습니다. Jellyfin을 직접 설치해서 잘 쓰고 있었고, Pi-hole도 수동으로 세팅했습니다. 그런데 어느 날 시스템 업데이트를 했더니 Jellyfin이 깨졌습니다. 의존성 충돌이라는데, 뭐가 뭔지 모르겠고, 해결하려면 또 검색하고, 시도하고, 실패하고… 결국 새벽 3시까지 삽질한 끝에 OS를 새로 설치했습니다.

그 이후로 Docker를 배웠습니다. 그리고 한 번도 그런 일을 겪지 않았습니다.

오늘 글에서는 Docker가 도대체 뭐길래 이 모양인지, 왜 홈서버 운영자들이 “무조건 Docker”를 외치는지 설명하겠습니다. 어렵지 않습니다. 진짜로요.

1. 먼저, 왜 격리가 필요한가?

홈서버에 Jellyfin(미디어 서버)과 Nextcloud(파일 클라우드)를 같이 돌린다고 가정해봅시다.

두 프로그램 모두 리눅스 서버에 직접 설치할 수 있습니다. apt install로 패키지 깔고, 설정 파일 수정하고, 서비스 시작하면 됩니다. 간단해 보입니다.

문제는 시간이 지나면서 시작됩니다.

                 ┌──────────────────────────────────────┐
                 │         리눅스 서버 (Ubuntu)          │
                 ├──────────────────────────────────────┤
                 │  PHP 8.1  ←── Nextcloud가 필요       │
                 │  PHP 8.3  ←── 새 플러그인이 필요      │
                 │  FFmpeg 5.x ←── Jellyfin이 설치함    │
                 │  FFmpeg 6.x ←── 업데이트하면 깨짐     │
                 │  Python 3.10 ←── 시스템 기본         │
                 │  Python 3.12 ←── 새 앱이 필요        │
                 │                                      │
                 │     😱 의존성 지옥 (Dependency Hell)  │
                 └──────────────────────────────────────┘
  • Nextcloud는 PHP 8.1이 필요한데, 어떤 플러그인은 PHP 8.3을 요구합니다.
  • Jellyfin은 특정 버전의 FFmpeg와 궁합이 맞는데, 시스템 업데이트로 버전이 바뀌면 트랜스코딩이 깨집니다.
  • 새로 설치하려는 앱이 Python 3.12를 요구하는데, 시스템 기본은 3.10입니다.

이런 상황을 **의존성 지옥(Dependency Hell)**이라고 부릅니다. 프로그램 A가 요구하는 라이브러리와 프로그램 B가 요구하는 라이브러리가 서로 충돌하는 상황입니다.

해결책은 명확합니다: 각 프로그램을 서로 격리시키면 됩니다.

2. 격리의 두 가지 방법: VM vs 컨테이너

프로그램을 격리하는 방법에는 크게 두 가지가 있습니다.

🖥️ 가상 머신(Virtual Machine, VM)

VM은 컴퓨터 안에 또 다른 컴퓨터를 만드는 것입니다. 하이퍼바이저(Hypervisor)라는 소프트웨어가 하드웨어를 가상화해서, 그 위에 완전히 독립된 운영체제를 설치합니다.

┌─────────────────────────────────────────────────────────┐
│                      하드웨어 (N100 서버)                │
├─────────────────────────────────────────────────────────┤
│                    하이퍼바이저 (Proxmox)                │
├──────────────────┬──────────────────┬───────────────────┤
│    VM 1          │     VM 2         │     VM 3          │
│  ┌───────────┐   │   ┌───────────┐  │   ┌───────────┐   │
│  │ Ubuntu    │   │   │ Debian    │  │   │ Windows   │   │
│  │ 커널      │   │   │ 커널      │  │   │ 커널      │   │
│  │ 라이브러리│   │   │ 라이브러리│  │   │ 라이브러리│   │
│  │ Jellyfin  │   │   │ Nextcloud │  │   │ 테스트용  │   │
│  └───────────┘   │   └───────────┘  │   └───────────┘   │
│   RAM: 4GB       │   RAM: 4GB       │   RAM: 4GB        │
│   Disk: 40GB     │   Disk: 40GB     │   Disk: 40GB      │
└──────────────────┴──────────────────┴───────────────────┘

장점:

  • 완벽한 격리. VM끼리는 서로의 존재조차 모릅니다.
  • 서로 다른 OS를 돌릴 수 있습니다 (리눅스 옆에 윈도우).
  • 한 VM이 해킹당해도 다른 VM은 안전합니다.

단점:

  • 무겁습니다. 각 VM마다 전체 OS를 돌려야 합니다. 커널, 드라이버, 시스템 서비스… 전부 따로.
  • 메모리를 많이 먹습니다. VM 3개면 최소 12GB RAM이 필요합니다.
  • 부팅이 느립니다. VM 시작할 때마다 OS 부팅 과정을 거칩니다.
  • 디스크 공간도 많이 잡아먹습니다. VM마다 OS 이미지가 따로 필요합니다.

Proxmox가 대표적인 VM 관리 플랫폼입니다. 강력하지만, 홈서버 입문자에게는 과한 면이 있습니다.


📦 컨테이너(Container)

컨테이너는 VM보다 훨씬 가벼운 격리 방식입니다. 핵심 차이점은 OS 커널을 공유한다는 것입니다.

┌─────────────────────────────────────────────────────────┐
│                     하드웨어 (N100 서버)                 │
├─────────────────────────────────────────────────────────┤
│                 호스트 OS (Ubuntu Server)               │
│                 리눅스 커널 (공유)                       │
├─────────────────────────────────────────────────────────┤
│                   Docker Engine                         │
├───────────────┬───────────────┬───────────────┬─────────┤
│ 컨테이너 1    │ 컨테이너 2    │ 컨테이너 3    │ ...     │
│ ┌──────────┐  │ ┌──────────┐  │ ┌──────────┐  │         │
│ │Jellyfin  │  │ │Nextcloud │  │ │Pi-hole   │  │         │
│ │라이브러리│  │ │라이브러리│  │ │라이브러리│  │         │
│ └──────────┘  │ └──────────┘  │ └──────────┘  │         │
│  RAM: ~200MB  │  RAM: ~300MB  │  RAM: ~50MB   │         │
└───────────────┴───────────────┴───────────────┴─────────┘

VM은 “집을 통째로 복사하는 것”이라면, 컨테이너는 “같은 건물에서 칸막이로 방을 나누는 것”입니다. 건물의 기초(커널)는 공유하되, 각 방(컨테이너)은 독립적인 공간입니다.

장점:

  • 가볍습니다. OS 커널을 공유하니 오버헤드가 적습니다.
  • 빠릅니다. 컨테이너 시작에 1~2초면 충분합니다. 부팅이 아니라 프로세스 시작이니까요.
  • 메모리 효율적. 실제로 사용하는 만큼만 메모리를 씁니다.
  • 이식성. 한 번 만든 컨테이너는 어디서든 똑같이 돌아갑니다.

단점:

  • 리눅스 컨테이너는 리눅스에서만 네이티브로 돌아갑니다 (윈도우/맥은 내부적으로 VM 사용).
  • VM만큼 완벽한 격리는 아닙니다 (커널을 공유하니까).

⚔️ VM vs 컨테이너: 언제 뭘 써야 하나?

기준VM컨테이너
격리 수준완벽프로세스 수준
시작 시간수십 초~수 분1~2초
메모리 효율낮음 (OS 전체 로드)높음 (필요한 만큼)
디스크 사용큼 (GB 단위)작음 (MB~GB)
다른 OS 실행가능불가능 (커널 공유)
활용 예Proxmox, 보안 실험Docker, 앱 배포

홈서버 입문자에게 컨테이너(Docker)를 추천하는 이유:

  • 홈서버에서 돌리는 대부분의 서비스(Jellyfin, Nextcloud, Pi-hole 등)는 리눅스 앱입니다.
  • 윈도우가 필요한 경우가 거의 없습니다.
  • N100 같은 저사양 서버에서는 VM의 오버헤드가 부담됩니다.
  • 컨테이너 하나 잘못돼도 docker rm하고 다시 만들면 끝입니다. VM을 다시 만드는 것보다 100배 빠릅니다.

3. Docker란 무엇인가?

Docker는 컨테이너를 쉽게 만들고 관리하게 해주는 도구입니다.

컨테이너 기술 자체는 리눅스에 이미 내장되어 있습니다 (cgroups, namespaces). 하지만 이걸 직접 다루려면 상당히 복잡합니다. Docker는 이런 복잡함을 추상화해서, 몇 줄의 명령어로 컨테이너를 다룰 수 있게 해줍니다.

📚 Docker 핵심 개념 4가지

Docker를 이해하려면 네 가지 개념만 알면 됩니다.

1️⃣ 이미지 (Image)

이미지는 컨테이너의 설계도입니다. 프로그램 + 실행에 필요한 모든 것(라이브러리, 설정 파일 등)을 하나로 패키징한 것입니다.

┌─────────────────────────────────────┐
│          Jellyfin 이미지            │
├─────────────────────────────────────┤
│  - Ubuntu 기반 파일시스템            │
│  - .NET 런타임                       │
│  - FFmpeg (트랜스코딩용)             │
│  - Jellyfin 바이너리                 │
│  - 기본 설정 파일                    │
└─────────────────────────────────────┘

이미지는 읽기 전용입니다. 변경할 수 없습니다. Docker Hub(hub.docker.com)에 수십만 개의 이미지가 공개되어 있습니다. jellyfin/jellyfin, linuxserver/nextcloud, pihole/pihole 등 홈서버에서 쓰는 거의 모든 앱의 공식 이미지가 있습니다.

2️⃣ 컨테이너 (Container)

컨테이너는 이미지를 실행한 인스턴스입니다. 설계도(이미지)를 바탕으로 실제로 동작하는 프로세스를 만든 것입니다.

이미지 ────────────► 컨테이너
(설계도)    실행    (실제 동작하는 앱)

하나의 이미지로 여러 컨테이너를 만들 수 있습니다:

jellyfin/jellyfin ──┬──► jellyfin-1 (거실 TV용)
      (이미지)      └──► jellyfin-2 (테스트용)

컨테이너는 일시적입니다. 컨테이너를 삭제하면 그 안에서 생성된 데이터도 사라집니다. (그래서 볼륨이 필요합니다)

3️⃣ 볼륨 (Volume)

볼륨은 컨테이너의 데이터를 영구 저장하는 공간입니다.

컨테이너는 기본적으로 휘발성입니다. Jellyfin 컨테이너를 지우면 설정, 시청 기록, 라이브러리 정보가 다 날아갑니다. 이걸 방지하려면 중요한 데이터를 볼륨에 저장해야 합니다.

┌───────────────────────────────────────────────────────┐
│                    호스트 서버                         │
│  /srv/jellyfin/config ◄────┐                          │
│  /srv/jellyfin/media  ◄──┐ │                          │
│                          │ │      ┌─────────────────┐ │
│                          │ └──────┤ /config         │ │
│                          └────────┤ /media          │ │
│                                   │   (Jellyfin)    │ │
│                                   └─────────────────┘ │
│                                     컨테이너 내부      │
└───────────────────────────────────────────────────────┘

볼륨 = 호스트의 폴더와 컨테이너 내부 폴더를 연결하는 것

볼륨을 사용하면:

  • 컨테이너를 삭제해도 데이터는 남습니다.
  • 컨테이너를 업데이트해도 설정이 유지됩니다.
  • 호스트에서 직접 파일을 확인하고 백업할 수 있습니다.

4️⃣ 네트워크 (Network)

Docker 네트워크는 컨테이너들이 서로 통신하는 방법을 정의합니다.

기본적으로 각 컨테이너는 격리되어 있어서 서로 통신할 수 없습니다. 같은 네트워크에 연결된 컨테이너끼리만 통신할 수 있습니다.

┌───────────────────────────────────────────────────────┐
│                  Docker Network "backend"             │
│  ┌────────────┐    ┌────────────┐    ┌────────────┐  │
│  │ Nextcloud  │◄───│  MariaDB   │    │   Redis    │  │
│  │            │    │ (DB 서버)   │    │ (캐시)     │  │
│  └────────────┘    └────────────┘    └────────────┘  │
└───────────────────────────────────────────────────────┘

같은 네트워크 안에서는 컨테이너 이름으로 통신 가능:
Nextcloud가 DB에 접속할 때: "mariadb:3306"

포트 매핑도 네트워크의 일부입니다:

  • 컨테이너 내부의 포트를 호스트의 포트에 연결합니다.
  • -p 8096:8096 → 호스트의 8096 포트로 접속하면 컨테이너의 8096 포트로 연결

🎯 정리: Docker 핵심 개념

┌─────────────────────────────────────────────────────────────┐
│                        Docker 구조                          │
├─────────────────────────────────────────────────────────────┤
│                                                             │
│   📦 이미지 (Image)                                         │
│   └─► 앱 + 환경을 패키징한 설계도 (읽기 전용)                │
│                                                             │
│   🏃 컨테이너 (Container)                                   │
│   └─► 이미지를 실행한 인스턴스 (일시적)                      │
│                                                             │
│   💾 볼륨 (Volume)                                          │
│   └─► 데이터를 영구 저장하는 공간                            │
│                                                             │
│   🌐 네트워크 (Network)                                     │
│   └─► 컨테이너 간 통신 경로                                  │
│                                                             │
└─────────────────────────────────────────────────────────────┘

4. 홈서버에서 Docker가 빛나는 순간들

이론은 충분합니다. Docker가 실제로 어떻게 홈서버 생활을 바꾸는지 보여드리겠습니다.

✨ 시나리오 1: 설치가 1분이면 끝난다

기존 방식 (직접 설치):

# Pi-hole 설치하려면...
sudo apt update
sudo apt install curl
curl -sSL https://install.pi-hole.net | bash
# 설치 마법사 따라가기... (5분)
# 웹 인터페이스 비밀번호 설정...
# DNS 설정 변경...

Docker 방식:

docker run -d \
  --name pihole \
  -p 53:53/tcp -p 53:53/udp -p 80:80 \
  -e TZ=Asia/Seoul \
  -v /srv/pihole/etc:/etc/pihole \
  -v /srv/pihole/dnsmasq:/etc/dnsmasq.d \
  pihole/pihole

복사-붙여넣기 한 번이면 Pi-hole이 돌아갑니다. “리눅스 명령어 잘 모르는데…”라는 걱정? Docker 명령어만 알면 됩니다.

✨ 시나리오 2: 업데이트가 두렵지 않다

기존 방식:

sudo apt update && sudo apt upgrade
# 기도하기 🙏
# 혹시 뭔가 깨지면... 새벽까지 삽질

Docker 방식:

# 1. 기존 컨테이너 중지 & 삭제
docker stop jellyfin
docker rm jellyfin

# 2. 새 이미지 받기
docker pull jellyfin/jellyfin:latest

# 3. 같은 설정으로 다시 시작
docker run -d --name jellyfin ... (이전과 동일)

볼륨에 데이터가 저장되어 있으므로, 시청 기록/설정/라이브러리 전부 그대로입니다. 문제가 생기면? 이전 버전 이미지로 다시 실행하면 됩니다. 롤백이 쉽습니다.

✨ 시나리오 3: 서버 이전이 간단하다

오래된 서버에서 새 N100으로 이사 가야 합니다.

기존 방식:

  • 각 프로그램 설정 파일 위치 찾기
  • 데이터 백업
  • 새 서버에 OS 설치
  • 각 프로그램 다시 설치
  • 설정 복원
  • 되나 안 되나 테스트
  • (예상 소요 시간: 반나절~하루)

Docker 방식:

# 구 서버에서
tar -czvf homeserver-backup.tar.gz /srv/

# 새 서버에서
tar -xzvf homeserver-backup.tar.gz -C /
docker compose up -d

Docker Compose 파일과 볼륨 데이터만 있으면, 새 서버에서 30분 안에 모든 서비스가 복원됩니다.

✨ 시나리오 4: 실험이 자유롭다

“이 앱 좋다던데 한번 써볼까?”

기존 방식: 설치했다가 맘에 안 들면 지워야 하는데, 완전히 지워지지 않는 설정 파일들… 시스템이 점점 더러워집니다.

Docker 방식:

# 일단 실행해보기
docker run -d --name test-app some-app:latest

# 맘에 안 들면
docker stop test-app
docker rm test-app
docker rmi some-app:latest

# 흔적 제로. 시스템은 깨끗.

5. 실습: Docker 첫걸음

이제 직접 해봅시다. 실습 환경은 Ubuntu Server를 기준으로 합니다. (Debian, 다른 배포판도 거의 동일합니다)

🔧 Step 1: Docker 설치

# 1. 패키지 업데이트
sudo apt update

# 2. 필요한 패키지 설치
sudo apt install -y ca-certificates curl gnupg

# 3. Docker 공식 GPG 키 추가
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
sudo chmod a+r /etc/apt/keyrings/docker.gpg

# 4. Docker 저장소 추가
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

# 5. Docker 설치
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

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

# 7. 로그아웃 후 다시 로그인하거나:
newgrp docker

설치 확인:

docker --version
# Docker version 24.x.x, build xxxxxxx

docker compose version
# Docker Compose version v2.x.x

🔧 Step 2: Hello World 컨테이너

Docker의 전통적인 첫 번째 실습입니다.

docker run hello-world

출력 결과:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
...
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

무슨 일이 일어났나요?

  1. hello-world 이미지가 로컬에 없음 → Docker Hub에서 다운로드
  2. 이미지로 컨테이너 생성
  3. 컨테이너 실행 (메시지 출력)
  4. 실행 완료 후 컨테이너 종료

🔧 Step 3: 기본 명령어 실습

컨테이너 실행: docker run

# 기본 실행
docker run nginx

# 백그라운드 실행 (-d)
docker run -d nginx

# 이름 지정 (--name)
docker run -d --name my-nginx nginx

# 포트 매핑 (-p)
docker run -d --name my-nginx -p 8080:80 nginx
# 호스트의 8080 포트 → 컨테이너의 80 포트

실행 중인 컨테이너 확인: docker ps

# 실행 중인 컨테이너만
docker ps

# 모든 컨테이너 (중지된 것 포함)
docker ps -a

# 출력 예시:
CONTAINER ID   IMAGE   COMMAND                  STATUS         PORTS                  NAMES
a1b2c3d4e5f6   nginx   "/docker-entrypoint.…"   Up 2 minutes   0.0.0.0:8080->80/tcp   my-nginx

컨테이너 중지: docker stop

# 이름으로 중지
docker stop my-nginx

# ID로 중지 (앞 몇 글자만 입력해도 됨)
docker stop a1b2

컨테이너 삭제: docker rm

# 중지된 컨테이너 삭제
docker rm my-nginx

# 실행 중인 컨테이너 강제 삭제 (-f)
docker rm -f my-nginx

이미지 관리: docker images, docker rmi

# 다운로드된 이미지 목록
docker images

# 이미지 삭제
docker rmi nginx

# 사용하지 않는 이미지 일괄 삭제
docker image prune

🔧 Step 4: 실용적인 예제 - Nginx 웹서버

# 1. 볼륨용 디렉토리 생성
mkdir -p /srv/nginx/html

# 2. 테스트용 HTML 파일 생성
echo "<h1>Hello from Docker!</h1>" > /srv/nginx/html/index.html

# 3. Nginx 컨테이너 실행
docker run -d \
  --name nginx-test \
  -p 8080:80 \
  -v /srv/nginx/html:/usr/share/nginx/html:ro \
  nginx

# 4. 브라우저에서 http://서버IP:8080 접속
# 또는 curl로 테스트:
curl http://localhost:8080

-v /srv/nginx/html:/usr/share/nginx/html:ro 부분이 볼륨 마운트입니다.

  • 호스트의 /srv/nginx/html 폴더가
  • 컨테이너의 /usr/share/nginx/html 폴더로 연결됩니다.
  • :ro는 읽기 전용(read-only)이라는 뜻입니다.

🔧 Step 5: 컨테이너 내부 들여다보기

# 실행 중인 컨테이너의 로그 보기
docker logs nginx-test

# 실시간 로그 (-f = follow)
docker logs -f nginx-test

# 컨테이너 내부에 접속 (bash 셸)
docker exec -it nginx-test bash

# 내부에서:
ls /usr/share/nginx/html
cat /etc/nginx/nginx.conf
exit

docker exec -it는 정말 자주 쓰는 명령어입니다. 컨테이너 안에서 무슨 일이 일어나는지 확인하거나, 설정을 임시로 수정할 때 유용합니다.


6. 명령어 치트시트

┌───────────────────────────────────────────────────────────────┐
│                    Docker 필수 명령어                          │
├───────────────────────────────────────────────────────────────┤
│                                                               │
│  🏃 컨테이너 관리                                              │
│  ────────────────────────────────────────────────────────     │
│  docker run -d --name [이름] [이미지]    # 백그라운드 실행     │
│  docker ps                              # 실행 중 목록        │
│  docker ps -a                           # 전체 목록           │
│  docker stop [이름]                      # 중지               │
│  docker start [이름]                     # 시작               │
│  docker restart [이름]                   # 재시작             │
│  docker rm [이름]                        # 삭제               │
│  docker rm -f [이름]                     # 강제 삭제          │
│                                                               │
│  📦 이미지 관리                                                │
│  ────────────────────────────────────────────────────────     │
│  docker images                          # 이미지 목록         │
│  docker pull [이미지]                    # 이미지 다운로드     │
│  docker rmi [이미지]                     # 이미지 삭제         │
│  docker image prune                     # 미사용 이미지 정리  │
│                                                               │
│  🔍 디버깅                                                     │
│  ────────────────────────────────────────────────────────     │
│  docker logs [이름]                      # 로그 보기          │
│  docker logs -f [이름]                   # 실시간 로그        │
│  docker exec -it [이름] bash             # 내부 접속          │
│  docker inspect [이름]                   # 상세 정보          │
│                                                               │
│  🧹 정리                                                       │
│  ────────────────────────────────────────────────────────     │
│  docker system prune                    # 미사용 리소스 정리  │
│  docker system prune -a                 # 전체 정리 (주의!)   │
│                                                               │
└───────────────────────────────────────────────────────────────┘

7. 자주 묻는 질문

Q. Docker를 쓰면 성능이 떨어지나요?

A. 거의 차이 없습니다. Docker 컨테이너는 VM과 달리 하드웨어를 에뮬레이션하지 않습니다. 네이티브에 비해 1~3% 정도의 오버헤드가 있다고 알려져 있지만, 체감하기 어려운 수준입니다. N100 같은 저사양에서도 Jellyfin 트랜스코딩이 문제없이 돌아갑니다.

Q. Docker 말고 Podman이라는 것도 있던데요?

A. Podman도 좋은 선택입니다. Docker와 거의 동일한 명령어를 사용하고, rootless(루트 권한 없이) 실행이 기본이라 보안 면에서 장점이 있습니다. 하지만 2025년 현재, 홈서버 커뮤니티의 대부분의 가이드와 자료가 Docker 기준으로 작성되어 있어서 입문자에게는 Docker를 추천합니다.

Q. Docker Desktop과 Docker Engine의 차이는?

A. Docker Desktop은 GUI가 있는 데스크탑용이고, Docker Engine은 서버용 CLI 버전입니다. 홈서버에서는 Docker Engine을 사용합니다. 이 글에서 설치한 것이 Docker Engine입니다.

Q. 컨테이너가 자동으로 시작되게 하려면?

A. --restart 옵션을 사용합니다.

docker run -d --name jellyfin --restart unless-stopped jellyfin/jellyfin
  • unless-stopped: 수동으로 중지하지 않는 한 항상 재시작
  • always: 무조건 재시작
  • on-failure: 오류로 종료되었을 때만 재시작

8. 다음 단계: Docker Compose

지금까지 docker run 명령어로 컨테이너를 실행했습니다. 하지만 옵션이 많아지면 명령어가 점점 길어집니다:

docker run -d \
  --name jellyfin \
  --restart unless-stopped \
  -p 8096:8096 \
  -v /srv/jellyfin/config:/config \
  -v /srv/jellyfin/cache:/cache \
  -v /mnt/media:/media:ro \
  -e TZ=Asia/Seoul \
  --device /dev/dri:/dev/dri \
  jellyfin/jellyfin

이걸 매번 타이핑하거나 기억하기 어렵습니다. 그래서 Docker Compose가 있습니다.

위 명령어를 docker-compose.yml 파일로 작성하면:

services:
  jellyfin:
    image: jellyfin/jellyfin
    container_name: jellyfin
    restart: unless-stopped
    ports:
      - 8096:8096
    volumes:
      - /srv/jellyfin/config:/config
      - /srv/jellyfin/cache:/cache
      - /mnt/media:/media:ro
    environment:
      - TZ=Asia/Seoul
    devices:
      - /dev/dri:/dev/dri

그리고 실행은:

docker compose up -d

단 한 줄입니다.

다음 포스팅 **“Docker Compose로 홈서버 서비스 관리하기”**에서 Docker Compose를 제대로 다루겠습니다. 여러 컨테이너를 하나의 파일로 관리하고, 서비스 간 의존성을 설정하고, 환경변수를 분리하는 방법까지 배울 수 있습니다.


🚀 마무리

Docker는 홈서버 운영의 게임 체인저입니다.

  • 의존성 지옥에서 해방됩니다.
  • 설치와 업데이트가 간단해집니다.
  • 서버 이전과 백업이 쉬워집니다.
  • 실험과 롤백이 자유로워집니다.

처음엔 새로운 개념들이 어색할 수 있습니다. 하지만 일주일만 써보면 “이거 없이 어떻게 살았지?”라는 생각이 들 겁니다.

:::tip[오늘의 숙제]

  1. 서버에 Docker를 설치하세요.
  2. docker run hello-world를 실행해보세요.
  3. docker run -d --name test-nginx -p 8080:80 nginx로 웹서버를 띄워보세요.
  4. 브라우저에서 http://서버IP:8080에 접속해보세요.

여기까지 했다면, 당신은 이미 Docker 사용자입니다! :::

이 글 공유하기:
다음 글: Docker Compose 완벽 가이드: 복잡한 서버 관리, 텍스트...
My avatar

글을 마치며

이 글이 도움이 되었기를 바랍니다. 궁금한 점이나 의견이 있다면 댓글로 남겨주세요.

더 많은 기술 인사이트와 개발 경험을 공유하고 있으니, 다른 포스트도 확인해보세요.

유럽살며 여행하며 코딩하는 노마드의 여정을 함께 나누며, 함께 성장하는 개발자 커뮤니티를 만들어가요! 🚀


홈서버 마스터 클래스 시리즈