Docker 공부노트 - volume

코변·2022년 10월 20일
0

도커 공부노트

목록 보기
3/5
post-thumbnail

Photo by Rubaitul Azad on Unsplash

도커의 임시 데이터는 컨테이너에 의해서 관리되지만 영구데이터는 볼륨에 의해서 관리된다.

도커 컨테이너를 지우고 다시 image를 컨테이너에 띄우면 컨테이너에 저장되었던 데이터는 사라지고 없다.

같은 이미지를 사용한다고 해도 컨테이너를 새로 생성한다면 이전 컨테이너에 저장된 모든 데이터는 손실된다.

컨테이너는 데이터를 image에 저장하지 않기 때문이다.

해결방법은 볼륨이다!

볼륨은 컨테이너나 이미지에 존재하는 것이 아니고 내 컴퓨터의 폴더이다!

이 폴더가 도커 컨테이너 내부의 폴더에 매핑된다.

이 두 폴더의 변경사항은 서로에게 반영된다.

내 컴퓨터의 특정 폴더를 변경하면 컨테이너 내부에서 엑세스할 수 있고 물론 반대로도 가능하다.(물론 내 컴퓨터에 어디있는지도 모르고 도커가 알아서 관리하므로 내 컴퓨터에서 볼륨 폴더를 수정할 일은 대체로 없다.)

이러한 방법으로 볼륨은 컨테이너가 종료된 이후에도 지속되며 데이터를 지킬 수 있다.

컨테이너는 볼륨에 데이터를 읽고 쓸 수 있다.

폴더구조가

app

feedback

pages

public

temp

Dockerfile

package.json

server.js

로 이루어져있다고 했을 때 서버에서 피드백을 받아 저장하는 장소는 feedback 폴더다. 이 폴더를 volume으로 지정하고 싶다면 아래와 같은 코드를 도커파일에 추가해준다.

영구데이터가 존재해야하는 곳이 바로 feedback폴더이므로 볼륨으로 지정해주면 컨테이너가 종료되고 또 삭제되더라도 데이터는 내 컴퓨터에 남아있게 된다.

FROM node:14

WORKDIR /app

COPY package.json .

RUN npm install

COPY . .

EXPOSE 80

VOLUME [ "/app/feedback" ]

CMD [ "node", "server.js" ]

볼륨에는 anonymous volumes와 named volumes가 있다.

이 두가지는 마찬가지로 호스트 컴퓨터(내 컴퓨터)에 일부 폴더와 결로를 설정한다.

docker volume ls
## 이 명령어를 통해 볼륨을 리스팅할 수 있다.

→ 위의 명령어대로 볼륨을 설정한 다음 컨테이너를 종료하고 다시 볼륨리스트를 출력해보면 볼륨이 사라진 것을 볼 수 있다.

이는 볼륨이 익명이기 때문에 컨테이너가 있는동안만 존재한다.

→ 컨테이너가 지워지면 데이터가 사라진다는 점에서 별 차이가 없기 때문이다.

named volumes를 사용하면 컨테이너가 지워진 다음에도 데이터는 영구적으로 남는다.

named volumes를 사용하기 위해서는 dockerfile에서 volume 명령어를 제거하고 컨테이너를 생성할 때 태그와 함께 추가해주어야 한다.

docker run -d -p 3000:80 --rm --name feedback-app \
-v 볼륨이름:/app/feedback -> 원하는 폴더이름 컨테이너 이름:태그
## 위와 같이 -v 와 함께 볼륨이름:/폴더이름으로 묶어 컨테이너를 띄우면
## 볼륨은 내가 명명한 이름을 가지게 되고 컨테이너가 삭제되어도
## 데이터를 가진 채로 유지된다.
docker run -d -p 3000:80 --rm --name feedback-app \
-v 볼륨이름:/app/feedback -> 원하는 폴더이름 -v 내컴퓨터 폴더의 절대경로:/app 컨테이너 이름:태그
## 바인드 마운트는 host(내컴퓨터)에서 수정가능하게 폴더를 묶어준다.
## -v 내컴퓨터 폴더의 절대경로:/app 이와 같은 방식으로 '바인드' 해줄 수 있다.
## 파일 폴더 전체 모두 바인드 가능하다.
## 경로 부분에 띄어쓰기나 특수문자로 인해 오류가 발생할 수도 있다 큰 따옴표로
## "내컴퓨터 폴더의 절대경로:/app"와 같이 묶어주면 오류를 방지할 수 있다.
## 환경설정 리소수에 file sharing에 공유 가능 리소스로 추가되어 있어야 바인드를 사용할 수 있다.
## -v ${pwd}:/app처럼 축약어로 나타낼 수도 있다.

위 코드와 같이 사용하게 되면 app 폴더 전체를 덮어쓰게 되며 디펜던시의 설치가 제대로 이루어지지 않는다.

여기에서 익명 볼륨의 도움을 받을 수 있는데

docker run -d -p 3000:80 --rm --name feedback-app \
-v 볼륨이름:/app/feedback -> 원하는 폴더이름 -v 내컴퓨터 폴더의 절대경로:/app \
-v /app/node_modules 컨테이너 이름:태그
## -v /app/node_modules 코드를 추가하여 익명 볼륨을 생성한다.
## 이렇게 더 뎁스가 깊은 폴더와 덜 깊은 폴더가 있다면 도커는 뎁스가 더 깊은 폴더를 우선시한다.
## 따라서 npm install로 인해서 생겨난 node_modules라는 폴더는 바인드로 인해
## 덮어씌워지는 부분에서 제외될 수 있다.

읽기 전용 볼륨

바인드 마운트를 디폴트값으로 설정하면 도커 내부파일 또한 호스트(내컴퓨터)의 파일을 변경할 수 있는데 이를 방지하기 위해서는 ro 옵션을 넣어주어야 한다.

docker run -d -p 3000:80 --rm --name feedback-app \
-v 볼륨이름:/app/feedback -> 원하는 폴더이름 -v "내컴퓨터 폴더의 절대경로:/app:ro" \
-v /app/node_modules 컨테이너 이름:태그
## 위와 같이 :ro를 기존 바인드 문구에 추가해주면 읽기전용으로 변경되며
## 도커가 바인드 된 폴더나 그 하위폴더에 있는 파일을 변경하거나 생성할 수 없게된다.
docker volume ls
## ls로 볼륨을 리스팅할 수 있다.

docker volume create
## create명령어로 생성이 가능

docker volume inspect volume_name
## 볼륨의 정보를 볼 수 있다.

docker volume rm
## rm으로 삭제도 가능하고

docker volume prune
## prune으로 가지치기도 가능하다.

바인드 마운트 vs Dockerfile COPY

바인드 마운트로 모든 파일들을 동기화 시킬 수 있는데 굳이 이미지 빌드시에 copy할 필요가 있는가?

  • 실제로 image 빌드 시에 copy를 제거해도 바인드마운트를 실행하면 모든 코드가 잘 구동됨을 알 수 있다.
  • 그러나 프로덕션 환경에서는 동기화 되는 폴더는 필요하지 않다.
  • 왜냐하면 프로덕션 환경에서는 안정적인 상태가 필요하기 때문이다.
  • 그렇기 때문에 copy를 활용해 더 static한 환경 구성이 필요하다.

copy . . 은 모든 파일을 복사한다.

.dockerignore파일을 통해서 복사하지 않을 파일을 고를 수 있다.

ARG vs ENV

둘 다 계속 변경할 지도 모르는 부분을 하드코딩으로 일일이 바꿔 줄 필요가 없도록 도와준다는 장점이 있다.

서로 다른 환경, 구성에서 동일한 이미지, 컨테이너를 실행할 수 있도록 도움을 준다.

ARG

  • 이미지 빌드에 쓰인다
  • Dockerfile 에 ARG 이름 = 밸류로 선언할 수 있다.
  • ARG는 cmd 에서는 활용할 수 없다. cm는 컨테이너가 시작될 때 실행되는 런타임 명령어이기 때문이다.
  • docker build 명령어 입력시에 —build-arg 태그를 추가하고 이름=밸류를 추가하면 빌드 시에 ARG를 바꿔줄 수 있다.

ENV

  • 구동중인 어플리케이션에 쓰인다.
  • docker run —env 태그나 -e 태그로 추가할 수 있다.
  • .env 파일으로 환경변수를 관리할 수도 있다. 이때는 —env-file ./.env를 선언해야한다.
profile
내 것인 줄 알았으나 받은 모든 것이 선물이었다.

0개의 댓글