Docker 볼륨 실전 가이드: 5가지 예제로 컨테이너 데이터 유실 완벽 해결

터미널의 마지막 줄에 Database import completed successfully가 출력됐습니다. 네 시간이나 씨름한 끝에 드디어 테스트 데이터 2만 건을 MySQL 컨테이너로 가져왔습니다. API 몇 개를 호출해 봤고 테스트도 통과했습니다.
다음 날 아침, 습관처럼 docker ps를 입력해 컨테이너 상태를 확인했습니다. 아무것도 없었습니다. 어젯밤에 시작하는 걸 잊었나 싶어 서둘러 docker ps -a로 모든 컨테이너를 확인했지만 역시 찾을 수 없었습니다. 그제야 떠올랐습니다. 잠들기 전 디스크 공간을 정리하려고 무심코 docker system prune -a를 실행했던 것입니다.
끝장이었습니다. 모든 데이터가 사라졌습니다. 테스트 데이터 2만 건과 네 시간의 작업이 완전히 0으로 돌아갔습니다.
Docker를 배운 지 겨우 3주째라 컨테이너가 빠르게 시작되고 환경 격리가 잘된다는 것만 알았습니다. 컨테이너 자체는 데이터 저장에 적합하지 않다는 ‘아킬레스건’이 있다는 사실은 몰랐습니다. 컨테이너를 삭제하면 데이터도 사라지고, 다시 시작하면 설정 파일이 초기 상태로 돌아갑니다.
이 글에서는 다섯 가지 실전 사례를 통해 Docker Volume(데이터 볼륨)으로 데이터를 컨테이너 밖에 분리하는 방법을 단계별로 설명합니다. 이렇게 하면 데이터가 컨테이너의 생성과 삭제에 더 이상 영향을 받지 않습니다.
컨테이너 데이터 유실의 진실
컨테이너를 삭제하면 데이터는 왜 사라질까요?
Docker는 계층형 파일 시스템을 사용합니다. 여러 겹의 케이크를 떠올려 보세요. 아래쪽은 이미지 레이어로, 읽기 전용이며 모든 컨테이너가 공유합니다. 위쪽은 컨테이너 레이어로, 쓰기가 가능하며 각 컨테이너가 독점합니다. 컨테이너 안에서 만든 파일, 변경한 설정, 가져온 데이터는 모두 이 최상위 레이어에 기록됩니다.
핵심은 컨테이너를 삭제할 때 이 쓰기 가능 레이어도 함께 제거된다는 점입니다.
믿기 어렵다면 다음 명령을 실행해 보세요.
# Alpine 컨테이너를 시작하고 파일 쓰기
docker run -it --name test-container alpine sh
# 컨테이너 안에서 실행
echo "重要数据" > /tmp/data.txt
exit
# 컨테이너 삭제
docker rm test-container
# 데이터 복구 시도
docker run -it --name test-container alpine sh
cat /tmp/data.txt # 오류: No such file or directory
데이터는 아무런 경고도 없이 순식간에 사라집니다.
사실 이 설계는 꽤 합리적입니다. 컨테이너는 원래 ‘상태 비저장 애플리케이션’을 위해 설계됐습니다. Nginx나 API 서버를 생각해 보세요. 이런 애플리케이션은 데이터를 저장할 필요가 없고 시작할 때마다 상태가 같습니다. 그렇다면 데이터베이스, Redis, 파일 업로드 서비스는 어떨까요? 이들은 반드시 데이터를 보존해야 합니다.
Docker가 공식적으로 제공하는 해결책이 바로 Volume(데이터 볼륨)입니다. 데이터를 컨테이너 밖에 저장해 컨테이너의 수명과 데이터의 수명을 완전히 분리합니다.
Volume이란 무엇이며, 어떻게 데이터를 지킬까요?
Volume의 본질: Docker의 ‘외장 하드디스크’
Volume은 컨테이너에 외장 하드디스크를 연결하는 것과 같습니다. 데이터는 컨테이너 안이 아니라 호스트의 특정 디렉터리에 기록되고, 그 디렉터리를 컨테이너 내부의 특정 경로에 ‘마운트’합니다. 컨테이너에서는 /var/lib/mysql로 보이지만 실제 데이터는 호스트의 /var/lib/docker/volumes/mysql-data/_data에 저장됩니다.
컨테이너를 삭제해도 괜찮습니다. 데이터는 호스트에 그대로 남아 있습니다. 새 컨테이너를 시작하면서 같은 Volume을 다시 마운트하면 데이터가 돌아옵니다.
Docker는 세 가지 마운트 방식을 제공합니다. 초보자가 가장 자주 혼동하는 부분입니다.
| 마운트 유형 | 데이터 저장 위치 | 적합한 용도 | 관리 방식 |
|---|---|---|---|
| Volume | Docker가 관리하는 디렉터리(/var/lib/docker/volumes/) | 데이터베이스 영속화, 프로덕션 데이터 | Docker 명령으로 통합 관리 |
| Bind Mount | 호스트의 임의 경로 | 개발 중 코드와 설정 파일 마운트 | 경로를 직접 관리 |
| tmpfs | 메모리 | 임시 데이터, 민감 정보(디스크에 기록하지 않음) | 컨테이너가 중지되면 삭제 |
솔직히 저도 처음에는 Volume과 Bind Mount를 구분하지 못했습니다. 둘 다 ‘호스트 디렉터리를 컨테이너에 넣는 것’처럼 보였습니다. 그러다 문제가 생겼습니다. Bind Mount로 MySQL 데이터 디렉터리를 마운트한 뒤 실수로 호스트 디렉터리를 삭제했고, MySQL 컨테이너가 그대로 중단됐습니다.
Volume은 Docker가 완전히 관리하므로 경로, 권한, 백업 전략을 일일이 신경 쓸 필요가 없습니다. 데이터 위치가 궁금하면 docker volume inspect로 확인합니다. 데이터를 이전하고 싶다면 docker volume 명령으로 처리합니다. 이것이 공식 문서에서 Bind Mount보다 Volume을 권장하는 이유입니다.
Volume 데이터는 실제로 어디에 저장될까요?
Linux에서는 모든 Volume이 기본적으로 다음 위치에 저장됩니다.
/var/lib/docker/volumes/<volume-name>/_data/
Mac과 Windows 사용자는 이 경로를 찾지 않아도 됩니다. Docker Desktop은 가상 머신 안에서 실행되므로 호스트에서 이 경로를 볼 수 없습니다. 대신 docker volume inspect로 상세 정보를 확인할 수 있습니다.
5가지 예제로 익히는 Volume 핵심 사용법
이론은 여기까지입니다. 이제 직접 실습해 보겠습니다. 기초부터 실전까지 이어지는 다섯 가지 예제를 한 번 따라 하면 Volume을 확실히 이해할 수 있습니다.
사례 1: 첫 번째 이름 있는 Volume 만들기
가장 간단한 단계부터 시작해 빈 Volume을 만들어 보겠습니다.
# my-data라는 Volume 생성
docker volume create my-data
# 모든 Volume 확인
docker volume ls
# Volume 상세 정보 확인
docker volume inspect my-data
예상 출력(inspect 명령):
[
{
"CreatedAt": "2025-12-17T12:00:00Z",
"Driver": "local",
"Mountpoint": "/var/lib/docker/volumes/my-data/_data",
"Name": "my-data"
}
]
Mountpoint가 보이나요? 이곳이 데이터가 실제로 저장되는 위치입니다.
사례 2: Nginx 정적 웹사이트 영속화
상황을 가정해 보겠습니다. 정적 웹사이트를 개발하면서 코드를 수정할 때마다 Nginx 컨테이너를 다시 시작합니다. 그런데 재시작할 때마다 이전에 업로드한 이미지와 로그가 사라집니다.
해결 방법은 Nginx의 /usr/share/nginx/html 디렉터리를 Volume에 마운트하는 것입니다.
# 웹사이트 콘텐츠를 저장할 Volume 생성
docker volume create nginx-html
# Nginx 컨테이너를 시작하고 Volume 마운트
docker run -d \
--name my-nginx \
-p 8080:80 \
-v nginx-html:/usr/share/nginx/html \
nginx:latest
# 컨테이너에 들어가 테스트 페이지 생성
docker exec my-nginx bash -c 'echo "<h1>Hello Docker Volume!</h1>" > /usr/share/nginx/html/index.html'
# 접속 테스트(브라우저에서 http://localhost:8080을 열거나 명령줄에서 테스트)
curl http://localhost:8080
이제 컨테이너를 삭제합니다.
docker rm -f my-nginx
새 컨테이너를 시작하고 같은 Volume을 마운트합니다.
docker run -d \
--name my-nginx-v2 \
-p 8080:80 \
-v nginx-html:/usr/share/nginx/html \
nginx:latest
# 다시 접속해도 콘텐츠가 그대로 남아 있습니다!
curl http://localhost:8080
데이터가 사라지지 않았습니다. 이것이 Volume의 힘입니다.
사례 3: MySQL 데이터 영속화(실전)
가장 흔한 요구 사항입니다. MySQL을 컨테이너로 배포한다면 데이터는 반드시 영속화해야 합니다.
# MySQL 전용 Volume 생성
docker volume create mysql-data
# MySQL 컨테이너 시작
docker run -d \
--name mysql-demo \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-e MYSQL_DATABASE=testdb \
-p 3306:3306 \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# MySQL이 시작될 때까지 대기(약 10초)
sleep 10
# MySQL에 연결해 테스트 테이블 생성
docker exec -it mysql-demo mysql -uroot -pmy-secret-pw testdb -e "
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50)
);
INSERT INTO users (name) VALUES ('Alice'), ('Bob');
"
# 데이터 조회
docker exec -it mysql-demo mysql -uroot -pmy-secret-pw testdb -e "SELECT * FROM users;"
이제 실수로 삭제한 상황을 재현해 컨테이너를 삭제합니다.
docker rm -f mysql-demo
같은 Volume을 마운트해 MySQL 컨테이너를 다시 시작합니다.
docker run -d \
--name mysql-demo-v2 \
-e MYSQL_ROOT_PASSWORD=my-secret-pw \
-p 3306:3306 \
-v mysql-data:/var/lib/mysql \
mysql:8.0
# 시작될 때까지 대기
sleep 10
# 데이터가 그대로 남아 있는지 조회
docker exec -it mysql-demo-v2 mysql -uroot -pmy-secret-pw testdb -e "SELECT * FROM users;"
핵심: MySQL의 데이터 디렉터리는 /var/lib/mysql이며, 반드시 이 경로를 마운트해야 합니다. 데이터베이스마다 경로가 다릅니다. Redis는 /data, PostgreSQL은 /var/lib/postgresql/data를 사용합니다.
사례 4: Redis 영속화 설정
Redis는 기본적으로 데이터를 메모리에 저장하지만, RDB나 AOF를 사용해 디스크에 영속화하도록 설정할 수 있습니다.
# Redis 데이터 Volume 생성
docker volume create redis-data
# Redis 컨테이너를 시작하고 AOF 영속화 활성화
docker run -d \
--name redis-demo \
-p 6379:6379 \
-v redis-data:/data \
redis:latest redis-server --appendonly yes
# --appendonly yes로 AOF 영속화 활성화
# 테스트 데이터 쓰기
docker exec -it redis-demo redis-cli SET mykey "Hello Redis Volume"
# 데이터 읽기
docker exec -it redis-demo redis-cli GET mykey
컨테이너를 삭제합니다.
docker rm -f redis-demo
다시 시작합니다.
docker run -d \
--name redis-demo-v2 \
-p 6379:6379 \
-v redis-data:/data \
redis:latest redis-server --appendonly yes
# 데이터가 그대로 남아 있음
docker exec -it redis-demo-v2 redis-cli GET mykey
주의: 반드시 --appendonly yes 매개변수를 추가해야 합니다. 그렇지 않으면 Redis는 데이터를 메모리에만 저장하므로 컨테이너를 다시 시작했을 때 데이터가 여전히 유실될 수 있습니다.
사례 5: 여러 컨테이너가 Volume 공유하기
한 Nginx 컨테이너는 정적 파일을 제공하고, 다른 애플리케이션 컨테이너는 로그를 생성한다고 가정해 보겠습니다. 두 컨테이너가 같은 Volume을 공유합니다.
# 공유 Volume 생성
docker volume create shared-logs
# 애플리케이션 컨테이너를 시작해 로그 쓰기
docker run -d \
--name app-writer \
-v shared-logs:/logs \
alpine sh -c "while true; do echo $(date) >> /logs/app.log; sleep 2; done"
# Nginx 컨테이너를 시작해 로그 읽기
docker run -d \
--name log-reader \
-p 8080:80 \
-v shared-logs:/usr/share/nginx/html:ro \
nginx:latest
# :ro는 읽기 전용 마운트를 의미하며 Nginx가 실수로 로그를 수정하는 것을 방지함
# app-writer가 로그를 기록하도록 몇 초 대기
sleep 5
# 로그 파일 접속(브라우저에서 http://localhost:8080/app.log 열기)
curl http://localhost:8080/app.log
핵심:
- 하나의 Volume을 여러 컨테이너에 동시에 마운트할 수 있습니다.
:ro접미사를 추가하면 읽기 전용 모드로 설정돼 보안이 향상됩니다.- 실제 프로덕션에서는 이런 방식으로 ‘로그 수집 컨테이너 + 애플리케이션 컨테이너’ 아키텍처를 구현할 수 있습니다.
Volume 관리 명령
다섯 가지 예제를 모두 마치면 ‘이 Volume을 어떻게 확인하고 삭제하거나 정리하지?‘라는 의문이 생길 수 있습니다.
다음은 전체 관리 명령을 정리한 빠른 참조표입니다.
# 1. Volume 생성
docker volume create <volume-name>
# 2. 모든 Volume 목록 보기
docker volume ls
# 3. Volume 상세 정보 확인(마운트 경로 포함)
docker volume inspect <volume-name>
# 4. 지정한 Volume 삭제
docker volume rm <volume-name>
# 주의: Volume을 컨테이너가 사용 중이면 오류 발생
# 5. 사용하지 않는 모든 Volume 삭제(디스크 공간 정리)
docker volume prune
# 확인 메시지가 표시되면 y를 입력해 계속 진행
# 6. 사용하지 않는 모든 Volume 강제 삭제(확인 생략)
docker volume prune -f
흔한 문제: Volume을 삭제할 때 volume is in use가 표시되는 경우
이 메시지는 컨테이너가 해당 Volume을 사용 중이라는 뜻입니다. 다음과 같이 해결합니다.
# 어떤 컨테이너가 사용 중인지 확인
docker ps -a --filter volume=<volume-name>
# 먼저 컨테이너 중지 및 삭제
docker rm -f <container-name>
# Volume 삭제
docker volume rm <volume-name>
디스크 공간 사용량 확인
Volume이 디스크 공간을 얼마나 차지하는지 알고 싶다면 다음 명령을 사용해 보세요.
# Linux/Mac 사용자
docker volume inspect <volume-name> --format '{{ .Mountpoint }}' | xargs du -sh
# 출력 예: 512M /var/lib/docker/volumes/mysql-data/_data
Bind Mount와 Volume: 무엇을 사용해야 할까요?
초보자가 가장 많이 고민하는 문제입니다. 저도 처음에는 잘 구분하지 못해 둘을 뒤섞어 사용하곤 했습니다.
한 문장으로 기억하면 됩니다. 프로덕션 데이터에는 Volume, 개발 코드에는 Bind Mount를 사용하세요.
구체적인 권장 사항은 다음과 같습니다.
| 상황 | 권장 방식 | 이유 |
|---|---|---|
| MySQL/PostgreSQL 데이터베이스 | Volume | Docker가 관리해 백업이 편하고 성능이 좋음 |
| Redis/MongoDB 영속화 | Volume | 위와 동일 |
| 로그 파일, 업로드 파일 | Volume | 데이터가 안전하고 컨테이너 삭제의 영향을 받지 않음 |
| 개발 중 소스 코드 마운트 | Bind Mount | 코드를 수정하면 컨테이너를 다시 시작하지 않아도 즉시 반영됨 |
| 설정 파일(nginx.conf) 마운트 | Bind Mount | 설정을 편리하게 수정하고 빠르게 테스트할 수 있음 |
| 임시 데이터, 캐시 | tmpfs | 성능이 가장 좋고 디스크 공간을 사용하지 않음 |
구문 비교
# Volume 방식(영속 데이터에 권장)
docker run -v my-volume:/data redis:latest
# Bind Mount 방식(개발 환경에 권장)
docker run -v /Users/me/code:/app node:latest
# 새 구문 --mount(더 명확하므로 프로덕션 환경에 권장)
docker run --mount type=volume,source=my-volume,target=/data redis:latest
docker run --mount type=bind,source=/Users/me/code,target=/app node:latest
결정 트리
새로운 요구 사항에서 무엇을 사용해야 할지 모르겠다면 다음 세 가지를 자문해 보세요.
-
데이터를 장기간 보존해야 하나요?
예 → Volume, 아니요 → tmpfs -
호스트에서 데이터를 직접 수정해야 하나요?
예 → Bind Mount, 아니요 → Volume -
프로덕션 환경인가요, 개발 환경인가요?
프로덕션 → Volume, 개발 → Bind Mount
실제 사례 비교
제 개발 환경은 다음과 같습니다.
# 개발 시: 코드는 Bind Mount, 데이터베이스는 Volume 사용
docker run -d \
--name dev-app \
-v $(pwd)/src:/app/src \ # Bind Mount: 코드 변경 사항이 즉시 반영됨
-v app-uploads:/app/uploads \ # Volume: 사용자가 업로드한 파일
-v postgres-data:/var/lib/postgresql/data \ # Volume: 데이터베이스 데이터
my-app:dev
제 프로덕션 환경은 다음과 같습니다.
# 프로덕션에서는 모두 Volume 사용
docker run -d \
--name prod-app \
-v app-uploads:/app/uploads \
-v postgres-data:/var/lib/postgresql/data \
my-app:latest
# 코드는 이미 이미지에 패키징되어 있어 마운트할 필요가 없음
자주 묻는 질문과 모범 사례
FAQ: 직접 겪은 문제와 해결 방법
Q1: Volume의 데이터도 유실될 수 있나요?
아닙니다. docker volume rm을 직접 실행하지 않는 한 데이터는 계속 보존됩니다. 호스트를 다시 시작해도 데이터는 남아 있습니다.
다만 docker system prune -a --volumes는 사용하지 않는 모든 Volume을 삭제하므로 주의해서 사용해야 합니다!
Q2: 컨테이너를 시작할 때 Volume이 없으면 어떻게 되나요?
Docker가 자동으로 생성합니다. 다음 명령을 실행해 보세요.
# 미리 docker volume create를 실행하지 않고 바로 시작
docker run -d -v auto-created-volume:/data alpine
# Docker가 auto-created-volume이라는 Volume을 자동 생성함
그래도 저는 직접 생성하는 방식을 권합니다. 데이터가 어디에 저장되는지 더 명확하게 알 수 있기 때문입니다.
Q3: Volume 데이터는 어떻게 백업하나요?
공식 권장 방법은 다음과 같습니다.
# 임시 컨테이너를 시작해 Volume 데이터 압축
docker run --rm \
-v mysql-data:/source \
-v $(pwd):/backup \
alpine tar -czf /backup/mysql-backup.tar.gz -C /source .
# 복원할 때
docker run --rm \
-v mysql-data:/target \
-v $(pwd):/backup \
alpine tar -xzf /backup/mysql-backup.tar.gz -C /target
Q4: Volume을 서로 다른 호스트 간에 이전할 수 있나요?
가능하지만 직접 작업해야 합니다.
- 원래 호스트에서 위 방법으로 Volume 데이터를 압축합니다.
.tar.gz파일을 새 호스트로 전송합니다.- 새 호스트에서 Volume을 만들고 데이터를 압축 해제합니다.
더 고급 방법으로는 NFS나 클라우드 스토리지를 Volume Driver로 사용할 수 있습니다.
Q5: 익명 Volume이란 무엇이며 어떻게 정리하나요?
Volume 이름을 지정하지 않으면 Docker가 익명 Volume을 생성합니다.
docker run -d -v /data alpine # a1b2c3d4...와 같은 임의의 이름 생성
익명 Volume은 관리하기 어렵고 쌓이면서 디스크 공간을 차지하기 쉽습니다. 다음과 같이 정리합니다.
docker volume prune # 익명 Volume을 포함해 사용하지 않는 모든 Volume 삭제
항상 이름 있는 Volume을 사용하는 것이 가장 좋은 방법입니다.
6가지 모범 사례(프로덕션 환경 필수)
-
항상 이름 있는 Volume 사용
# ✓ 좋은 습관 docker run -v mysql-data:/var/lib/mysql mysql:8.0 # ✗ 나쁜 습관 docker run -v /var/lib/mysql mysql:8.0 # 익명 Volume -
중요 데이터 정기 백업
예약 작업을 설정해 데이터베이스 Volume을 매일 백업하세요. 데이터를 잃는 기분은 한 번 겪어 보면 잊기 어렵습니다. -
Docker Compose로 복잡한 프로젝트 관리
# docker-compose.yml services: db: image: mysql:8.0 volumes: - mysql-data:/var/lib/mysql volumes: mysql-data: driver: local -
프로덕션 환경에서는 -v 대신 —mount 사용
--mount구문은 더 명확하고 오류 메시지도 이해하기 쉽습니다.docker run --mount type=volume,source=mysql-data,target=/var/lib/mysql mysql:8.0 -
사용하지 않는 Volume 정기 정리
매월 한 번 실행하세요.docker volume prune -
민감 데이터에는 암호화된 Volume 사용
Volume에 비밀번호나 키가 있다면 LUKS 암호화 파티션 같은 암호화 방식을 고려하세요.
결론
글을 시작하며 소개한 그 새벽으로 돌아가 보겠습니다. 그때 Docker Volume을 알았다면 다음 한 줄이면 충분했습니다.
docker run -d --name mysql-demo -v mysql-data:/var/lib/mysql mysql:8.0
그러면 데이터는 컨테이너와 함께 사라지지 않았을 것입니다. 네 시간의 작업과 테스트 데이터 2만 건이 모두 호스트에 안전하게 남아 있었을 것입니다.
Docker 컨테이너 자체는 ‘상태 비저장’입니다. 이것은 장점인 동시에 한계이기도 합니다. Volume은 바로 이 한계를 극복하기 위해 존재합니다. 컨테이너의 가벼움과 격리라는 장점을 누리면서도 데이터를 안심하고 저장할 수 있게 해 줍니다.
이 글에서는 첫 Volume 생성부터 Nginx 정적 웹사이트 영속화, MySQL과 Redis를 활용한 실전 사례, 여러 컨테이너의 Volume 공유까지 다섯 가지 예제를 살펴봤습니다. 이 사례만 익혀도 일상적인 개발 요구의 90%를 해결할 수 있습니다.
이제 직접 해 볼 차례입니다. 터미널을 열어 첫 Volume을 만들고 MySQL 컨테이너를 시작한 뒤 데이터를 조금 입력해 보세요. 그런 다음 컨테이너를 삭제하고 다시 시작해 데이터가 그대로 남아 있는 순간을 확인하면 ‘데이터 영속화’의 의미를 제대로 이해하게 될 것입니다.
마지막으로 새벽 3시에 데이터가 사라지는 공포를 다시 겪고 싶지 않다면 이 글을 저장해 두세요. 언젠가 큰 도움이 될지도 모릅니다.
Docker 데이터 볼륨 실전 전체 과정
기본 개념부터 MySQL·Redis 영속화까지, 5가지 예제로 컨테이너 데이터 유실 문제를 완벽하게 해결합니다.
⏱️ Estimated time: 30 min
- 1
Step 1: 문제의 원인 이해: 컨테이너 데이터가 유실되는 이유
문제의 원인:
• Docker 컨테이너 자체는 데이터 저장에 적합하지 않아 컨테이너를 삭제하면 데이터도 사라짐
• 컨테이너를 다시 시작하면 설정 파일이 초기 상태로 돌아감
• 컨테이너를 삭제할 때 쓰기 가능 레이어도 함께 제거됨
• 이것이 Docker의 '아킬레스건'임
Docker 계층형 파일 시스템:
• 아래쪽은 이미지 레이어로, 읽기 전용이며 모든 컨테이너가 공유함
• 위쪽은 컨테이너 레이어로, 쓰기가 가능하며 각 컨테이너가 독점함
• 컨테이너 안에서 만든 파일, 변경한 설정, 가져온 데이터는 모두 이 최상위 레이어에 기록됨
• 컨테이너를 삭제하면 이 쓰기 가능 레이어도 함께 제거됨 - 2
Step 2: 사례 1: 첫 번째 Volume 만들기
Volume 생성:
• docker volume create 명령으로 Volume 생성
• 명령: docker volume create my-data
• Volume은 Docker가 관리하며 Docker 데이터 디렉터리에 저장되므로 프로덕션 환경에 적합함
Volume 사용:
• 컨테이너를 시작할 때 Volume 마운트: docker run -d -v my-data:/data alpine
• 데이터가 Volume에 저장되므로 컨테이너를 삭제해도 유실되지 않음
Volume 확인:
• docker volume ls로 모든 Volume 확인
• docker volume inspect my-data로 Volume 상세 정보 확인 - 3
Step 3: 사례 2~5: Nginx·MySQL·Redis 영속화 및 여러 컨테이너 공유
사례 2: Nginx 정적 웹사이트 영속화
• 컨테이너에 Volume 마운트: docker run -d -v nginx-html:/usr/share/nginx/html nginx
• 정적 파일이 Volume에 저장되므로 컨테이너를 삭제해도 파일이 유실되지 않음
사례 3: MySQL 데이터 영속화
• /var/lib/mysql에 Volume 마운트: docker run -d -v mysql-data:/var/lib/mysql mysql:8.0
• 데이터베이스 데이터가 Volume에 저장되므로 컨테이너를 삭제해도 유실되지 않음
사례 4: Redis 데이터 영속화
• /data에 Volume 마운트: docker run -d -v redis-data:/data redis
• Redis 데이터가 Volume에 저장되므로 컨테이너를 삭제해도 유실되지 않음
사례 5: 여러 컨테이너가 Volume 공유
• 여러 컨테이너에 동일한 Volume 마운트:
docker run -d -v shared-data:/data container1
docker run -d -v shared-data:/data container2
• 여러 컨테이너가 데이터를 공유할 수 있음 - 4
Step 4: Volume과 Bind Mount 비교 및 모범 사례
Volume과 Bind Mount 비교:
Volume
• Docker가 관리하며 Docker 데이터 디렉터리에 저장됨
• 더 안전하고 신뢰할 수 있어 프로덕션 환경에 적합함
Bind Mount
• 호스트 디렉터리를 직접 마운트함
• 설정이 유연해 개발 환경에 적합함
모범 사례:
• 프로덕션 환경에서는 Volume 사용
• 개발 환경에서는 Bind Mount 사용 가능
• Volume 데이터를 정기적으로 백업:
docker run --rm -v mysql-data:/data -v $(pwd):/backup alpine tar czf /backup/mysql-backup.tar.gz /data
• 관리하기 쉽도록 이름 있는 Volume을 사용하고 익명 Volume은 피함
• 사용하지 않는 Volume을 정기적으로 정리: 매월 docker volume prune을 한 번 실행해 미사용 Volume 삭제
FAQ
컨테이너 데이터는 왜 유실되나요? Docker 컨테이너는 데이터 저장에 적합하지 않나요?
Docker는 계층형 파일 시스템을 사용합니다. 여러 겹의 케이크를 떠올려 보세요.
• 아래쪽은 이미지 레이어로, 읽기 전용이며 모든 컨테이너가 공유함
• 위쪽은 컨테이너 레이어로, 쓰기가 가능하며 각 컨테이너가 독점함
• 컨테이너 안에서 만든 파일, 변경한 설정, 가져온 데이터는 모두 이 최상위 레이어에 기록됨
• 컨테이너를 삭제하면 이 쓰기 가능 레이어도 함께 제거됨
Docker Volume으로 데이터 유실 문제를 어떻게 해결하나요?
Volume 생성:
• docker volume create 명령으로 Volume 생성: docker volume create my-data
• Volume은 Docker가 관리하며 Docker 데이터 디렉터리에 저장되므로 프로덕션 환경에 적합함
Volume 사용:
• 컨테이너를 시작할 때 Volume 마운트: docker run -d -v my-data:/data alpine
• 데이터가 Volume에 저장되므로 컨테이너를 삭제해도 유실되지 않음
MySQL과 Redis의 데이터 영속화는 어떻게 설정하나요?
• /var/lib/mysql에 Volume 마운트: docker run -d -v mysql-data:/var/lib/mysql mysql:8.0
• 데이터베이스 데이터가 Volume에 저장되므로 컨테이너를 삭제해도 유실되지 않음
Redis 데이터 영속화:
• /data에 Volume 마운트: docker run -d -v redis-data:/data redis
• Redis 데이터가 Volume에 저장되므로 컨테이너를 삭제해도 유실되지 않음
영속화 확인:
• 컨테이너를 삭제한 뒤 다시 만들어도 데이터가 남아 있음
• docker volume inspect로 Volume 위치 확인
• 데이터는 호스트에 저장됨
Volume과 Bind Mount의 차이는 무엇이며, 무엇을 사용해야 하나요?
Volume:
• Docker가 관리하며 Docker 데이터 디렉터리에 저장됨
• 더 안전하고 신뢰할 수 있어 프로덕션 환경에 적합함
Bind Mount:
• 호스트 디렉터리를 직접 마운트함
• 설정이 유연해 개발 환경에 적합함
선택 기준:
• 프로덕션 환경에서는 Volume 사용(Docker가 데이터를 관리하므로 더 안전하고 신뢰할 수 있음)
• 개발 환경에서는 Bind Mount 사용 가능(호스트 파일에 직접 접근할 수 있어 디버깅이 더 편리함)
모범 사례:
• 프로덕션 환경에서는 Volume 사용
• 개발 환경에서는 Bind Mount 사용 가능
• Volume 데이터를 정기적으로 백업
• 관리하기 쉽도록 이름 있는 Volume 사용
• 익명 Volume은 피함
4분 읽기 · 게시일: 2025년 12월 17일 · 수정일: 2026년 9월 4일
Docker 실전 가이드
검색으로 들어왔다면 같은 시리즈의 이전 글이나 다음 글로 이동하는 것이 가장 빠릅니다.
이전
Docker Compose로 PHP 환경 한 번에 배포하기: DNMP 완전 가이드(Nginx+MySQL+PHP)
Docker Compose를 사용해 DNMP(Docker+Nginx+MySQL+PHP) 개발 환경을 한 번에 배포하는 방법을 단계별로 설명합니다. 10분이면 팀별 환경 차이를 완전히 해결할 수 있으며, 전체 설정 파일과 문제 해결 가이드도 제공합니다.
33편 중 12편
다음
Docker 볼륨 백업과 마이그레이션 실전 가이드: 3가지 방법 완전 분석
tar 압축, docker cp 명령어, 자동화 도구를 활용한 Docker 볼륨 백업 3가지 방법을 자세히 설명합니다. 데이터베이스 백업 주의사항, 서버 마이그레이션 전체 절차, 실수 방지 가이드까지 담아 Docker 데이터 백업을 간단하고 안정적으로 수행할 수 있습니다.
33편 중 14편



댓글
GitHub로 로그인하여 댓글을 남기세요