홈서버 구축 완전 가이드 6편: Docker와 컨테이너 활용
Home Server Complete Guide Part 6: Docker and Container Usage
서론: 왜 Docker인가?
홈서버를 운영하다 보면 이것저것 설치하고 싶은 프로그램이 많아집니다. 미디어 서버, 파일 동기화, 광고 차단, 비밀번호 관리자... 하지만 프로그램을 직접 설치하면 여러 가지 문제가 생깁니다. 의존성 충돌, 업데이트 시 설정 날아감, 다른 서버로 이전할 때 처음부터 다시 설정해야 하는 번거로움 등이 대표적이죠.
Docker는 이런 문제를 깔끔하게 해결해줍니다. 컨테이너라는 격리된 환경에서 프로그램을 실행하기 때문에 서로 영향을 주지 않고, 설정 파일 몇 줄만으로 복잡한 서비스를 배포할 수 있습니다. 이번 편에서는 Docker의 기본 개념부터 실제로 유용한 서비스들을 배포하는 방법까지 상세히 알아보겠습니다.
1. Docker란 무엇인가?
1.1 컨테이너의 개념
컨테이너는 애플리케이션과 그 실행에 필요한 모든 것(라이브러리, 설정 파일 등)을 하나의 패키지로 묶은 것입니다. 가상 머신과 비슷해 보이지만 훨씬 가볍고 빠릅니다.
- 가상 머신(VM): 전체 운영체제를 포함하므로 무겁고 부팅에 시간이 걸립니다.
- 컨테이너: 호스트 OS의 커널을 공유하므로 가볍고 거의 즉시 시작됩니다.
쉽게 비유하자면, 가상 머신은 집 전체를 통째로 옮기는 것이고, 컨테이너는 필요한 가구만 컨테이너 박스에 담아 옮기는 것입니다.
1.2 Docker의 주요 개념
- 이미지(Image): 컨테이너를 만들기 위한 템플릿입니다. 프로그램과 필요한 환경이 모두 포함되어 있습니다.
- 컨테이너(Container): 이미지를 실행한 인스턴스입니다. 실제로 돌아가는 프로그램이라고 보면 됩니다.
- 레지스트리(Registry): 이미지를 저장하고 배포하는 저장소입니다. Docker Hub가 대표적입니다.
- 볼륨(Volume): 컨테이너의 데이터를 영구적으로 저장하는 공간입니다.
1.3 Docker의 장점
- 격리성: 각 컨테이너는 독립된 환경에서 실행되어 서로 영향을 주지 않습니다.
- 이식성: 한 번 만든 이미지는 어디서든 동일하게 실행됩니다.
- 재현성: 설정 파일만 있으면 언제든 같은 환경을 재현할 수 있습니다.
- 효율성: 가상 머신보다 훨씬 적은 리소스를 사용합니다.
- 생태계: 수많은 이미지가 Docker Hub에 공개되어 있어 바로 사용 가능합니다.
2. Docker 설치
2.1 Ubuntu/Debian에서 설치
공식 저장소를 사용하여 최신 버전의 Docker를 설치합니다.
# 기존 패키지 제거
sudo apt remove docker docker-engine docker.io containerd runc
# 필요 패키지 설치
sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release
# Docker GPG 키 추가
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Docker 저장소 추가
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Docker 설치
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 서비스 시작 및 부팅 시 자동 시작
sudo systemctl start docker
sudo systemctl enable docker
2.2 현재 사용자를 docker 그룹에 추가
매번 sudo를 입력하지 않으려면 현재 사용자를 docker 그룹에 추가합니다.
sudo usermod -aG docker $USER
# 로그아웃 후 다시 로그인하면 적용됩니다
2.3 설치 확인
# Docker 버전 확인
docker --version
# Docker Compose 버전 확인
docker compose version
# 테스트 컨테이너 실행
docker run hello-world
3. Docker 기본 명령어
3.1 이미지 관련 명령어
# 이미지 다운로드
docker pull nginx
# 로컬 이미지 목록 확인
docker images
# 이미지 삭제
docker rmi nginx
# 사용하지 않는 이미지 정리
docker image prune
3.2 컨테이너 실행 (docker run)
docker run은 가장 많이 사용하는 명령어입니다. 주요 옵션을 알아봅시다.
# 기본 실행
docker run nginx
# 백그라운드 실행 (-d)
docker run -d nginx
# 컨테이너 이름 지정 (--name)
docker run -d --name my-nginx nginx
# 포트 매핑 (-p 호스트포트:컨테이너포트)
docker run -d -p 8080:80 nginx
# 볼륨 마운트 (-v 호스트경로:컨테이너경로)
docker run -d -v /my/content:/usr/share/nginx/html nginx
# 환경 변수 설정 (-e)
docker run -d -e MYSQL_ROOT_PASSWORD=secret mysql
# 재시작 정책 설정 (--restart)
docker run -d --restart unless-stopped nginx
# 여러 옵션 조합
docker run -d \
--name webserver \
-p 80:80 \
-v /var/www:/usr/share/nginx/html:ro \
--restart unless-stopped \
nginx
3.3 컨테이너 관리 (docker ps)
# 실행 중인 컨테이너 목록
docker ps
# 모든 컨테이너 목록 (중지된 것 포함)
docker ps -a
# 컨테이너 중지
docker stop my-nginx
# 컨테이너 시작
docker start my-nginx
# 컨테이너 재시작
docker restart my-nginx
# 컨테이너 삭제
docker rm my-nginx
# 실행 중인 컨테이너 강제 삭제
docker rm -f my-nginx
# 중지된 컨테이너 모두 삭제
docker container prune
3.4 로그 확인 (docker logs)
# 로그 보기
docker logs my-nginx
# 실시간 로그 보기 (-f: follow)
docker logs -f my-nginx
# 마지막 100줄만 보기
docker logs --tail 100 my-nginx
# 타임스탬프 포함
docker logs -t my-nginx
3.5 컨테이너 내부 접근 (docker exec)
# 컨테이너 내부에서 명령 실행
docker exec my-nginx ls /etc/nginx
# 컨테이너 쉘 접속 (-it: 대화형 터미널)
docker exec -it my-nginx /bin/bash
# 쉘이 bash가 아닌 경우 (Alpine 등)
docker exec -it my-nginx /bin/sh
4. Docker Compose 활용
4.1 Docker Compose란?
Docker Compose는 여러 컨테이너를 정의하고 관리하기 위한 도구입니다. YAML 파일에 서비스 구성을 정의하면 한 번의 명령으로 모든 서비스를 시작하거나 중지할 수 있습니다.
4.2 docker-compose.yml 기본 구조
version: "3.8"
services:
web:
image: nginx:latest
container_name: my-web
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stopped
db:
image: mariadb:latest
container_name: my-db
environment:
- MYSQL_ROOT_PASSWORD=secretpassword
- MYSQL_DATABASE=myapp
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
volumes:
db_data:
4.3 Docker Compose 명령어
# 서비스 시작 (백그라운드)
docker compose up -d
# 서비스 중지 및 컨테이너 삭제
docker compose down
# 서비스 중지 (컨테이너 유지)
docker compose stop
# 서비스 재시작
docker compose restart
# 로그 보기
docker compose logs -f
# 특정 서비스만 재시작
docker compose restart web
# 이미지 업데이트 후 재배포
docker compose pull
docker compose up -d
4.4 실전 예제: WordPress + MariaDB
version: "3.8"
services:
wordpress:
image: wordpress:latest
container_name: wordpress
ports:
- "8080:80"
environment:
- WORDPRESS_DB_HOST=db
- WORDPRESS_DB_USER=wordpress
- WORDPRESS_DB_PASSWORD=wordpress_password
- WORDPRESS_DB_NAME=wordpress
volumes:
- wordpress_data:/var/www/html
depends_on:
- db
restart: unless-stopped
db:
image: mariadb:latest
container_name: wordpress-db
environment:
- MYSQL_ROOT_PASSWORD=root_password
- MYSQL_DATABASE=wordpress
- MYSQL_USER=wordpress
- MYSQL_PASSWORD=wordpress_password
volumes:
- db_data:/var/lib/mysql
restart: unless-stopped
volumes:
wordpress_data:
db_data:
5. Portainer로 웹 GUI 관리
5.1 Portainer 소개
Portainer는 Docker를 웹 브라우저에서 관리할 수 있게 해주는 도구입니다. 컨테이너 시작/중지, 로그 확인, 이미지 관리 등 대부분의 작업을 GUI로 할 수 있어서 터미널에 익숙하지 않은 분들께 특히 유용합니다.
5.2 Portainer 설치
# 볼륨 생성
docker volume create portainer_data
# Portainer 실행
docker run -d \
-p 9443:9443 \
--name portainer \
--restart unless-stopped \
-v /var/run/docker.sock:/var/run/docker.sock \
-v portainer_data:/data \
portainer/portainer-ce:latest
5.3 Portainer 초기 설정
- 웹 브라우저에서
https://서버IP:9443접속 - 관리자 계정 생성 (비밀번호 12자 이상)
- "Get Started" 또는 "Local" 환경 선택
- 대시보드에서 컨테이너, 이미지, 볼륨 등 관리
5.4 Portainer 주요 기능
- 컨테이너 관리: 시작, 중지, 재시작, 삭제, 로그 확인
- 스택(Stack): docker-compose 파일을 웹에서 관리
- 이미지 관리: 이미지 다운로드, 삭제, 빌드
- 볼륨 관리: 볼륨 생성, 삭제, 백업
- 네트워크 관리: Docker 네트워크 설정
- 템플릿: 미리 정의된 앱 템플릿으로 빠른 배포
6. 유용한 Docker 앱들
6.1 Pi-hole: 네트워크 광고 차단
Pi-hole은 DNS 레벨에서 광고를 차단하는 서비스입니다. 한 번 설정하면 네트워크에 연결된 모든 기기에서 광고가 차단됩니다.
version: "3.8"
services:
pihole:
container_name: pihole
image: pihole/pihole:latest
ports:
- "53:53/tcp"
- "53:53/udp"
- "80:80/tcp"
environment:
TZ: 'Asia/Seoul'
WEBPASSWORD: 'your_password_here'
volumes:
- './etc-pihole:/etc/pihole'
- './etc-dnsmasq.d:/etc/dnsmasq.d'
restart: unless-stopped
설치 후 공유기의 DNS 서버를 Pi-hole 서버 IP로 변경하면 전체 네트워크에 적용됩니다.
6.2 Nginx Proxy Manager: 리버스 프록시
Nginx Proxy Manager는 여러 서비스에 도메인을 연결하고 SSL 인증서를 자동으로 관리해주는 도구입니다.
version: "3.8"
services:
npm:
image: 'jc21/nginx-proxy-manager:latest'
container_name: nginx-proxy-manager
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
restart: unless-stopped
초기 로그인 정보: Email admin@example.com, Password changeme
6.3 Homepage: 홈서버 대시보드
Homepage는 홈서버의 모든 서비스를 한눈에 볼 수 있는 대시보드입니다. 깔끔한 디자인과 다양한 서비스 위젯을 제공합니다.
version: "3.8"
services:
homepage:
image: ghcr.io/gethomepage/homepage:latest
container_name: homepage
ports:
- 3000:3000
volumes:
- ./config:/app/config
- /var/run/docker.sock:/var/run/docker.sock:ro
restart: unless-stopped
6.4 Uptime Kuma: 서비스 모니터링
Uptime Kuma는 웹사이트, 서비스, 포트 등의 가동 상태를 모니터링하고 알림을 보내주는 도구입니다.
version: "3.8"
services:
uptime-kuma:
image: louislam/uptime-kuma:latest
container_name: uptime-kuma
ports:
- "3001:3001"
volumes:
- ./data:/app/data
restart: unless-stopped
다운타임 발생 시 텔레그램, 디스코드, 이메일 등으로 알림을 받을 수 있습니다.
6.5 Vaultwarden: 비밀번호 관리자
Vaultwarden은 Bitwarden 호환 비밀번호 관리자입니다. 공식 Bitwarden 서버보다 훨씬 가볍고 셀프 호스팅에 최적화되어 있습니다.
version: "3.8"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
ports:
- "8000:80"
environment:
- SIGNUPS_ALLOWED=true
- ADMIN_TOKEN=your_random_admin_token
volumes:
- ./data:/data
restart: unless-stopped
HTTPS 없이는 보안상 위험하므로 반드시 리버스 프록시를 통해 SSL을 적용하세요.
7. 데이터 백업과 볼륨 관리
7.1 볼륨의 종류
- Named Volume: Docker가 관리하는 볼륨.
docker volume create로 생성 - Bind Mount: 호스트의 특정 경로를 컨테이너에 마운트
일반적으로 설정 파일이나 백업이 필요한 데이터는 Bind Mount를 사용하는 것이 관리하기 편합니다.
7.2 볼륨 관리 명령어
# 볼륨 목록 확인
docker volume ls
# 볼륨 상세 정보
docker volume inspect volume_name
# 볼륨 삭제
docker volume rm volume_name
# 사용하지 않는 볼륨 정리
docker volume prune
7.3 데이터 백업 전략
방법 1: Bind Mount 디렉토리 직접 백업
# 서비스 중지 후 백업
docker compose stop
tar -czvf backup_$(date +%Y%m%d).tar.gz ./data
docker compose start
방법 2: 실행 중인 컨테이너에서 백업
# MySQL/MariaDB 백업
docker exec my-db mysqldump -u root -p'password' --all-databases > backup.sql
# PostgreSQL 백업
docker exec my-postgres pg_dumpall -U postgres > backup.sql
방법 3: Named Volume 백업
# 임시 컨테이너로 볼륨 내용 백업
docker run --rm \
-v volume_name:/source:ro \
-v $(pwd):/backup \
alpine tar -czvf /backup/volume_backup.tar.gz -C /source .
7.4 자동 백업 스크립트
#!/bin/bash
# backup.sh
BACKUP_DIR="/backup/docker"
DATE=$(date +%Y%m%d_%H%M%S)
# 백업 디렉토리 생성
mkdir -p $BACKUP_DIR
# 각 서비스 데이터 백업
for dir in /opt/docker/*/; do
service=$(basename $dir)
tar -czvf "$BACKUP_DIR/${service}_${DATE}.tar.gz" -C $dir .
done
# 30일 이상된 백업 삭제
find $BACKUP_DIR -type f -mtime +30 -delete
echo "Backup completed: $DATE"
crontab에 등록하여 자동 실행할 수 있습니다.
# 매일 새벽 3시 백업
0 3 * * * /opt/scripts/backup.sh >> /var/log/docker-backup.log 2>&1
8. Docker 문제 해결
8.1 자주 발생하는 문제들
포트가 이미 사용 중일 때
# 포트 사용 중인 프로세스 확인
sudo lsof -i :80
# 또는 docker-compose.yml에서 다른 포트로 변경
권한 문제로 볼륨 접근이 안 될 때
# 호스트 디렉토리 권한 확인
ls -la ./data
# 권한 변경
sudo chown -R 1000:1000 ./data
컨테이너가 계속 재시작될 때
# 로그 확인
docker logs container_name
# 재시작 정책 변경
docker update --restart no container_name
8.2 디스크 공간 정리
# Docker가 사용하는 디스크 용량 확인
docker system df
# 사용하지 않는 모든 것 정리 (주의!)
docker system prune -a
# 볼륨 제외하고 정리
docker system prune
마무리
이번 편에서는 Docker의 기본 개념부터 실제 활용까지 폭넓게 다뤘습니다. Docker를 익히면 홈서버 운영이 정말 편해집니다. 새로운 서비스를 설치할 때 의존성 걱정 없이 docker-compose 파일 하나로 끝낼 수 있고, 문제가 생기면 컨테이너만 삭제하고 다시 시작하면 됩니다.
처음에는 명령어가 낯설게 느껴질 수 있지만, Portainer 같은 GUI 도구를 함께 사용하면 훨씬 쉽게 적응할 수 있습니다. 이 글에서 소개한 서비스들부터 하나씩 설치해보면서 Docker에 익숙해지시길 권합니다.
다음 편에서는 홈서버 보안을 강화하는 방법에 대해 알아보겠습니다. 방화벽 설정, VPN 구축, 침입 탐지 등 안전한 홈서버 운영을 위한 필수 지식을 다룰 예정입니다.