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로 붙인다.
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로 올린 스택이 멈춰 있으면 “미사용”으로 잡혀 날아갈 수 있다.