JUINTINATION
도커(Docker) 가볍게 입문해보기 - 4 본문
지난 도커(Docker) 가볍게 입문해보기 - 3에서 이어지는 내용이며 해당 글은 이 링크로 들어가면 확인할 수 있다. 지난 글에서 언급했듯이 이 스터디는 학교 선배가 작성한 강의 자료를 참고하였으며 ETRI에서 대여한 관련 책과 추가로 대여한 다른 책을 참고했다.
Docker Container의 휘발성
volume-test라는 디렉터리를 만들고 다음과 같이 Dockerfile을 작성했다.
FROM ubuntu:14.04
RUN mkdir example
WORKDIR /example
RUN echo "print('hello world')" >> ex.py
ENTRYPOINT [ "/bin/bash" ]
위의 Dockerfile에 의해 리눅스 환경의 example 디렉터리에 print('hello world')
가 작성되어있는 ex.py
파일을 생성한다.$ docker build -t volume-test .
커맨드를 실행하여 이미지를 빌드하고 $ docker run -it --name volumetestcontainer volume-test
커맨드를 실행하여 컨테이너를 하나 만든 후에 다음과 같이 a.txt
를 생성해보자.
생성한 a.txt 뿐만 아니라 도커 이미지에서 생성한 ex.py도 존재하는것을 볼 수 있다. 하지만 이 컨테이너를 지우고 동일한 이미지로 컨테이너를 생성하면 당연하게도 아까 만든 a.txt라는 파일은 사라지고 Dockerfile에 의한 ex.py만 남아있을 것이다.
기본적으로 이미지를 통해 컨테이너를 만들면 컨테이너는 읽기전용이 된다. 그리고 컨테이너 변경 사항만 별도로 저장하여 컨테이너 정보를 보존한다. 이미지는 어떠한 경우로도 변경되지 않는다. 원래 이미지에서 변경된 파일 시스템들은 모두 Container Layer에 저장되게 된다. 단, 이 Container Layer는 컨테이너가 삭제되면 같이 삭제가 된다. 그렇기에 기본적으로 Docker Container는 휘발성을 가진다.
Docker volume
Docker Volume을 사용하면, 데이터를 영구적으로 저장할 수 있다. 다음은 Docker에서 볼륨을 관리하는 방법 중 대표적인 3가지이다.
1. Host Machine과 Container의 공유
volume-test 디렉터리로 이동하여 $ mkdir sqltest
커맨드를 실행하여 sqltest 디렉터리를 만들고 $ cd sqltest
명령어로 해당 디렉터리로 이동한다. 이후에 다음 커맨드를 실행하여 mysql 컨테이너를 생성해보자.
$ docker run -d -e MYSQL_ROOT_PASSWORD=pw1234 -e MYSQL_DATABASE=demoDB -v $(pwd):/var/lib/mysql mysql
일반적인 $ docker run
과 달리진 점이라면 -v
옵션이 생긴것이다. -v
옵션의 인자는 기본적으로 아래와 같은 형태로 입력한다.
(호스트 머신 디렉토리):(컨테이너 디렉토리)
$ ls
커맨드를 실행하여 현재 디렉터리를 확인해보면 mysql config와 관련된 파일들이 생긴 것을 볼 수 있다.
확인해보니 mysql 컨테이너의 이름이 자동으로 festive_blackburn으로 설정되었다. 이제 $ docker exec -it festive_blackburn bash
mysql 컨테이너에 접속해서 $ cd /var/lib/mysql
커맨드와 $ touch example.txt
커맨드를 차례로 실행하여 exampletext.txt파일을 만들고 호스트 머신에서도 해당 파일이 생겼는지 확인해보자.
실제로 $ exit
커맨드를 실행하여 mysql 컨테이너를 나간 후에 $ ls
커맨드를 실행하여 확인해보니 호스트 머신에서도 example.txt 파일이 생긴 것을 확인할 수 있다. 이를 통해 컨테이너의 /var/lib/mysql
와 현재 디렉토리는 동일한 디렉토리를 사용한다는 것을 알 수 있을 것이다. 컨테이너를 삭제한 후 현재 디렉토리를 다시 확인해 보면 컨테이너는 없어졌지만 mysql 관련 config 파일들은 남아있는것을 볼 수 있을 것이다.
이제 위에서 생성한 Dockerfile에 다음과 같이 VOLUME [ "/example" ]
을 한 줄 추가하여 /example
디렉토리를 호스트와 공유할 수 있도록 지정해준 후에 다시 빌드해보자.
FROM ubuntu:14.04
RUN mkdir example
WORKDIR /example
RUN echo "print('hello world')" >> ex.py
VOLUME [ "/example" ]
ENTRYPOINT [ "/bin/bash" ]
/example
디렉토리에 ex.py
가 기본적으로 존재한다는 점을 상기하고 $ docker run -it -v $(pwd):/example volume-test
커맨드를 실행하여 컨테이너를 -v
옵션에 현재 디렉토리와 /example
디렉터리를 연결해주면서 생성한 후에 해당 디렉토리의 파일 리스트를 출력해보자.
위의 사진을 보면 $ ls | grep ex.py
커맨드를 실행해서 확인했음에도 불구하고 있어야 할 ex.py
가 존재하지 않는 것을 확인할 수 있다.
이를 통해 알 수 있는것은 기존에 존재하던 컨테이너 디렉토리에 호스트 볼륨을 공유하게 되면 컨테이너 디렉토리는 덮어씌우기가 된다는 점이다. 기존에 mysql 컨테이너로 실습을 할때는 /var/lib/mysql에 원래 파일이 존재했던것이 아닌, mysql이 초기 설정되면서 파일이 작성되었기 때문에 파일이 호스트 디렉토리에 공유된 것이다.
2. Volume Container
-v
옵션을 사용하여 컨테이너와 호스트 머신 디렉터리를 공유할 수 있는것을 알았다. 볼륨을 공유하는 두번째 방법은 -v
옵션을 통해 생성한 컨테이너를 --volumes-from
옵션을 통해 또 다른 컨테이너가 디렉토리를 공유하는것이다.
우선 volume-test
디렉터리로 이동하여 $ rm -rf sqltest/
커맨드를 실행하여 sqltest
디렉토리의 파일을 모두 지우고 위에서 작성한 도커파일을 통해 $ docker run -it --name first_level_container -v $(pwd):/example volume-test
커맨들와 $ docker run -it --name second_level_container --volumes-from first_level_container volume-test
커맨드를 차례로 실행하여 컨테이너 2개를 만들어 보자. second_level_container
를 생성할 때 --volumes-from
옵션을 설정하여 -v
옵션이 지정된 컨테이너 볼륨 디렉토리를 공유하는 것이다.
그리고 다음과 같이 first_level_container
에서 $ echo "Hello World" >> a.txt
커맨드를 실행하여 a.txt
를 생성하고 first_level_container
에서도 파일이 동일하게 생기는 것을 확인할 수 있다. 당연한 것이지만, 호스트 머신에서도 동일하게 파일이 생성되었다
만약 --volumes-from
을 통해서 공유받은 컨테이너가 서로 다른 Dockerfile을 가진다면 어떻게 될까? 그 질문의 답은 '영향을 미치지 않는다' 이다. 위에서 만든 도커파일이 아닌 일반 ubuntu Dockerfilef로 $ docker run -it --volumes-from first_level_container ubuntu bash
커맨드를 실행하여 컨테이너를 생성하여 a.txt가 존재하는지 확인해보자.
Dockerfile과 상관없이 동일하게 first_level_container
의 디렉터리를 공유받는 것을 볼 수 있으며 파일을 생성해도 동일하게 공유된다. --volumes-from
옵션을 통해 볼륨을 공유하면 아래와 같은 구조를 가진다.
3. Docker Volume
위에서 본 두가지 방법들은 결론적으로 호스트와의 공유를 통해서 볼륨을 공유하였다. 세번째 방법은 도커 자체에서 제공하는 볼륨을 사용하는것이다.
docker volume은 디렉토리 하나의 단위이며 이는 Docker Engine이 파일시스템의 도커 영역에서 관리하는 방식이다. 위 두 방식과 마찬가지로 호스트 머신에 저장되는 방식이며 도커 볼륨을 생성하기 위해서는 $ docker volume create
명령어를 통해 생성한다. 그 후 $ docker volume ls
를 통해 볼륨 리스트들을 확인해보자.
도커 볼륨을 사용한 컨테이너를 만들때는 위에서 보았던 방식과 동일하게 -v 옵션을 사용하며 인자는 아래와 같이 주면 된다
(볼륨 이름):(컨테이너 공유 디렉토리)
위에서 생성한 도커이미지와 방금 만든 $ docker run -it -v testvolume:/example volume-test
커맨드를 실행하여 testvolmue
을 이용하여 컨테이너를 생성해본 후에 $ mkdir test
커맨드를 실행하여 test
라는 디렉터리를 만들어보자.
만약 Docker Desktop이 있다면 다음과 같이 volumes 탭에서 방금 만든 볼륨을 확인할 수 있다.
이후에 방금 만든 볼륨을 클릭한 후 다음과 같이 In Use탭에서 해당 볼륨을 사용중인 컨테이너를 Data탭에서 해당 볼륨 내에 있는 test디렉토리를 볼 수 있다.
당연하게도 해당 볼륨을 사용하는 컨테이너를 만들면 컨테이너 마운트로 지정한 경로에 test라는 디렉토리가 똑같이 존재하게 된다.
도커 볼륨은 아래와 같은 구조로 사용을 하게 되는것이다.
도커 볼륨의 기본적인 단위들을 확인할 때는 다음과 같이 $ docker inspect
명령어를 사용해 줄 수 있다. 단 --type을 volume으로 지정해줘야 하며 나는 방금 만든 testvolume
에 대해 확인하기 위해 $ docker inspect --type volume testvolume
커맨드를 실행했다.
볼륨을 삭제하기 위해서는 $ docker volume rm
명령어을 사용하면 된다.
나는 처음에 Error response from daemon: remove testvolume: volume is in use - [3bc690f9196e153d0a621b2427b3539e6191584158857b906b029b68b2c70d87] 오류가 발생했는데 위와 같은 방법으로 해당 볼륨을 사용중인 컨테이너를 삭제한 후 해당 볼륨을 다시 삭제하는 방식으로 해결했다.
상황에 맞게 사용해야 하는 Docker Volume
도커 볼륨이랑 호스트 머신과의 공유는 어떨때 구분해서 써야할지 간단하게 정리해 보았다.
Host machine
- Docker Container과 config filed을 공유할 때
- Dev Container를 구성하여 사용하는 경우, 호스트와 컨테이너 간의 소스코드 연동을 위해서 사용
- 디렉토리 구조가 일정하게 잡혀있는 것이 보장되어야 하는 경우
Docker Volume
- 디렉토리 구조가 일정하게 잡혀있지 않아도 되는 경우
- 도커 컨테이너 자체적인 운용만으로도 괜찮으며, 원격 혹은 클라우드 호스트에 저장할때 적합
결론
미루고 미뤄왔던 Docker Volume에 대한 정리가 이제야 끝났다. 처음에 mysql 컨테이너를 생성할 때 생성은 잘 되는데 제대로 실행이 안 돼서 좀 헤맸는데 어찌저찌 자료를 찾아가며 해결해봤다.
아직 정확히 이해했다고 하긴 어렵긴 하지만 스퍼트 프로젝트 기간이 진짜 얼마 남지 않았기 때문에 빨리 빨리 도커라이징을 진행해야지!
'StudyNote' 카테고리의 다른 글
Mac OS 자바 버전 여러 개 관리하기 (0) | 2024.02.14 |
---|---|
Express.js를 사용한 스퍼트 프로젝트 (2) | 2024.02.08 |
간단한 Express 프로젝트 Dockerizing 해보기 (1) | 2024.02.01 |
도커(Docker) 가볍게 입문해보기 - 3 (1) | 2024.01.27 |
도커(Docker) 가볍게 입문해보기 - 2 (3) | 2024.01.26 |