← 글 목록

notes

Docker - volum ( 개념 , 사용)

Docker volume의 데이터 영속성·생성·마운트와 사용 시 주의점 정리.

컨테이너를 지우면 컨테이너 안의 파일도 같이 사라진다. DB 데이터·업로드 파일은 남기고 싶은데… 그때 쓰는 게 볼륨(volume)이다.

  • 운영 데이터(DB, 업로드)는 named volume에 둔다. 컨테이너를 지워도 남는다.
  • 로컬 개발은 소스는 bind mount, node_modules는 named volume으로 나눈다.
  • docker compose down -v와 prune --volumes는 볼륨까지 지우니 돌리기 전에 볼륨 이름부터 확인한다.

왜 필요한가

컨테이너 = 잠깐 쓰는 실행 환경. 이미지 다시 받고 docker compose up 다시 하면 파일시스템은 초기화에 가깝다. MySQL 데이터 디렉터리(/var/lib/mysql)를 컨테이너 안에만 두면 재배포할 때마다 DB가 날아간다.

볼륨을 붙이면 “컨테이너는 버려도 데이터는 Docker가 관리하는 디스크에 남는다”.

헷갈렸던 게 docker compose down과 down -v의 차이다. 그냥 down은 컨테이너와 네트워크만 지우고, -v를 붙이면 compose 파일에 선언된 named volume까지 지운다. 로컬에서 DB를 초기화하고 싶을 때만 -v를 쓴다.

세 가지 붙이는 방식

Named volume 빠른 예

docker volume create my-data

docker run -d \
  --name nginx-test \
  -v my-data:/usr/share/nginx/html \
  -p 8080:80 \
  nginx

Compose에서 DB

services:
  db:
    image: mysql:8.0
    volumes:
      - mysql_data:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: example
      MYSQL_DATABASE: testdb

volumes:
  mysql_data:

volumes: 아래 이름만 적어 두면 compose가 named volume을 만들어 준다.

Bind mount (개발)

services:
  web:
    image: nginx
    volumes:
      - ./html:/usr/share/nginx/html:ro
    ports:
      - "8080:80"

호스트에서 ./html 고치면 컨테이너에 바로 보인다. 대신 호스트 OS·경로에 묶인다. 프로덕션 DB를 bind로 두는 건 피한다.

컨테이너끼리 공유

같은 named volume을 두 서비스에 붙이면 파일을 같이 본다. 둘 다 쓰기를 하면 충돌이 나니, 보통 한쪽만 쓰고 나머지는 :ro로 붙인다.

nginx 두 대가 같은 폴더를 보는 compose
services:
  web1:
    image: nginx
    volumes:
      - shared_content:/usr/share/nginx/html
    ports:
      - "8081:80"
  web2:
    image: nginx
    volumes:
      - shared_content:/usr/share/nginx/html:ro
    ports:
      - "8082:80"

volumes:
  shared_content:

tmpfs

services:
  app:
    image: node:20
    tmpfs:
      - /app/temp

개발에서 node_modules만 volume

소스는 bind, node_modules는 named volume으로 두면 호스트·컨테이너 OS 차이로 깨지는 걸 줄일 수 있다.

services:
  dev:
    image: node:20
    volumes:
      - ./src:/app/src
      - node_modules:/app/node_modules
    working_dir: /app
    command: npm run dev

volumes:
  node_modules:

백업할 때

볼륨을 읽기 전용으로 다른 컨테이너에 붙여 pg_dump 같은 걸 돌린다. 단, pg_dump는 파일을 읽는 게 아니라 DB에 접속해서 덤프를 뜨는 거라 아래 예제처럼 -h db와 비밀번호를 같이 줘야 실제로 돈다. 볼륨 폴더 자체를 통째로 백업하고 싶으면 tar를 쓰는 게 더 단순하다.

# 볼륨 통째 백업 (DB는 멈춘 상태에서)
docker run --rm -v pg_data:/source:ro -v $(pwd):/backup alpine \
  tar czf /backup/pg_data.tar.gz -C /source .

# 복원
docker run --rm -v pg_data:/target -v $(pwd):/backup alpine \
  tar xzf /backup/pg_data.tar.gz -C /target
services:
  db:
    image: postgres:13
    volumes:
      - pg_data:/var/lib/postgresql/data
    environment:
      POSTGRES_PASSWORD: example
  backup:
    image: postgres:13
    volumes:
      - pg_data:/source:ro
      - ./backups:/backups
    environment:
      PGPASSWORD: example
    command: pg_dump -h db -U postgres -f /backups/backup.sql
    depends_on:
      - db

volumes:
  pg_data:

관리 명령

docker volume create my_volume
docker volume ls
docker volume inspect my_volume
docker volume rm my_volume
docker volume prune   # 안 쓰는 볼륨만

docker system prune -a --volumes는 사용 중이지 않은 볼륨까지 지운다. auto clean / cron 글이랑 겹치는데, DB 볼륨 이름 확인하고 돌리는 습관을 들이자. compose로 올린 스택이 멈춰 있으면 “미사용”으로 잡혀 날아갈 수 있다.