Docker 볼륨과 바인딩 마운트: 컨테이너 데이터를 올바른 방식으로 유지

  1. 홈
  2. 블로그
  3. 데브옵스

데브옵스

Docker 볼륨과 바인딩 마운트: 올바른 방식으로 컨테이너 데이터 유지

컨테이너를 제거하면 더 안전한 곳에 저장하지 않는 한 해당 데이터도 함께 이동됩니다. 볼륨, 바인드 마운트 및 tmpfs의 차이점, 각각의 사용 시기, 중요한 백업 방법을 알아보세요.

읽는 시간 9분
Docker 볼륨과 바인드 마운트: 컨테이너 데이터를 올바른 방식으로 유지

핵심 요약

  • 컨테이너의 쓰기 가능한 레이어는 컨테이너와 함께 삭제되므로 중요한 데이터는 마운트가 필요합니다.
  • 명명된 볼륨은 Docker에 의해 관리되며 데이터베이스 및 프로덕션 데이터에 일반적으로 선택됩니다.
  • 바인드 마운트 호스트 폴더를 매핑하므로 개발 중 라이브 코드에 이상적입니다.
  • docker compose down -v 볼륨을 삭제하므로 주의해서 사용하고 테스트된 백업을 보관하세요.

컨테이너에서 데이터베이스를 시작하고, 일부 데이터를 추가하고, 컨테이너를 제거하고, 새 컨테이너를 시작합니다. 데이터가 사라졌습니다. 거의 모든 사람이 이 교훈을 어려운 방법으로 배웁니다. Docker 볼륨 및 바인드 마운트는 하나의 컨테이너 수명 이후에도 데이터를 유지하기 위해 존재합니다.

이 가이드에서는 각각의 작동 방식과 선택 방법을 설명합니다. 여기에 있는 명령과 파일은 Docker의 문서화된 동작을 기반으로 한 표준 예제이며 이 기사에서는 실행하지 않았으므로 일회용 데이터에 먼저 사용해 보세요. 세부 정보는 Docker 버전과 Docker Desktop에 따라 다를 수 있습니다. 컨테이너를 처음 사용하는 경우 초보자를 위한 Docker 튜토리얼부터 시작하세요.

컨테이너 데이터가 사라지는 이유

Docker 이미지는 읽기 전용 레이어로 구성됩니다. 컨테이너가 시작되면 Docker는 쓰기 가능한 얇은 레이어를 맨 위에 추가하고 모든 변경 사항이 거기에 적용됩니다. 해당 레이어는 중지했다가 다시 시작해도 유지되지만 컨테이너가 삭제되면 제거됩니다.

docker run -d --name db -e POSTGRES_PASSWORD=devonly postgres:17
# ... create tables and add data ...
docker rm -f db
docker run -d --name db -e POSTGRES_PASSWORD=devonly postgres:17
# The data you added is not there

이는 컨테이너를 자유롭게 교체할 수 있도록 의도적으로 설계된 것입니다. 이는 보관해야 할 모든 항목이 컨테이너 외부에 있어야 함을 의미합니다. 이를 수행하는 세 가지 방법이 있습니다:

유형 저장 위치 용기를 제거해도 살아남나요?
명명된 볼륨 Docker가 관리하는 영역 예
바인드 마운트 선택한 호스트 경로 예
tmpfs 마운트 호스트 메모리 아니요

Docker 볼륨과 바인드 마운트를 나란히 배치

측면 명명된 볼륨 바인드 마운트
관리인 도커 당신
위치 Docker의 저장 영역 호스트의 모든 경로
호스트 폴더에 따라 달라집니까? 아니요 예
호스트에서 편집 디자인상 어색함 쉽고, 변경 사항이 즉시 나타납니다.
이미지에서 미리 채워진 빈 대상? 예 아니요, 호스트 경로가 이를 숨깁니다.
도커 CLI 명령 네, docker volume 아니요
원격 저장소용 드라이버 예 아니요
다음에 가장 적합 데이터베이스, 생산 데이터 개발 중인 소스 코드

명명된 볼륨

볼륨은 Docker가 생성하고 관리하는 스토리지입니다. 이름으로 참조하면 물리적으로 어디에 사는지 신경 쓸 필요가 없습니다.

docker volume create pgdata

docker run -d --name db \
  -e POSTGRES_PASSWORD=devonly \
  -v pgdata:/var/lib/postgresql/data \
  postgres:17

이제 데이터베이스 파일은 pgdata에 있습니다. 컨테이너를 삭제하고 동일한 볼륨으로 새 컨테이너를 시작하면 데이터는 그대로 유지됩니다. Linux에서 볼륨은 일반적으로 /var/lib/docker/volumes/ 아래에 있지만 해당 파일을 직접 편집하면 안 됩니다. Docker Desktop에서는 일반 폴더가 아닌 가상 머신 내부에 있습니다.

컨테이너 내부의 경로는 이미지에 따라 다르므로 이미지 설명서를 확인하세요. 잘못된 경로에 마운트하는 것은 전형적인 실수입니다. 모든 것이 작동하는 것처럼 보이지만 데이터는 여전히 컨테이너 계층에 기록되고 있습니다. 최신 주요 버전의 이미지도 이 경로를 변경할 수 있으므로 업그레이드하기 전에 릴리스 노트를 읽어보세요.

Docker는 이름이 지정된 볼륨이 없으면 자동으로 생성합니다. 이름 없이 생성된 익명 볼륨도 작동하지만 긴 임의 ID를 가지며 추적하기 쉽습니다. 항상 볼륨 이름을 지정하십시오.

바인드 마운트

바인드 마운트는 특정 호스트 경로를 컨테이너에 직접 매핑합니다. 양측 모두 동일한 파일을 즉시 볼 수 있습니다. 편집기의 편집 내용은 다시 빌드하지 않고도 실행 중인 컨테이너에 적용되므로 개발에 적합합니다.

docker run -d --name web \
  -p 8080:80 \
  -v "$(pwd)/site:/usr/share/nginx/html:ro" \
  nginx:1.27

site/의 파일을 편집하고 브라우저를 새로 고치면 변경 사항이 표시됩니다. :ro는 컨테이너 내부에서 마운트를 읽기 전용으로 만듭니다. 이는 컨테이너가 거기에 쓸 필요가 없을 때 좋은 습관입니다.

바인드 마운트에는 몇 가지 장단점이 있습니다.

  • 호스트에 연결됩니다. 경로는 각 시스템에 존재해야 하므로 설정의 이식성이 떨어집니다.
  • 이미지 내용을 숨깁니다. /app 위에 마운트하면 거기에 있던 이미지가 무엇이든 보이지 않게 됩니다. 일반적인 예는 node_modules이 사라지는 것입니다.
  • 호스트를 노출합니다. 쓰기 가능한 마운트가 있는 컨테이너는 실제 호스트 파일을 변경하거나 삭제할 수 있습니다. 위험을 완전히 이해하지 않는 한 / 또는 Docker 소켓과 같은 민감한 경로를 마운트하지 마십시오.
  • 성능은 다를 수 있습니다. macOS 및 Windows용 Docker Desktop에서 파일 공유는 가상화 경계를 넘어 Linux보다 느릴 수 있습니다.

tmpfs 마운트

tmpfs 마운트는 호스트의 메모리에 상주하며 컨테이너 계층에 기록되지 않습니다. 컨테이너가 중지되면 사라지므로 임시 파일, 캐시 및 단기 민감한 데이터에 적합합니다.

docker run -d --tmpfs /app/cache:size=64m myapp:1.0

tmpfs는 Linux 호스트에서 사용할 수 있습니다. 또한 데이터 유지에 신경 쓰지 않는 일회용 테스트 환경에서 데이터베이스 속도를 높일 수도 있습니다.

-v 또는 –mount?

두 플래그 모두 작동합니다. --mount은 더 길지만 더 명확하고 많은 사람들이 스크립트에서 이를 선호합니다.

# Short form
docker run -v pgdata:/var/lib/postgresql/data postgres:17

# Explicit form
docker run --mount type=volume,source=pgdata,target=/var/lib/postgresql/data postgres:17

# Bind mount, read-only
docker run --mount type=bind,source="$(pwd)"/site,target=/usr/share/nginx/html,readonly nginx:1.27

한 가지 의미 있는 차이점이 있습니다. -v을 사용하면 누락된 호스트 경로가 빈 폴더로 생성되어 오타를 숨길 수 있습니다. --mount 및 바인드 유형을 사용하면 Docker가 대신 오류를 보고합니다. 또한 -v에서는 왼쪽이 유형을 결정합니다. 이름은 볼륨을 의미하고 경로는 바인드 마운트를 의미합니다. 따라서 -v data:/x와 -v ./data:/x는 매우 다른 작업을 수행합니다.

Docker Compose의 볼륨

대부분의 실제 프로젝트는 Compose 파일에 저장소를 선언합니다. 이것은 적절한 작업을 위해 두 가지 종류를 모두 사용합니다.

services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - ./src:/app/src      # bind mount: live code
    depends_on:
      - db

  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: devonly
    volumes:
      - pgdata:/var/lib/postgresql/data   # named volume: data

volumes:
  pgdata:

명명된 볼륨은 최상위 volumes 섹션에서 선언되어야 합니다. Compose에는 실제 이름 앞에 프로젝트 이름이 붙습니다. 전체 연습을 보려면 Docker Compose 튜토리얼을 참조하세요.

팁: docker compose down는 명명된 볼륨을 유지하지만 docker compose down -v은 데이터와 함께 해당 볼륨을 삭제합니다. -v를 포함하는 스크립트와 쉘 기록에 특히 주의하십시오.

유용한 볼륨 명령

명령 기능
도커 볼륨 ls 볼륨 나열
도커 볼륨 생성 이름 볼륨을 생성합니다
도커 볼륨 검사 이름 위치를 포함한 세부정보를 표시합니다.
도커 볼륨 rm 이름 볼륨과 해당 데이터를 삭제합니다.
도커 볼륨 정리 사용하지 않는 볼륨을 제거합니다.
도커 시스템 df -v 볼륨을 포함한 디스크 사용량을 표시합니다.

이 작업은 취소할 수 없으므로 확인하기 전에 prune이 제거할 내용을 확인하십시오. 현재 어떤 컨테이너도 사용하지 않는 볼륨에는 여전히 중요한 데이터가 보관될 수 있습니다.

볼륨 백업 및 복원

볼륨과 호스트 폴더를 모두 탑재하는 단기 컨테이너를 실행하여 볼륨을 백업할 수 있습니다.

# Back up
docker run --rm \
  -v pgdata:/data:ro \
  -v "$(pwd)":/backup \
  alpine tar czf /backup/pgdata.tar.gz -C /data .

# Restore into a new volume
docker volume create pgdata_restored
docker run --rm \
  -v pgdata_restored:/data \
  -v "$(pwd)":/backup \
  alpine tar xzf /backup/pgdata.tar.gz -C /data

라이브 데이터베이스의 경우 이와 같은 파일을 복사하면 일관되지 않은 상태가 캡처될 수 있습니다. 먼저 컨테이너를 중지하거나 PostgreSQL용 pg_dump과 같은 데이터베이스 자체 도구를 사용하는 것이 좋습니다. 그리고 한 번도 복원하지 않은 백업은 실제로는 희망일 뿐이므로 복원을 테스트해 보세요.

파일 권한

“권한 거부”는 마운트와 관련된 가장 일반적인 문제입니다. 파일은 Linux에서 숫자 사용자 및 그룹 ID를 유지하므로 컨테이너가 사용자 1000으로 실행되고 호스트 폴더가 다른 사용자에 속하는 경우 쓰기가 실패합니다. 이 문제를 해결하는 몇 가지 방법은 다음과 같습니다.

  • 일치하는 사용자로 컨테이너를 실행합니다: docker run --user "$(id -u):$(id -g)" ...
  • Dockerfile 모범 사례에 설명된 대로 이미지에 올바른 소유권을 설정하세요.
  • 새 볼륨이 처음 사용될 때 이미지 폴더의 소유권을 가지므로 데이터에는 명명된 볼륨을 선호합니다.
  • SELinux를 사용하는 시스템에서는 바인드 마운트에 :z 또는 :Z 레이블이 필요할 수 있습니다.

Linux 명령 가이드에서 설명하는 것처럼 chmod 777의 유혹을 피하세요.

어느 것을 사용해야 합니까?

상황 사용
데이터베이스 데이터 명명된 볼륨
실시간 편집 소스 코드 바인드 마운트
저장소의 구성 파일 읽기 전용 바인드 마운트
컨테이너 간 데이터 공유 명명된 볼륨
임시 캐시 또는 스크래치 파일 tmpfs
일회용 테스트 데이터베이스 tmpfs 또는 마운트 없음
프로덕션의 애플리케이션 코드 이미지에 빌드하세요.

마지막 행이 중요합니다. 프로덕션에서는 코드가 이미지에 속하므로 테스트한 내용이 실행됩니다. 클러스터에서 데이터 스토리지는 광범위한 Kubernetes 문서에서 다루는 영구 볼륨을 통해 다시 다르게 작동합니다. Docker와 Kubernetes 가이드에서는 두 가지가 어떻게 연관되어 있는지 설명합니다.

일반적인 실수

  • 잘못된 경로에 마운트됩니다. 데이터는 여전히 컨테이너 레이어에 존재하며 나중에 사라집니다.
  • down -v를 가볍게 실행합니다. 이렇게 하면 명명된 볼륨이 삭제됩니다.
  • -v와 함께 상대 경로를 사용합니다. -v data:/x과 같은 형식은 폴더 매핑이 아닌 볼륨을 생성합니다.
  • 쓰기 가능한 바인드 마운트에 비밀을 넣습니다. 읽기 전용으로 마운트하거나 비밀 기능을 사용하세요.
  • 한 볼륨에서 두 개의 데이터베이스 컨테이너를 가리킵니다. 이로 인해 데이터가 손상될 수 있습니다.
  • 백업이 없습니다. 볼륨은 백업이 아닙니다. 동일한 디스크에 상주합니다.

마무리

경험상 규칙은 간단합니다. 데이터에 대한 명명된 볼륨, 편집 중인 코드에 대한 바인드 마운트, 지속되어서는 안되는 항목에 대한 tmpfs입니다. 일회용 데이터베이스에서 사용해 보세요. 명명된 볼륨을 생성하고, 행을 추가하고, 컨테이너를 삭제하고, 새 볼륨을 시작하고, 행이 살아남았는지 확인하세요. 그런 다음 필요하기 전에 백업과 복원을 연습해 보세요.

자주 묻는 질문

Docker 볼륨과 바인드 마운트의 차이점은 무엇입니까?

볼륨은 Docker에 의해 관리되며 자체 영역에 저장됩니다. 바인드 마운트는 사용자가 제어하는 ​​특정 호스트 경로를 컨테이너에 직접 매핑합니다.

컨테이너를 중지하면 해당 데이터가 삭제되나요?

아니요. 쓰기 가능한 계층의 데이터는 중지했다가 다시 시작해도 유지됩니다. 볼륨 또는 바인드 마운트에 저장되지 않는 한 컨테이너가 제거되면 손실됩니다.

Docker가 작성된 후에도 Docker 볼륨이 유지됩니까?

예, Docker Compose가 종료된 후에도 명명된 볼륨은 그대로 유지됩니다. -v 플래그를 추가하면 포함된 모든 데이터와 함께 삭제됩니다.

Docker 볼륨은 어디에 저장되나요?

Linux에서는 일반적으로 /var/lib/docker/volumes 아래에 있습니다. Docker Desktop에서는 가상 머신 내부에 있습니다. Docker Volume Inspect를 사용하여 위치를 확인하세요.

여러 컨테이너가 볼륨을 공유할 수 있나요?

예, 여러 컨테이너가 하나의 볼륨을 마운트할 수 있습니다. 애플리케이션은 동시 액세스를 안전하게 처리해야 하며 데이터베이스는 일반적으로 이런 방식으로 데이터 파일을 공유해서는 안 됩니다.

계속 학습하세요

Stack Quora와 작업

테스트, WordPress 또는 SEO에 도움이 필요하십니까?

우리는 팀이 더 나은 소프트웨어를 출시하고 사이트를 성장시킬 수 있도록 돕습니다. 현재 진행 중인 작업을 알려주시면 명확한 다음 단계를 제안해 드리겠습니다.

계속 읽으세요

추가 가이드 테스트, AI 및 최신 개발

이 기사가 마음에 드셨나요? 주제를 선택하고 최신 튜토리얼로 바로 이동하세요.

인공지능

AI 환각 설명: 언어 모델이 사물을 구성하는 이유와 이를 줄이는 방법

AI 환각은 그것이 무엇인지, 언어 모델이 환각을 생성하는 이유, 일반적인 유형, 접지 및 프롬프트를 통해 환각을 줄이는 방법, 그리고 우리가 실행한 간단한 점검에 대해 설명했습니다.

기사 읽기 →
DevOps

환경 변수 설명: .env 파일, 비밀 및 구성이 올바르게 완료되었습니다.

우리가 실행한 Python 예제를 통해 설명된 환경 변수: 읽기 및 설정, 모든 값이 문자열인 이유, .env 파일, 프로세스 상속, 비밀 및 유효성 검사.

기사 읽기 →
소프트웨어 개발

API 속도 제한 설명: 알고리즘, 헤더 및 429 오류 처리

우리가 실행한 시뮬레이션을 통해 설명된 API 속도 제한: 토큰 버킷, 고정 창, 슬라이딩 창, 429 응답, 속도 제한 헤더, 백오프를 사용한 재시도 및 테스트 제한.

기사 읽기 →
테스트 자동화

Python에서 조롱: unittest.mock, 패치 및 테스트를 거짓말로 만드는 실수

Unittest.mock을 사용하여 Python에서 모의, 테스트됨: 모의 및 return_value, 부작용, 이름이 사용되는 패치, 사양 및 자동 사양, 모의 날짜 및 일반적인 실수.

기사 읽기 →
소프트웨어 테스트

코드 커버리지 설명: 회선 커버리지와 분기 커버리지 및 100%의 실제 의미

실제 Coverage.py 실행을 통해 설명되는 코드 적용 범위: 라인, 분기 및 조건 적용 범위, 보고서 읽기, 100% 적용 범위가 여전히 버그를 놓칠 수 있는 이유 및 합리적인 대상.

기사 읽기 →
데이터베이스 및 SQL

SQL의 DELETE vs TRUNCATE vs DROP: 차이점, 롤백 및 사용 시기

테스트된 SQL을 통해 DELETE 대 TRUNCATE 대 DROP에 대해 설명합니다. 각각의 제거, 롤백, 트리거, ID 재설정, 속도 및 PostgreSQL, MySQL, SQL Server 및 SQLite의 차이점.

기사 읽기 →
데이터베이스 및 SQL

SQL 뷰 설명: 예제를 통해 함정 생성, 사용 및 방지

우리가 실행한 쿼리로 설명된 SQL 뷰: 뷰 생성, 실시간 결과, 열 숨기기, 성능, 업데이트 가능하고 구체화된 뷰, 손상된 종속성 및 모범 사례.

기사 읽기 →
소프트웨어 개발

TypeScript 인터페이스와 유형: 실제 차이점, 컴파일러로 테스트

TypeScript 인터페이스 대 유형, 실제 컴파일러로 확인: 둘 다 할 수 있는 것, 하나만 할 수 있는 것, 선언 병합, 확장 대 교차점 및 따라야 할 간단한 규칙.

기사 읽기 →
소프트웨어 개발

Python *args 및 **kwargs 설명: 명확한 예가 포함된 유연한 함수

Python *args 및 **kwargs는 우리가 실행한 코드(패킹 및 언패킹, 매개변수 순서, 키워드 전용 및 위치 전용 인수, 데코레이터 및 일반적인 오류)를 설명했습니다.

기사 읽기 →
소프트웨어 개발

Python Lambda 함수: 구문, 실제 사용 및 사용하지 말아야 할 경우

Python 람다 함수는 구문, 키를 사용한 정렬, 맵 및 필터, 클로저, 후기 바인딩 트랩, 일반 def가 더 나은 선택인 경우 등 우리가 실행한 코드로 설명되었습니다.

기사 읽기 →
인공지능

AI 에이전트란 ​​무엇입니까? 작동 방식, 간단한 에이전트 루프를 사용하여 실행할 수 있음

AI 에이전트란 무엇입니까? 우리가 실행한 작은 Python 루프, 실제 위험 및 간단한 챗봇이 더 나은 선택일 때 에이전트 루프, 도구, 메모리 및 가드레일에 대한 일반 가이드입니다.

기사 읽기 →
DevOps

모니터링과 관찰 가능성: 로그, 지표, 추적을 통한 실제 차이점

모니터링과 관찰 가능성 설명: 알려진 오류와 알려지지 않은 오류, 로그, 지표 및 추적, 결제 사건 안내, 골든 신호, OpenTelemetry 및 유용한 경고.

기사 읽기 →
DevOps

Docker 볼륨과 바인딩 마운트: 컨테이너 데이터를 올바른 방식으로 유지

Docker 볼륨과 바인드 마운트 설명: 컨테이너 데이터가 사라지는 이유, 명명된 볼륨, 바인드 마운트, tmpfs, Compose 예제, 백업, 권한 및 각 사용 시기.

기사 읽기 →
테스트 자동화

TDD와 BDD: 주요 차이점, 두 가지 방식으로 구축된 하나의 기능 및 각 사용 시기

TDD와 BDD는 두 가지 방식으로 구축된 하나의 할인 기능, 즉 우리가 실행한 코드를 사용한 적록 리팩토링, 주어진 시점 시나리오, 도구, 장단점 및 각 사용 시기를 설명합니다.

기사 읽기 →
소프트웨어 개발

Git merge vs rebase: 차이점, 예제, 언제 무엇을 쓸까

Git merge vs rebase를 실제 로그 출력, 비교표, rebase의 황금률, 안전한 팀 워크플로로 설명합니다.

기사 읽기 →
소프트웨어 개발

파이썬 리스트 컴프리헨션: 문법, 예제, 피해야 할 때

파이썬 리스트 컴프리헨션 설명: 문법, 필터링, if-else, 중첩 반복문, 실제 측정 시간, 그리고 일반 for 반복문이 더 나은 경우.

기사 읽기 →
데이터베이스 및 SQL

예제로 쉽게 배우는 SQL JOIN (Inner, Left, Right, Full)

샘플 테이블과 쿼리로 SQL JOIN을 단계별로 이해하세요. INNER, LEFT, RIGHT, FULL, CROSS, SELF와 흔한 실수, 성능 팁까지 정리했습니다.

기사 읽기 →