Volume

이승준·2024년 10월 30일

Docker

목록 보기
5/6

Volume

  • host machine 의 dir 로, 컨테이너나 이미지에 존재하지 않는다
  • host 에 장착된 드라이브에 존재하거나, 컨테이너로 매핑된다
  • host 상에서 매핑된 주소는 docker 가 관리하고, 우리는 알 수 없다
  • 컨테이너가 삭제되어도 유지되어야 할 데이터가 있을 때 사용

COPY 와의 차이?

  • COPY 는 복사 당시의 snapshot 을 일회성으로 복사하는 것
  • volume 은 컨테이너 내부의 폴더를 host 상의 폴더에 연결

Cross Device Error

  • volume 을 다루면서 흔하게 볼 수 있는 오류다
  • 장치 간 링크가 허용되지 않는다는 의미를 가진다
  • docker 는 파일을 컨테이너 내의 다른 폴더로 이동시키지 않는다

조회, 제거

  • docker volume ls: volume 목록 조회
  • docker volume rm <VOLUME_NAME>: 특정 volume 제거
  • docker volume prune: 미사용 volume 제거

Anonymous Volume

  • DockerfileVOLUME 명령어에 경로를 특정할 수 있다.
FROM node:16

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 80

VOLUME [ "/app/feedback" ]

CMD [ "node", "server.js" ]
  • /app/feedback 이 컨테이너 내부 경로가 되었다
  • 이 경로는 컨테이너 외부에서 매핑될 내부 위치다
  • Dockerfile 을 토대로 이미지를 빌드해보자
    docker build -t feedback-node:volumes .
  • 이미지를 토대로 컨테이너를 실행하자
    docker run -d -p 3000:80 --rm --name feedback-app feedback-node:volumes
  • 이렇게 이름이 지정되지 않은 것을 anonymous volume 이라고 한다
  • 하지만, 이름을 모르기 때문에 우리가 접근할 수 없다
  • 또한, 익명이기에 컨테이너가 삭제되면 삭제된다
    • --rm 옵션을 사용해 run 을 했을 때 해당하는 말이다
    • --rm 없이 runrm 을 사용하면 volume 은 남아있다
    • docker prune 이 필요한 이유가 이것이다

Named Volume

  • 볼륨에 접근하기 위해 이름을 붙인 named volume 을 사용한다
  • 또한, 컨테이너 종료 후에도 볼륨을 유지할 수 있다
  • named volume 은 영구적이어야 하는 데이터나, 직접 볼 필요가 없는 데이터에 적합하다
  • named volume 은 Dockerfile 에선 생성할 수 없고, 컨테이서 실행 시 생성한다
    * 앞에서 추가한 VOLUME 을 제거하자
    docker run --name <CONTAINER_NAME> -v <VOLUME_NAME>:<VOLUME_PATH> <IMAGE_NAME>
  • named volume 은 여러 컨테이너에 연결 가능하다

Bind Mounts

  • 개발자가 직접 컨테이너 경로를 주고 관리하는 저장소
  • 이미지의 성질에 의해 build 이후의 수정사항은 반영되지 않는다
  • bind mount 는 이로 인한 제약을 해결한다
  • 컨테이너는 파일을 스냅샷이 아닌 binding mount 에서 복사한다
  • 이로 인해 영구적이고, 편집 가능한 데이터를 관리할 때 적합

binding mount 적용

  • 컨테이너에 적용되기 때문에 run 에서 명시
    docker run --name feedback-app -v feedback:/app/feedback -v "<FILE_PATH>:/app" feedback-node:volumes
  • 이 때 bind 되는 host 상의 경로는 절대경로여야 한다
  • named volume 선언과 유사하나, : 앞이 경로다

Volume 병합

  • 위에서 우리는 컨테이너의 /app 을 지정한 host 상의 dir 로 덮어썼다
  • 이로 인해, 이미지 build 시 실행한 npm install 로 인해 생긴 node_modules dir 이 삭제된다
  • 이를 해결하기 위해 덮어쓰지 않을 부분을 명시한다
    docker run --name feedback-app -v feedback:/app/feedback -v "<FILE_PATH>:/app" -v /app/node_modules feedback-node:volumes
  • 이로 인해 app/node_modules 는 anonymous volume 이 되었다
  • docker 는 충돌의 경우 더 구제척인 내부 경로를 우선시해, app/node_modules 로 매핑된 경로를 우선시해 유지시킨다

Read Only Volume

  • 우리가 파일을 변경할 수 있는 곳은 오로지 host 상이다
  • 컨테이너가 host 상의 파일을 변경하는 것을 방지해야 할 때가 있다.
  • 이를 위해 bind mount 를 read only 로 설정한다
    docker run --name feedback-app -v feedback:/app/feedback -v "<FILE_PATH>:/app:ro" -v /app/node_modules feedback-node:volumes

Volume 관리

생성

  • 컨테이너 실행 시 -v 이용
  • 수동으로 생성도 가능
    docker volume create <VOLUME_NAME>

확인

  • 모든 볼륨 확인
    docker volume ls
  • 볼륨의 자세한 정보 확인
    docker volume inspect <VOLUME_NAME>

사용

  • run 명령에 미리 만든 볼륨 이름 명시
    docker run --name <CONTAINER_NAME> -v <VOLUME_NAME>:<VOLUME_PATH> <IMAGE_NAME>

삭제

  • 개별 삭제
    `docker volume rm <VOLUME_NAME>
  • 사용하지 않는 볼륨 모두 삭제
    docker volume prune

ENV 사용

  1. Dockerfile 에 명시하는 방법
# Dockerfile
ENV PORT=80
EXPOSE $PORT
  • 이후 --e 로 컨테이너 실행 시 명시해준다
  • 아래와 같이 여러 개의 변수 설정도 가능
    docker run -d -p 3000:8000 --e PORT=8000 --e ENV2=7000 --e ENV3=6000 --rm --name <CONTAINER_NAME> <IMAGE_NAME>
  1. .env 파일 이용
#.env
PORT=8000
  • 이후 --env-file 로 컨테이너 실행에서 사용
    `docker run -d -p 3000:8000
    --env-file ./.env
    --rm
    --name <CONTAINER_NAME> <IMAGE_NAME>

ARG 사용

# Dockerfile
FROM node:14

ARG DEFAULT_PORT=80

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

ENV PORT $DEFAULT_PORT

EXPOSE $PORT

CMD [ "node", "server.js" ]
  • 같은 Dockerfile 을 이용한 두 이미지가 다른 port 를 가지게 할 수 있다
  • docker build -t feedback-node:web-app .
  • docker build -t feedback-node:dev --build-arg DEFAULT_PORT=8000 .
profile
인하대학교 컴퓨터공학과

0개의 댓글