볼륨으로 컨테이너 데이터를 저장하는 법

볼륨으로 컨테이너 데이터를 저장하는 법

컨테이너에 저장한 파일은 컨테이너가 삭제되면 함께 사라져요. 쓰기 레이어도 컨테이너 수명과 함께 사라지거든요. 그래서 DB 데이터나 업로드 파일처럼 반드시 남아 있어야 하는 것들은 컨테이너 밖의 저장소에 보관해야 해요. 이때 쓰는 게 **볼륨(volume)**입니다.

볼륨은 도커 호스트의 한 디렉토리에 저장되는데, 그 디렉토리가 컨테이너 안에 마운트돼요. 바인드 마운트와 비슷하지만, 볼륨은 도커가 직접 관리하고 호스트 머신의 핵심 기능과 분리돼 있다는 점이 달라요. 호스트 디렉토리 구조나 OS에 의존적인 바인드 마운트와 달리, 볼륨은 도커가 완전히 관리하므로 컨테이너가 쓰고 만드는 데이터를 유지하는 기본 수단으로 권장돼요.

출처: Volumes — Docker Docs

볼륨의 수명주기

볼륨의 내용물은 특정 컨테이너의 수명주기 밖에 존재해요. 컨테이너가 파괴되면 쓰기 레이어도 함께 파괴되지만, 볼륨을 사용하면 그 컨테이너를 지워도 데이터는 남아요. 다른 컨테이너가 그 볼륨을 다시 마운트해 이어서 쓸 수 있죠.

마운트 문법

docker run에서 볼륨을 마운트할 때는 --mount 또는 --volume 플래그를 써요.

$ docker run --mount type=volume,src=<volume-name>,dst=<mount-path>
$ docker run --volume <volume-name>:<mount-path>

--mount의 옵션을 보면 마운트 동작을 세밀하게 제어할 수 있어요.

| 옵션 | 설명 | | source, src | 마운트의 출처. 이름 있는 볼륨이라면 볼륨 이름, 익명 볼륨이라면 생략해요. | | readonly, ro | 포함하면 볼륨을 읽기 전용으로 마운트해요. | | volume-nocopy | 포함하면 대상의 데이터가 비어 있을 때 볼륨으로 복사되지 않아요. 기본적으로 대상 경로의 내용은 마운트된 볼륨(비어 있을 때)로 복사돼요. |

이름 있는 볼륨의 경우 --volume에서 첫 번째 필드는 볼륨 이름이고 호스트 머신에서 고유해요. 익명 볼륨은 첫 필드를 생략해요. 두 번째 필드는 컨테이너 안에서 파일·디렉토리가 마운트되는 경로예요.

볼륨 만들고 관리하기

만든 볼륨의 상세 정보는 docker volume inspect로 확인할 수 있어요.

$ docker volume inspect my-vol
[
    {
        "Driver": "local",
        "Labels": {},
        "Mountpoint": "/var/lib/docker/volumes/my-vol/_data",
        "Name": "my-vol",
        "Options": {},
        "Scope": "local"
    }
]

볼륨을 지우려면 docker volume rm my-vol을 실행해요.

컨테이너에 볼륨 붙이기

docker inspect로 컨테이너의 마운트 목록을 보면 볼륨이 어떤 경로에, 어떤 방식으로 연결돼 있는지 알 수 있어요.

"Mounts": [
    {
        "Type": "volume",
        "Name": "myvol2",
        "Source": "/var/lib/docker/volumes/myvol2/_data",
        "Destination": "/app",
        "Driver": "local",
        "Mode": "",
        "RW": true,
        "Propagation": ""
    }
]

Docker Compose에서 볼륨 쓰기

Compose에서는 서비스의 volumes 항목에 볼륨을 선언하고, 파일 아래쪽 volumes:에서 이름 있는 볼륨을 정의해요.

services:
  frontend:
    image: node:lts
    volumes:
      - myapp:/home/node/app
volumes:
  myapp:

docker compose up을 처음 실행하면 볼륨이 만들어지고, 이후 다시 실행해도 같은 볼륨을 재사용해요. Compose 바깥에서 docker volume create로 미리 만들어 둔 볼륨을 compose.yaml에서 쓰려면 external: true로 선언해요.

services:
  frontend:
    image: node:lts
    volumes:
      - myapp:/home/node/app
volumes:
  myapp:
    external: true

컨테이너로 볼륨 채우기

컨테이너가 새 볼륨을 만들면서 해당 디렉토리(예: /app/)에 파일·디렉토리가 있으면, 도커가 그 내용을 볼륨으로 복사해요. 이후 그 볼륨을 쓰는 다른 컨테이너도 같은 내용을 보게 되죠. 아래 예시는 nginx 컨테이너를 시작하며 새 볼륨 nginx-vol을 컨테이너의 /usr/share/nginx/html(Nginx가 기본 HTML을 두는 곳) 내용으로 채워요. --mount-v는 결과가 같아요.

--mount

$ docker run -d \
  --name=nginxtest \
  --mount source=nginx-vol,destination=/usr/share/nginx/html \
  nginx:latest

-v

$ docker run -d \
  --name=nginxtest \
  -v nginx-vol:/usr/share/nginx/html \
  nginx:latest

볼륨의 하위 디렉토리 마운트

볼륨의 특정 하위 디렉토리만 컨테이너에 연결하고 싶다면 --mount 플래그의 volume-subpath 파라미터를 써요. 마운트 전에 그 하위 디렉토리가 볼륨 안에 이미 존재해야 하며, 없으면 마운트가 실패해요.

더 알아보기